33
33
34
34
use infer:: { InferCtxt , RegionVariableOrigin , TypeVariableOrigin } ;
35
35
use rustc_data_structures:: indexed_vec:: IndexVec ;
36
- use smallvec:: SmallVec ;
37
36
use rustc_data_structures:: sync:: Lrc ;
38
37
use serialize:: UseSpecializedDecodable ;
38
+ use smallvec:: SmallVec ;
39
39
use std:: ops:: Index ;
40
40
use syntax:: source_map:: Span ;
41
41
use ty:: fold:: TypeFoldable ;
42
42
use ty:: subst:: Kind ;
43
- use ty:: { self , BoundTyIndex , Lift , Region , List , TyCtxt } ;
43
+ use ty:: { self , BoundTyIndex , Lift , List , Region , TyCtxt } ;
44
44
45
45
mod canonicalizer;
46
46
@@ -80,13 +80,31 @@ pub struct CanonicalVarValues<'tcx> {
80
80
/// various parts of it with canonical variables. This struct stores
81
81
/// those replaced bits to remember for when we process the query
82
82
/// result.
83
- #[ derive( Clone , Debug , Default , PartialEq , Eq , Hash , RustcDecodable , RustcEncodable ) ]
83
+ #[ derive( Clone , Debug , PartialEq , Eq , Hash , RustcDecodable , RustcEncodable ) ]
84
84
pub struct OriginalQueryValues < ' tcx > {
85
+ /// Map from the universes that appear in the query to the
86
+ /// universes in the caller context. For the time being, we only
87
+ /// ever put ROOT values into the query, so this map is very
88
+ /// simple.
89
+ pub universe_map : SmallVec < [ ty:: UniverseIndex ; 4 ] > ,
90
+
85
91
/// This is equivalent to `CanonicalVarValues`, but using a
86
92
/// `SmallVec` yields a significant performance win.
87
93
pub var_values : SmallVec < [ Kind < ' tcx > ; 8 ] > ,
88
94
}
89
95
96
+ impl Default for OriginalQueryValues < ' tcx > {
97
+ fn default ( ) -> Self {
98
+ let mut universe_map = SmallVec :: default ( ) ;
99
+ universe_map. push ( ty:: UniverseIndex :: ROOT ) ;
100
+
101
+ Self {
102
+ universe_map,
103
+ var_values : SmallVec :: default ( ) ,
104
+ }
105
+ }
106
+ }
107
+
90
108
/// Information about a canonical variable that is included with the
91
109
/// canonical value. This is sufficient information for code to create
92
110
/// a copy of the canonical value in some other inference context,
@@ -97,9 +115,17 @@ pub struct CanonicalVarInfo {
97
115
}
98
116
99
117
impl CanonicalVarInfo {
100
- pub fn universe ( self ) -> ty:: UniverseIndex {
118
+ pub fn universe ( & self ) -> ty:: UniverseIndex {
101
119
self . kind . universe ( )
102
120
}
121
+
122
+ pub fn is_existential ( & self ) -> bool {
123
+ match self . kind {
124
+ CanonicalVarKind :: Ty ( _) => true ,
125
+ CanonicalVarKind :: Region ( _) => true ,
126
+ CanonicalVarKind :: PlaceholderRegion ( ..) => false ,
127
+ }
128
+ }
103
129
}
104
130
105
131
/// Describes the "kind" of the canonical variable. This is a "kind"
@@ -112,8 +138,12 @@ pub enum CanonicalVarKind {
112
138
113
139
/// Region variable `'?R`.
114
140
Region ( ty:: UniverseIndex ) ,
115
- }
116
141
142
+ /// A "placeholder" that represents "any region". Created when you
143
+ /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
144
+ /// bound region `'a`.
145
+ PlaceholderRegion ( ty:: Placeholder ) ,
146
+ }
117
147
118
148
impl CanonicalVarKind {
119
149
pub fn universe ( self ) -> ty:: UniverseIndex {
@@ -125,6 +155,7 @@ impl CanonicalVarKind {
125
155
126
156
// Region variables can be created in sub-universes.
127
157
CanonicalVarKind :: Region ( ui) => ui,
158
+ CanonicalVarKind :: PlaceholderRegion ( placeholder) => placeholder. universe ,
128
159
}
129
160
}
130
161
}
@@ -242,8 +273,16 @@ impl<'gcx, V> Canonical<'gcx, V> {
242
273
/// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
243
274
/// ```
244
275
pub fn unchecked_map < W > ( self , map_op : impl FnOnce ( V ) -> W ) -> Canonical < ' gcx , W > {
245
- let Canonical { max_universe, variables, value } = self ;
246
- Canonical { max_universe, variables, value : map_op ( value) }
276
+ let Canonical {
277
+ max_universe,
278
+ variables,
279
+ value,
280
+ } = self ;
281
+ Canonical {
282
+ max_universe,
283
+ variables,
284
+ value : map_op ( value) ,
285
+ }
247
286
}
248
287
}
249
288
@@ -271,35 +310,50 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
271
310
where
272
311
T : TypeFoldable < ' tcx > ,
273
312
{
313
+ // For each universe that is referred to in the incoming
314
+ // query, create a universe in our local inference context. In
315
+ // practice, as of this writing, all queries have no universes
316
+ // in them, so this code has no effect, but it is looking
317
+ // forward to the day when we *do* want to carry universes
318
+ // through into queries.
319
+ let universes: IndexVec < ty:: UniverseIndex , _ > = std:: iter:: once ( ty:: UniverseIndex :: ROOT )
320
+ . chain ( ( 0 ..canonical. max_universe . as_u32 ( ) ) . map ( |_| self . create_next_universe ( ) ) )
321
+ . collect ( ) ;
322
+
274
323
let canonical_inference_vars =
275
- self . fresh_inference_vars_for_canonical_vars ( span, canonical. variables ) ;
324
+ self . instantiate_canonical_vars ( span, canonical. variables , |ui| universes [ ui ] ) ;
276
325
let result = canonical. substitute ( self . tcx , & canonical_inference_vars) ;
277
326
( result, canonical_inference_vars)
278
327
}
279
328
280
329
/// Given the "infos" about the canonical variables from some
281
- /// canonical, creates fresh inference variables with the same
282
- /// characteristics. You can then use `substitute` to instantiate
283
- /// the canonical variable with these inference variables.
284
- fn fresh_inference_vars_for_canonical_vars (
330
+ /// canonical, creates fresh variables with the same
331
+ /// characteristics (see `instantiate_canonical_var` for
332
+ /// details). You can then use `substitute` to instantiate the
333
+ /// canonical variable with these inference variables.
334
+ fn instantiate_canonical_vars (
285
335
& self ,
286
336
span : Span ,
287
337
variables : & List < CanonicalVarInfo > ,
338
+ universe_map : impl Fn ( ty:: UniverseIndex ) -> ty:: UniverseIndex ,
288
339
) -> CanonicalVarValues < ' tcx > {
289
340
let var_values: IndexVec < BoundTyIndex , Kind < ' tcx > > = variables
290
341
. iter ( )
291
- . map ( |info| self . fresh_inference_var_for_canonical_var ( span, * info) )
342
+ . map ( |info| self . instantiate_canonical_var ( span, * info, & universe_map ) )
292
343
. collect ( ) ;
293
344
294
345
CanonicalVarValues { var_values }
295
346
}
296
347
297
348
/// Given the "info" about a canonical variable, creates a fresh
298
- /// inference variable with the same characteristics.
299
- fn fresh_inference_var_for_canonical_var (
349
+ /// variable for it. If this is an existentially quantified
350
+ /// variable, then you'll get a new inference variable; if it is a
351
+ /// universally quantified variable, you get a placeholder.
352
+ fn instantiate_canonical_var (
300
353
& self ,
301
354
span : Span ,
302
355
cv_info : CanonicalVarInfo ,
356
+ universe_map : impl Fn ( ty:: UniverseIndex ) -> ty:: UniverseIndex ,
303
357
) -> Kind < ' tcx > {
304
358
match cv_info. kind {
305
359
CanonicalVarKind :: Ty ( ty_kind) => {
@@ -315,9 +369,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
315
369
ty. into ( )
316
370
}
317
371
318
- CanonicalVarKind :: Region ( ui) => self
319
- . next_region_var_in_universe ( RegionVariableOrigin :: MiscVariable ( span) , ui)
320
- . into ( ) ,
372
+ CanonicalVarKind :: Region ( ui) => self . next_region_var_in_universe (
373
+ RegionVariableOrigin :: MiscVariable ( span) ,
374
+ universe_map ( ui) ,
375
+ ) . into ( ) ,
376
+
377
+ CanonicalVarKind :: PlaceholderRegion ( ty:: Placeholder { universe, name } ) => {
378
+ let universe_mapped = universe_map ( universe) ;
379
+ let placeholder_mapped = ty:: Placeholder {
380
+ universe : universe_mapped,
381
+ name,
382
+ } ;
383
+ self . tcx
384
+ . mk_region ( ty:: RePlaceholder ( placeholder_mapped) )
385
+ . into ( )
386
+ }
321
387
}
322
388
}
323
389
}
0 commit comments