@@ -107,6 +107,20 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
107107 )
108108 }
109109
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+
110124 /// A hacky variant of `canonicalize_query` that does not
111125 /// canonicalize `'static`. Unfortunately, the existing leak
112126 /// check treaks `'static` differently in some cases (see also
@@ -162,11 +176,26 @@ struct CanonicalizeQueryResponse;
162176impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
163177 fn canonicalize_free_region (
164178 & self ,
165- _canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
179+ canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
166180 r : ty:: Region < ' tcx > ,
167181 ) -> ty:: Region < ' tcx > {
168182 match r {
169183 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+ }
170199 _ => {
171200 // Other than `'static` or `'empty`, the query
172201 // response should be executing in a fully
@@ -182,6 +211,29 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
182211 }
183212}
184213
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+
185237struct CanonicalizeAllFreeRegions ;
186238
187239impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
@@ -190,7 +242,7 @@ impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
190242 canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
191243 r : ty:: Region < ' tcx > ,
192244 ) -> ty:: Region < ' tcx > {
193- canonicalizer. canonical_var_for_region ( r)
245+ canonicalizer. canonical_var_for_region_in_root_universe ( r)
194246 }
195247
196248 fn any ( & self ) -> bool {
@@ -209,7 +261,7 @@ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
209261 if let ty:: ReStatic = r {
210262 r
211263 } else {
212- canonicalizer. canonical_var_for_region ( r)
264+ canonicalizer. canonical_var_for_region_in_root_universe ( r)
213265 }
214266 }
215267
@@ -252,7 +304,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
252304 opportunistically resolved to {:?}",
253305 vid, r
254306 ) ;
255- self . canonical_var_for_region ( r)
307+ self . canonicalize_region_mode
308+ . canonicalize_free_region ( self , r)
256309 }
257310
258311 ty:: ReStatic
@@ -261,7 +314,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
261314 | ty:: ReScope ( _)
262315 | ty:: RePlaceholder ( ..)
263316 | 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) ,
265319
266320 ty:: ReClosureBound ( ..) | ty:: ReCanonical ( _) => {
267321 bug ! ( "canonical region encountered during canonicalization" )
@@ -353,6 +407,7 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
353407 if !value. has_type_flags ( needs_canonical_flags) {
354408 let out_value = gcx. lift ( value) . unwrap ( ) ;
355409 let canon_value = Canonical {
410+ max_universe : ty:: UniverseIndex :: ROOT ,
356411 variables : List :: empty ( ) ,
357412 value : out_value,
358413 } ;
@@ -383,7 +438,14 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
383438
384439 let canonical_variables = tcx. intern_canonical_var_infos ( & canonicalizer. variables ) ;
385440
441+ let max_universe = canonical_variables
442+ . iter ( )
443+ . map ( |cvar| cvar. universe ( ) )
444+ . max ( )
445+ . unwrap_or ( ty:: UniverseIndex :: ROOT ) ;
446+
386447 Canonical {
448+ max_universe,
387449 variables : canonical_variables,
388450 value : out_value,
389451 }
@@ -450,10 +512,46 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
450512 }
451513 }
452514
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 > {
457555 let b = self . canonical_var ( info, r. into ( ) ) ;
458556 debug_assert_eq ! ( ty:: INNERMOST , b. level) ;
459557 self . tcx ( ) . mk_region ( ty:: ReCanonical ( b. var ) )
0 commit comments