@@ -167,14 +167,15 @@ pub fn implied_predicates<'tcx>(
167167 }
168168}
169169
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
172172where
173173 T : TypeFoldable < TyCtxt < ' tcx > > ,
174174{
175175 use rustc_middle:: ty;
176176 struct RegionEraserVisitor < ' tcx > {
177177 tcx : TyCtxt < ' tcx > ,
178+ depth : u32 ,
178179 }
179180
180181 impl < ' tcx > TypeFolder < TyCtxt < ' tcx > > for RegionEraserVisitor < ' tcx > {
@@ -190,22 +191,27 @@ where
190191 where
191192 T : TypeFoldable < TyCtxt < ' tcx > > ,
192193 {
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
195199 }
196200
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+ }
203208 }
204209 }
205- value. fold_with ( & mut RegionEraserVisitor { tcx } )
210+ value. fold_with ( & mut RegionEraserVisitor { tcx, depth : 0 } )
206211}
207212
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.
209215pub fn erase_and_norm < ' tcx , T > ( tcx : TyCtxt < ' tcx > , typing_env : TypingEnv < ' tcx > , x : T ) -> T
210216where
211217 T : TypeFoldable < TyCtxt < ' tcx > > + Copy ,
@@ -217,6 +223,21 @@ where
217223 )
218224}
219225
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+
220241pub trait ToPolyTraitRef < ' tcx > {
221242 fn to_poly_trait_ref ( & self ) -> PolyTraitRef < ' tcx > ;
222243}
0 commit comments