@@ -12,7 +12,9 @@ use crate::data_structures::SsoHashSet;
12
12
use crate :: fold:: { FallibleTypeFolder , TypeFoldable , TypeFolder , TypeSuperFoldable } ;
13
13
use crate :: inherent:: * ;
14
14
use crate :: lift:: Lift ;
15
- use crate :: visit:: { Flags , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor } ;
15
+ use crate :: visit:: {
16
+ Flags , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor , try_visit,
17
+ } ;
16
18
use crate :: { self as ty, Interner } ;
17
19
18
20
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
@@ -34,6 +36,7 @@ use crate::{self as ty, Interner};
34
36
pub struct Binder < I : Interner , T > {
35
37
value : T ,
36
38
bound_vars : I :: BoundVarKinds ,
39
+ clauses : I :: Clauses ,
37
40
}
38
41
39
42
// FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
@@ -42,13 +45,15 @@ impl<I: Interner, U: Interner, T> Lift<U> for Binder<I, T>
42
45
where
43
46
T : Lift < U > ,
44
47
I :: BoundVarKinds : Lift < U , Lifted = U :: BoundVarKinds > ,
48
+ I :: Clauses : Lift < U , Lifted = U :: Clauses > ,
45
49
{
46
50
type Lifted = Binder < U , T :: Lifted > ;
47
51
48
52
fn lift_to_interner ( self , cx : U ) -> Option < Self :: Lifted > {
49
53
Some ( Binder {
50
54
value : self . value . lift_to_interner ( cx) ?,
51
55
bound_vars : self . bound_vars . lift_to_interner ( cx) ?,
56
+ clauses : self . clauses . lift_to_interner ( cx) ?,
52
57
} )
53
58
}
54
59
}
@@ -106,15 +111,28 @@ where
106
111
!value. has_escaping_bound_vars( ) ,
107
112
"`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
108
113
) ;
109
- Binder { value, bound_vars : Default :: default ( ) }
114
+ Binder { value, bound_vars : Default :: default ( ) , clauses : I :: Clauses :: empty ( ) }
110
115
}
111
116
112
117
pub fn bind_with_vars ( value : T , bound_vars : I :: BoundVarKinds ) -> Binder < I , T > {
113
118
if cfg ! ( debug_assertions) {
114
119
let mut validator = ValidateBoundVars :: new ( bound_vars) ;
115
120
let _ = value. visit_with ( & mut validator) ;
116
121
}
117
- Binder { value, bound_vars }
122
+ Binder { value, bound_vars, clauses : I :: Clauses :: empty ( ) }
123
+ }
124
+
125
+ pub fn bind_with_vars_and_clauses (
126
+ value : T ,
127
+ bound_vars : I :: BoundVarKinds ,
128
+ clauses : I :: Clauses ,
129
+ ) -> Binder < I , T > {
130
+ if cfg ! ( debug_assertions) {
131
+ let mut validator = ValidateBoundVars :: new ( bound_vars) ;
132
+ value. visit_with ( & mut validator) ;
133
+ clauses. visit_with ( & mut validator) ;
134
+ }
135
+ Binder { bound_vars, value, clauses }
118
136
}
119
137
}
120
138
@@ -135,13 +153,18 @@ impl<I: Interner, T: TypeFoldable<I>> TypeSuperFoldable<I> for Binder<I, T> {
135
153
self ,
136
154
folder : & mut F ,
137
155
) -> Result < Self , F :: Error > {
138
- self . try_map_bound ( |ty| ty. try_fold_with ( folder) )
156
+ let Binder { bound_vars, value, clauses } = self ;
157
+ let clauses = clauses. try_fold_with ( folder) ?;
158
+ let value = value. try_fold_with ( folder) ?;
159
+ Ok ( Binder :: bind_with_vars_and_clauses ( value, bound_vars, clauses) )
139
160
}
140
161
}
141
162
142
163
impl < I : Interner , T : TypeVisitable < I > > TypeSuperVisitable < I > for Binder < I , T > {
143
164
fn super_visit_with < V : TypeVisitor < I > > ( & self , visitor : & mut V ) -> V :: Result {
144
- self . as_ref ( ) . skip_binder ( ) . visit_with ( visitor)
165
+ let ( value, clauses) = self . as_ref ( ) . skip_binder_with_clauses ( ) ;
166
+ try_visit ! ( clauses. visit_with( visitor) ) ;
167
+ value. visit_with ( visitor)
145
168
}
146
169
}
147
170
@@ -166,19 +189,23 @@ impl<I: Interner, T> Binder<I, T> {
166
189
self . value
167
190
}
168
191
192
+ pub fn skip_binder_with_clauses ( self ) -> ( T , I :: Clauses ) {
193
+ ( self . value , self . clauses )
194
+ }
195
+
169
196
pub fn bound_vars ( & self ) -> I :: BoundVarKinds {
170
197
self . bound_vars
171
198
}
172
199
173
200
pub fn as_ref ( & self ) -> Binder < I , & T > {
174
- Binder { value : & self . value , bound_vars : self . bound_vars }
201
+ Binder { value : & self . value , bound_vars : self . bound_vars , clauses : self . clauses }
175
202
}
176
203
177
204
pub fn as_deref ( & self ) -> Binder < I , & T :: Target >
178
205
where
179
206
T : Deref ,
180
207
{
181
- Binder { value : & self . value , bound_vars : self . bound_vars }
208
+ Binder { value : & self . value , bound_vars : self . bound_vars , clauses : self . clauses }
182
209
}
183
210
184
211
pub fn map_bound_ref < F , U : TypeVisitable < I > > ( & self , f : F ) -> Binder < I , U >
@@ -192,26 +219,39 @@ impl<I: Interner, T> Binder<I, T> {
192
219
where
193
220
F : FnOnce ( T ) -> U ,
194
221
{
195
- let Binder { value, bound_vars } = self ;
222
+ let Binder { value, bound_vars, clauses } = self ;
196
223
let value = f ( value) ;
197
224
if cfg ! ( debug_assertions) {
198
225
let mut validator = ValidateBoundVars :: new ( bound_vars) ;
199
226
let _ = value. visit_with ( & mut validator) ;
200
227
}
201
- Binder { value, bound_vars }
228
+ Binder { value, bound_vars, clauses }
229
+ }
230
+
231
+ pub fn map_clauses < F , U : TypeVisitable < I > > ( self , f : F ) -> Self
232
+ where
233
+ F : FnOnce ( I :: Clauses ) -> I :: Clauses ,
234
+ {
235
+ let Binder { value, bound_vars, clauses } = self ;
236
+ let clauses = f ( clauses) ;
237
+ if cfg ! ( debug_assertions) {
238
+ let mut validator = ValidateBoundVars :: new ( bound_vars) ;
239
+ clauses. visit_with ( & mut validator) ;
240
+ }
241
+ Binder { value, bound_vars, clauses }
202
242
}
203
243
204
244
pub fn try_map_bound < F , U : TypeVisitable < I > , E > ( self , f : F ) -> Result < Binder < I , U > , E >
205
245
where
206
246
F : FnOnce ( T ) -> Result < U , E > ,
207
247
{
208
- let Binder { value, bound_vars } = self ;
248
+ let Binder { value, bound_vars, clauses } = self ;
209
249
let value = f ( value) ?;
210
250
if cfg ! ( debug_assertions) {
211
251
let mut validator = ValidateBoundVars :: new ( bound_vars) ;
212
252
let _ = value. visit_with ( & mut validator) ;
213
253
}
214
- Ok ( Binder { value, bound_vars } )
254
+ Ok ( Binder { value, bound_vars, clauses } )
215
255
}
216
256
217
257
/// Wraps a `value` in a binder, using the same bound variables as the
@@ -227,7 +267,7 @@ impl<I: Interner, T> Binder<I, T> {
227
267
where
228
268
U : TypeVisitable < I > ,
229
269
{
230
- Binder :: bind_with_vars ( value, self . bound_vars )
270
+ Binder :: bind_with_vars_and_clauses ( value, self . bound_vars , self . clauses )
231
271
}
232
272
233
273
/// Unwraps and returns the value within, but only if it contains
@@ -245,21 +285,25 @@ impl<I: Interner, T> Binder<I, T> {
245
285
T : TypeVisitable < I > ,
246
286
{
247
287
// `self.value` is equivalent to `self.skip_binder()`
248
- if self . value . has_escaping_bound_vars ( ) { None } else { Some ( self . skip_binder ( ) ) }
288
+ if self . value . has_escaping_bound_vars ( ) && self . clauses . is_empty ( ) {
289
+ None
290
+ } else {
291
+ Some ( self . skip_binder ( ) )
292
+ }
249
293
}
250
294
}
251
295
252
296
impl < I : Interner , T > Binder < I , Option < T > > {
253
297
pub fn transpose ( self ) -> Option < Binder < I , T > > {
254
- let Binder { value, bound_vars } = self ;
255
- value. map ( |value| Binder { value, bound_vars } )
298
+ let Binder { value, bound_vars, clauses } = self ;
299
+ value. map ( |value| Binder { value, bound_vars, clauses } )
256
300
}
257
301
}
258
302
259
303
impl < I : Interner , T : IntoIterator > Binder < I , T > {
260
304
pub fn iter ( self ) -> impl Iterator < Item = Binder < I , T :: Item > > {
261
- let Binder { value, bound_vars } = self ;
262
- value. into_iter ( ) . map ( move |value| Binder { value, bound_vars } )
305
+ let Binder { value, bound_vars, clauses } = self ;
306
+ value. into_iter ( ) . map ( move |value| Binder { value, bound_vars, clauses } )
263
307
}
264
308
}
265
309
0 commit comments