@@ -167,14 +167,15 @@ pub fn implied_predicates<'tcx>(
167
167
}
168
168
}
169
169
170
- /// Erase all regions. Largely copied from `tcx.erase_regions`.
171
- pub fn erase_all_regions < ' tcx , T > ( tcx : TyCtxt < ' tcx > , value : T ) -> T
170
+ /// Erase all regions. Largely copied from `tcx.erase_regions`, but erases more regions .
171
+ fn erase_all_regions < ' tcx , T > ( tcx : TyCtxt < ' tcx > , value : T ) -> T
172
172
where
173
173
T : TypeFoldable < TyCtxt < ' tcx > > ,
174
174
{
175
175
use rustc_middle:: ty;
176
176
struct RegionEraserVisitor < ' tcx > {
177
177
tcx : TyCtxt < ' tcx > ,
178
+ depth : u32 ,
178
179
}
179
180
180
181
impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for RegionEraserVisitor < ' tcx > {
@@ -190,22 +191,27 @@ where
190
191
where
191
192
T : TypeFoldable < TyCtxt < ' tcx > > ,
192
193
{
193
- // Empty the binder
194
- Binder :: dummy ( t. skip_binder ( ) . fold_with ( self ) )
194
+ let t = self . tcx . anonymize_bound_vars ( t) ;
195
+ self . depth += 1 ;
196
+ let t = t. super_fold_with ( self ) ;
197
+ self . depth -= 1 ;
198
+ t
195
199
}
196
200
197
- fn fold_region ( & mut self , _r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
198
- // We erase bound regions despite it being possibly incorrect. `for<'a> fn(&'a
199
- // ())` and `fn(&'free ())` are different types: they may implement different
200
- // traits and have a different `TypeId`. It's unclear whether this can cause us
201
- // to select the wrong trait reference.
202
- self . tcx . lifetimes . re_erased
201
+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
202
+ // We don't erase bound regions that are bound inside the expression we started with,
203
+ // but we do erase those that point "outside of it".
204
+ match r. kind ( ) {
205
+ ty:: ReBound ( dbid, _) if dbid. as_u32 ( ) < self . depth => r,
206
+ _ => self . tcx . lifetimes . re_erased ,
207
+ }
203
208
}
204
209
}
205
- value. fold_with ( & mut RegionEraserVisitor { tcx } )
210
+ value. fold_with ( & mut RegionEraserVisitor { tcx, depth : 0 } )
206
211
}
207
212
208
- // Lifetimes are irrelevant when resolving instances.
213
+ // Normalize and erase lifetimes, erasing more lifetimes than normal because we might be already
214
+ // inside a binder and rustc doesn't like that.
209
215
pub fn erase_and_norm < ' tcx , T > ( tcx : TyCtxt < ' tcx > , typing_env : TypingEnv < ' tcx > , x : T ) -> T
210
216
where
211
217
T : TypeFoldable < TyCtxt < ' tcx > > + Copy ,
@@ -217,6 +223,21 @@ where
217
223
)
218
224
}
219
225
226
+ /// Given our currently hacky handling of binders, in order for trait resolution to work we must
227
+ /// empty out the binders of trait refs. Specifically it's so that we can reconnect associated type
228
+ /// constraints with the trait ref they come from, given that the projection in question doesn't
229
+ /// track the right binder currently.
230
+ pub fn normalize_bound_val < ' tcx , T > (
231
+ tcx : TyCtxt < ' tcx > ,
232
+ typing_env : TypingEnv < ' tcx > ,
233
+ x : Binder < ' tcx , T > ,
234
+ ) -> Binder < ' tcx , T >
235
+ where
236
+ T : TypeFoldable < TyCtxt < ' tcx > > + Copy ,
237
+ {
238
+ Binder :: dummy ( erase_and_norm ( tcx, typing_env, x. skip_binder ( ) ) )
239
+ }
240
+
220
241
pub trait ToPolyTraitRef < ' tcx > {
221
242
fn to_poly_trait_ref ( & self ) -> PolyTraitRef < ' tcx > ;
222
243
}
0 commit comments