@@ -63,10 +63,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
63
63
value,
64
64
Some ( self ) ,
65
65
self . tcx ,
66
- CanonicalizeRegionMode {
67
- static_region : true ,
68
- other_free_regions : true ,
69
- } ,
66
+ & CanonicalizeAllFreeRegions ,
70
67
var_values,
71
68
)
72
69
}
@@ -105,10 +102,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
105
102
value,
106
103
Some ( self ) ,
107
104
self . tcx ,
108
- CanonicalizeRegionMode {
109
- static_region : false ,
110
- other_free_regions : false ,
111
- } ,
105
+ & CanonicalizeQueryResponse ,
112
106
& mut var_values,
113
107
)
114
108
}
@@ -140,27 +134,87 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
140
134
value,
141
135
Some ( self ) ,
142
136
self . tcx ,
143
- CanonicalizeRegionMode {
144
- static_region : false ,
145
- other_free_regions : true ,
146
- } ,
137
+ & CanonicalizeFreeRegionsOtherThanStatic ,
147
138
var_values,
148
139
)
149
140
}
150
141
}
151
142
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
+ }
159
199
}
160
200
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
+
162
216
fn any ( & self ) -> bool {
163
- self . static_region || self . other_free_regions
217
+ true
164
218
}
165
219
}
166
220
@@ -172,7 +226,7 @@ struct Canonicalizer<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
172
226
// Note that indices is only used once `var_values` is big enough to be
173
227
// heap-allocated.
174
228
indices : FxHashMap < Kind < ' tcx > , CanonicalVar > ,
175
- canonicalize_region_mode : CanonicalizeRegionMode ,
229
+ canonicalize_region_mode : & ' cx dyn CanonicalizeRegionMode ,
176
230
needs_canonical_flags : TypeFlags ,
177
231
}
178
232
@@ -201,26 +255,13 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
201
255
self . canonical_var_for_region ( r)
202
256
}
203
257
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 ( ..)
213
260
| ty:: ReFree ( _)
214
261
| ty:: ReScope ( _)
215
262
| ty:: RePlaceholder ( ..)
216
263
| 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) ,
224
265
225
266
ty:: ReClosureBound ( ..) | ty:: ReCanonical ( _) => {
226
267
bug ! ( "canonical region encountered during canonicalization" )
@@ -286,10 +327,10 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
286
327
/// `canonicalize_query` and `canonicalize_response`.
287
328
fn canonicalize < V > (
288
329
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 > ,
293
334
) -> Canonicalized < ' gcx , V >
294
335
where
295
336
V : TypeFoldable < ' tcx > + Lift < ' gcx > ,
0 commit comments