@@ -107,6 +107,20 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
107
107
)
108
108
}
109
109
110
+ pub fn canonicalize_user_type_annotation < V > ( & self , value : & V ) -> Canonicalized < ' gcx , V >
111
+ where
112
+ V : TypeFoldable < ' tcx > + Lift < ' gcx > ,
113
+ {
114
+ let mut query_state = OriginalQueryValues :: default ( ) ;
115
+ Canonicalizer :: canonicalize (
116
+ value,
117
+ Some ( self ) ,
118
+ self . tcx ,
119
+ & CanonicalizeUserTypeAnnotation ,
120
+ & mut query_state,
121
+ )
122
+ }
123
+
110
124
/// A hacky variant of `canonicalize_query` that does not
111
125
/// canonicalize `'static`. Unfortunately, the existing leak
112
126
/// check treaks `'static` differently in some cases (see also
@@ -162,11 +176,26 @@ struct CanonicalizeQueryResponse;
162
176
impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
163
177
fn canonicalize_free_region (
164
178
& self ,
165
- _canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
179
+ canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
166
180
r : ty:: Region < ' tcx > ,
167
181
) -> ty:: Region < ' tcx > {
168
182
match r {
169
183
ty:: ReFree ( _) | ty:: ReEmpty | ty:: ReErased | ty:: ReStatic | ty:: ReEarlyBound ( ..) => r,
184
+ ty:: RePlaceholder ( placeholder) => canonicalizer. canonical_var_for_region (
185
+ CanonicalVarInfo {
186
+ kind : CanonicalVarKind :: PlaceholderRegion ( * placeholder) ,
187
+ } ,
188
+ r,
189
+ ) ,
190
+ ty:: ReVar ( vid) => {
191
+ let universe = canonicalizer. region_var_universe ( * vid) ;
192
+ canonicalizer. canonical_var_for_region (
193
+ CanonicalVarInfo {
194
+ kind : CanonicalVarKind :: Region ( universe) ,
195
+ } ,
196
+ r,
197
+ )
198
+ }
170
199
_ => {
171
200
// Other than `'static` or `'empty`, the query
172
201
// response should be executing in a fully
@@ -182,6 +211,29 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
182
211
}
183
212
}
184
213
214
+ struct CanonicalizeUserTypeAnnotation ;
215
+
216
+ impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation {
217
+ fn canonicalize_free_region (
218
+ & self ,
219
+ canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
220
+ r : ty:: Region < ' tcx > ,
221
+ ) -> ty:: Region < ' tcx > {
222
+ match r {
223
+ ty:: ReEarlyBound ( _) | ty:: ReFree ( _) | ty:: ReErased | ty:: ReEmpty | ty:: ReStatic => r,
224
+ ty:: ReVar ( _) => canonicalizer. canonical_var_for_region_in_root_universe ( r) ,
225
+ _ => {
226
+ // We only expect region names that the user can type.
227
+ bug ! ( "unexpected region in query response: `{:?}`" , r)
228
+ }
229
+ }
230
+ }
231
+
232
+ fn any ( & self ) -> bool {
233
+ false
234
+ }
235
+ }
236
+
185
237
struct CanonicalizeAllFreeRegions ;
186
238
187
239
impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
@@ -190,7 +242,7 @@ impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
190
242
canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
191
243
r : ty:: Region < ' tcx > ,
192
244
) -> ty:: Region < ' tcx > {
193
- canonicalizer. canonical_var_for_region ( r)
245
+ canonicalizer. canonical_var_for_region_in_root_universe ( r)
194
246
}
195
247
196
248
fn any ( & self ) -> bool {
@@ -209,7 +261,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
209
261
if let ty:: ReStatic = r {
210
262
r
211
263
} else {
212
- canonicalizer. canonical_var_for_region ( r)
264
+ canonicalizer. canonical_var_for_region_in_root_universe ( r)
213
265
}
214
266
}
215
267
@@ -252,7 +304,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
252
304
opportunistically resolved to {:?}",
253
305
vid, r
254
306
) ;
255
- self . canonical_var_for_region ( r)
307
+ self . canonicalize_region_mode
308
+ . canonicalize_free_region ( self , r)
256
309
}
257
310
258
311
ty:: ReStatic
@@ -261,7 +314,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
261
314
| ty:: ReScope ( _)
262
315
| ty:: RePlaceholder ( ..)
263
316
| ty:: ReEmpty
264
- | ty:: ReErased => self . canonicalize_region_mode . canonicalize_free_region ( self , r) ,
317
+ | ty:: ReErased => self . canonicalize_region_mode
318
+ . canonicalize_free_region ( self , r) ,
265
319
266
320
ty:: ReClosureBound ( ..) | ty:: ReCanonical ( _) => {
267
321
bug ! ( "canonical region encountered during canonicalization" )
@@ -353,6 +407,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
353
407
if !value. has_type_flags ( needs_canonical_flags) {
354
408
let out_value = gcx. lift ( value) . unwrap ( ) ;
355
409
let canon_value = Canonical {
410
+ max_universe : ty:: UniverseIndex :: ROOT ,
356
411
variables : List :: empty ( ) ,
357
412
value : out_value,
358
413
} ;
@@ -383,7 +438,14 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
383
438
384
439
let canonical_variables = tcx. intern_canonical_var_infos ( & canonicalizer. variables ) ;
385
440
441
+ let max_universe = canonical_variables
442
+ . iter ( )
443
+ . map ( |cvar| cvar. universe ( ) )
444
+ . max ( )
445
+ . unwrap_or ( ty:: UniverseIndex :: ROOT ) ;
446
+
386
447
Canonical {
448
+ max_universe,
387
449
variables : canonical_variables,
388
450
value : out_value,
389
451
}
@@ -450,10 +512,46 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
450
512
}
451
513
}
452
514
453
- fn canonical_var_for_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
454
- let info = CanonicalVarInfo {
455
- kind : CanonicalVarKind :: Region ,
456
- } ;
515
+ /// Shorthand helper that creates a canonical region variable for
516
+ /// `r` (always in the root universe). The reason that we always
517
+ /// put these variables into the root universe is because this
518
+ /// method is used during **query construction:** in that case, we
519
+ /// are taking all the regions and just putting them into the most
520
+ /// generic context we can. This may generate solutions that don't
521
+ /// fit (e.g., that equate some region variable with a placeholder
522
+ /// it can't name) on the caller side, but that's ok, the caller
523
+ /// can figure that out. In the meantime, it maximizes our
524
+ /// caching.
525
+ ///
526
+ /// (This works because unification never fails -- and hence trait
527
+ /// selection is never affected -- due to a universe mismatch.)
528
+ fn canonical_var_for_region_in_root_universe (
529
+ & mut self ,
530
+ r : ty:: Region < ' tcx > ,
531
+ ) -> ty:: Region < ' tcx > {
532
+ self . canonical_var_for_region (
533
+ CanonicalVarInfo {
534
+ kind : CanonicalVarKind :: Region ( ty:: UniverseIndex :: ROOT ) ,
535
+ } ,
536
+ r,
537
+ )
538
+ }
539
+
540
+ /// Returns the universe in which `vid` is defined.
541
+ fn region_var_universe ( & self , vid : ty:: RegionVid ) -> ty:: UniverseIndex {
542
+ self . infcx
543
+ . unwrap ( )
544
+ . borrow_region_constraints ( )
545
+ . var_universe ( vid)
546
+ }
547
+
548
+ /// Create a canonical variable (with the given `info`)
549
+ /// representing the region `r`; return a region referencing it.
550
+ fn canonical_var_for_region (
551
+ & mut self ,
552
+ info : CanonicalVarInfo ,
553
+ r : ty:: Region < ' tcx > ,
554
+ ) -> ty:: Region < ' tcx > {
457
555
let b = self . canonical_var ( info, r. into ( ) ) ;
458
556
debug_assert_eq ! ( ty:: INNERMOST , b. level) ;
459
557
self . tcx ( ) . mk_region ( ty:: ReCanonical ( b. var ) )
0 commit comments