@@ -63,10 +63,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
6363 value,
6464 Some ( self ) ,
6565 self . tcx ,
66- CanonicalizeRegionMode {
67- static_region : true ,
68- other_free_regions : true ,
69- } ,
66+ & CanonicalizeAllFreeRegions ,
7067 var_values,
7168 )
7269 }
@@ -105,10 +102,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
105102 value,
106103 Some ( self ) ,
107104 self . tcx ,
108- CanonicalizeRegionMode {
109- static_region : false ,
110- other_free_regions : false ,
111- } ,
105+ & CanonicalizeQueryResponse ,
112106 & mut var_values,
113107 )
114108 }
@@ -140,27 +134,87 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
140134 value,
141135 Some ( self ) ,
142136 self . tcx ,
143- CanonicalizeRegionMode {
144- static_region : false ,
145- other_free_regions : true ,
146- } ,
137+ & CanonicalizeFreeRegionsOtherThanStatic ,
147138 var_values,
148139 )
149140 }
150141}
151142
152- /// If this flag is true, then all free regions will be replaced with
153- /// a canonical var. This is used to make queries as generic as
154- /// possible. For example, the query `F: Foo<'static>` would be
155- /// canonicalized to `F: Foo<'0>`.
156- struct CanonicalizeRegionMode {
157- static_region : bool ,
158- other_free_regions : bool ,
143+ /// Controls how we canonicalize "free regions" that are not inference
144+ /// variables. This depends on what we are canonicalizing *for* --
145+ /// e.g., if we are canonicalizing to create a query, we want to
146+ /// replace those with inference variables, since we want to make a
147+ /// maximally general query. But if we are canonicalizing a *query
148+ /// response*, then we don't typically replace free regions, as they
149+ /// must have been introduced from other parts of the system.
150+ trait CanonicalizeRegionMode {
151+ fn canonicalize_free_region (
152+ & self ,
153+ canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
154+ r : ty:: Region < ' tcx > ,
155+ ) -> ty:: Region < ' tcx > ;
156+
157+ fn any ( & self ) -> bool ;
158+ }
159+
160+ struct CanonicalizeQueryResponse ;
161+
162+ impl CanonicalizeRegionMode for CanonicalizeQueryResponse {
163+ fn canonicalize_free_region (
164+ & self ,
165+ _canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
166+ r : ty:: Region < ' tcx > ,
167+ ) -> ty:: Region < ' tcx > {
168+ match r {
169+ ty:: ReFree ( _) | ty:: ReEmpty | ty:: ReErased | ty:: ReStatic | ty:: ReEarlyBound ( ..) => r,
170+ _ => {
171+ // Other than `'static` or `'empty`, the query
172+ // response should be executing in a fully
173+ // canonicalized environment, so there shouldn't be
174+ // any other region names it can come up.
175+ bug ! ( "unexpected region in query response: `{:?}`" , r)
176+ }
177+ }
178+ }
179+
180+ fn any ( & self ) -> bool {
181+ false
182+ }
183+ }
184+
185+ struct CanonicalizeAllFreeRegions ;
186+
187+ impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions {
188+ fn canonicalize_free_region (
189+ & self ,
190+ canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
191+ r : ty:: Region < ' tcx > ,
192+ ) -> ty:: Region < ' tcx > {
193+ canonicalizer. canonical_var_for_region ( r)
194+ }
195+
196+ fn any ( & self ) -> bool {
197+ true
198+ }
159199}
160200
161- impl CanonicalizeRegionMode {
201+ struct CanonicalizeFreeRegionsOtherThanStatic ;
202+
203+ impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic {
204+ fn canonicalize_free_region (
205+ & self ,
206+ canonicalizer : & mut Canonicalizer < ' _ , ' _ , ' tcx > ,
207+ r : ty:: Region < ' tcx > ,
208+ ) -> ty:: Region < ' tcx > {
209+ if let ty:: ReStatic = r {
210+ r
211+ } else {
212+ canonicalizer. canonical_var_for_region ( r)
213+ }
214+ }
215+
162216 fn any ( & self ) -> bool {
163- self . static_region || self . other_free_regions
217+ true
164218 }
165219}
166220
@@ -172,7 +226,7 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
172226 // Note that indices is only used once `var_values` is big enough to be
173227 // heap-allocated.
174228 indices : FxHashMap < Kind < ' tcx > , CanonicalVar > ,
175- canonicalize_region_mode : CanonicalizeRegionMode ,
229+ canonicalize_region_mode : & ' cx dyn CanonicalizeRegionMode ,
176230 needs_canonical_flags : TypeFlags ,
177231}
178232
@@ -201,26 +255,13 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
201255 self . canonical_var_for_region ( r)
202256 }
203257
204- ty:: ReStatic => {
205- if self . canonicalize_region_mode . static_region {
206- self . canonical_var_for_region ( r)
207- } else {
208- r
209- }
210- }
211-
212- ty:: ReEarlyBound ( ..)
258+ ty:: ReStatic
259+ | ty:: ReEarlyBound ( ..)
213260 | ty:: ReFree ( _)
214261 | ty:: ReScope ( _)
215262 | ty:: RePlaceholder ( ..)
216263 | ty:: ReEmpty
217- | ty:: ReErased => {
218- if self . canonicalize_region_mode . other_free_regions {
219- self . canonical_var_for_region ( r)
220- } else {
221- r
222- }
223- }
264+ | ty:: ReErased => self . canonicalize_region_mode . canonicalize_free_region ( self , r) ,
224265
225266 ty:: ReClosureBound ( ..) | ty:: ReCanonical ( _) => {
226267 bug ! ( "canonical region encountered during canonicalization" )
@@ -286,10 +327,10 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
286327 /// `canonicalize_query` and `canonicalize_response`.
287328 fn canonicalize < V > (
288329 value : & V ,
289- infcx : Option < & ' cx InferCtxt < ' cx , ' gcx , ' tcx > > ,
290- tcx : TyCtxt < ' cx , ' gcx , ' tcx > ,
291- canonicalize_region_mode : CanonicalizeRegionMode ,
292- var_values : & ' cx mut SmallCanonicalVarValues < ' tcx > ,
330+ infcx : Option < & InferCtxt < ' _ , ' gcx , ' tcx > > ,
331+ tcx : TyCtxt < ' _ , ' gcx , ' tcx > ,
332+ canonicalize_region_mode : & dyn CanonicalizeRegionMode ,
333+ var_values : & mut SmallCanonicalVarValues < ' tcx > ,
293334 ) -> Canonicalized < ' gcx , V >
294335 where
295336 V : TypeFoldable < ' tcx > + Lift < ' gcx > ,
0 commit comments