@@ -249,6 +249,8 @@ enum Scope<'a> {
249249 /// requires binders of nested trait refs to be merged.
250250 from_poly_trait_ref : bool ,
251251
252+ binder_depth : u32 ,
253+
252254 /// The late bound vars for a given item are stored by `HirId` to be
253255 /// queried later. However, if we enter an elision scope, we have to
254256 /// later append the elided bound vars to the list and need to know what
@@ -345,6 +347,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
345347 track_lifetime_uses,
346348 opaque_type_parent,
347349 from_poly_trait_ref,
350+ binder_depth,
348351 hir_id,
349352 s : _,
350353 } => f
@@ -354,6 +357,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
354357 . field ( "track_lifetime_uses" , track_lifetime_uses)
355358 . field ( "opaque_type_parent" , opaque_type_parent)
356359 . field ( "from_poly_trait_ref" , from_poly_trait_ref)
360+ . field ( "binder_depth" , binder_depth)
357361 . field ( "hir_id" , hir_id)
358362 . field ( "s" , & ".." )
359363 . finish ( ) ,
@@ -618,6 +622,45 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::
618622 }
619623}
620624
625+ impl < ' a , ' tcx > LifetimeContext < ' a , ' tcx > {
626+ fn depth ( & self , concanetate : bool ) -> u32 {
627+ let mut passed_boundary = false ;
628+ let mut scope = self . scope ;
629+ loop {
630+ match * scope {
631+ Scope :: Root => {
632+ break 0 ;
633+ }
634+
635+ Scope :: TraitRefBoundary { s, .. } => {
636+ passed_boundary = true ;
637+ scope = s;
638+ }
639+
640+ Scope :: Binder { binder_depth, from_poly_trait_ref, .. } => {
641+ break if concanetate {
642+ if passed_boundary || !from_poly_trait_ref {
643+ binder_depth + 1
644+ } else {
645+ binder_depth
646+ }
647+ } else {
648+ binder_depth + 1
649+ } ;
650+ }
651+
652+ Scope :: Elision { s, .. }
653+ | Scope :: ObjectLifetimeDefault { s, .. }
654+ | Scope :: TraitRefHackInner { s, .. }
655+ | Scope :: Supertrait { s, .. }
656+ | Scope :: Body { s, .. } => {
657+ scope = s;
658+ }
659+ }
660+ }
661+ }
662+ }
663+
621664impl < ' a , ' tcx > Visitor < ' tcx > for LifetimeContext < ' a , ' tcx > {
622665 type Map = Map < ' tcx > ;
623666
@@ -676,6 +719,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
676719 track_lifetime_uses : true ,
677720 opaque_type_parent : false ,
678721 from_poly_trait_ref : false ,
722+ binder_depth : self . depth ( false ) ,
679723 } ;
680724 self . with ( scope, move |_old_scope, this| {
681725 intravisit:: walk_fn ( this, fk, fd, b, s, hir_id)
@@ -801,6 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
801845 opaque_type_parent : true ,
802846 track_lifetime_uses,
803847 from_poly_trait_ref : false ,
848+ binder_depth : self . depth ( false ) ,
804849 s : ROOT_SCOPE ,
805850 } ;
806851 self . with ( scope, |old_scope, this| {
@@ -870,6 +915,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
870915 track_lifetime_uses : true ,
871916 opaque_type_parent : false ,
872917 from_poly_trait_ref : false ,
918+ binder_depth : self . depth ( false ) ,
873919 } ;
874920 self . with ( scope, |old_scope, this| {
875921 // a bare fn has no bounds, so everything
@@ -1063,6 +1109,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10631109 track_lifetime_uses : true ,
10641110 opaque_type_parent : false ,
10651111 from_poly_trait_ref : false ,
1112+ binder_depth : this. depth ( false ) ,
10661113 } ;
10671114 this. with ( scope, |_old_scope, this| {
10681115 this. visit_generics ( generics) ;
@@ -1083,6 +1130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10831130 track_lifetime_uses : true ,
10841131 opaque_type_parent : false ,
10851132 from_poly_trait_ref : false ,
1133+ binder_depth : self . depth ( false ) ,
10861134 } ;
10871135 self . with ( scope, |_old_scope, this| {
10881136 let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -1142,6 +1190,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
11421190 track_lifetime_uses : true ,
11431191 opaque_type_parent : true ,
11441192 from_poly_trait_ref : false ,
1193+ binder_depth : self . depth ( false ) ,
11451194 } ;
11461195 self . with ( scope, |old_scope, this| {
11471196 this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -1211,6 +1260,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
12111260 track_lifetime_uses : true ,
12121261 opaque_type_parent : true ,
12131262 from_poly_trait_ref : false ,
1263+ binder_depth : self . depth ( false ) ,
12141264 } ;
12151265 self . with ( scope, |old_scope, this| {
12161266 this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -1324,6 +1374,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
13241374 track_lifetime_uses : true ,
13251375 opaque_type_parent : false ,
13261376 from_poly_trait_ref : true ,
1377+ binder_depth : this. depth ( false ) ,
13271378 } ;
13281379 this. with ( scope, |old_scope, this| {
13291380 this. check_lifetime_params ( old_scope, & bound_generic_params) ;
@@ -1370,6 +1421,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
13701421 track_lifetime_uses : true ,
13711422 opaque_type_parent : false ,
13721423 from_poly_trait_ref : false ,
1424+ binder_depth : self . depth ( false ) ,
13731425 } ;
13741426 self . with ( scope, |_, this| {
13751427 intravisit:: walk_param_bound ( this, bound) ;
@@ -1516,6 +1568,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
15161568 track_lifetime_uses : true ,
15171569 opaque_type_parent : false ,
15181570 from_poly_trait_ref : true ,
1571+ binder_depth : self . depth ( true ) ,
15191572 } ;
15201573 self . with ( scope, |old_scope, this| {
15211574 this. check_lifetime_params ( old_scope, & trait_ref. bound_generic_params ) ;
@@ -2266,6 +2319,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
22662319 opaque_type_parent : true ,
22672320 track_lifetime_uses : false ,
22682321 from_poly_trait_ref : false ,
2322+ binder_depth : self . depth ( false ) ,
22692323 } ;
22702324 self . with ( scope, move |old_scope, this| {
22712325 this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -2323,7 +2377,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23232377 // given name or we run out of scopes.
23242378 // search.
23252379 let mut late_depth = 0 ;
2326- let mut in_poly_trait_ref = false ;
2380+ let mut first_binder_depth = None ;
23272381 let mut scope = self . scope ;
23282382 let mut outermost_body = None ;
23292383 let result = loop {
@@ -2341,25 +2395,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23412395 break None ;
23422396 }
23432397
2344- Scope :: TraitRefBoundary { s, .. } => {
2345- // We've exited nested poly trait refs; mark that we are no longer in nested trait refs.
2346- // We don't increase the late depth because this isn't a `Binder` scope.
2347- //
2348- // This came up in #83737, which boiled down to a case like this:
2349- //
2350- // ```
2351- // F: for<> Fn(&()) -> Box<dyn for<> Future<Output = ()> + Unpin>,
2352- // // ^^^^^
2353-
2354- // ```
2355- //
2356- // Here, as we traverse upwards from the `dyn for<>` binder, we want to reset `in_poly_trait_ref`
2357- // to false, so that we avoid excess contaenation when we encounter the outer `for<>` binder.
2358- in_poly_trait_ref = false ;
2359- scope = s;
2360- }
2361-
2362- Scope :: Binder { ref lifetimes, from_poly_trait_ref, s, .. } => {
2398+ Scope :: Binder { ref lifetimes, s, binder_depth, .. } => {
23632399 match lifetime_ref. name {
23642400 LifetimeName :: Param ( param_name) => {
23652401 if let Some ( & def) = lifetimes. get ( & param_name. normalize_to_macros_2_0 ( ) )
@@ -2369,47 +2405,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23692405 }
23702406 _ => bug ! ( "expected LifetimeName::Param" ) ,
23712407 }
2372-
2373- match ( from_poly_trait_ref, in_poly_trait_ref) {
2374- // This is the first binder we see that is a poly trait ref; add one to the
2375- // late depth and mark that we're potentially in nested trait refs.
2376- ( true , false ) => {
2377- in_poly_trait_ref = true ;
2378- late_depth += 1 ;
2379- }
2380- // We've already seen a binder that is a poly trait ref and this one is too,
2381- // that means that they are nested and we are concatenating the bound vars;
2382- // don't increase the late depth.
2383- //
2384- // This happens specifically with associated trait bounds like the following:
2385- //
2386- // ```
2387- // for<'a> T: Iterator<Item: for<'b> Foo<'a, 'b>>
2388- // ```
2389- //
2390- // In this case, as we traverse `for<'b>`, we would increment `late_depth` but
2391- // set `in_poly_trait_ref` to true. Then when we traverse `for<'a>`, we would
2392- // not increment `late_depth` again. (NB: Niko thinks this logic is actually
2393- // wrong.)
2394- ( true , true ) => { }
2395- // We've exited nested poly trait refs; add one to the late depth and mark
2396- // that we are no longer in nested trait refs
2397- ( false , true ) => {
2398- in_poly_trait_ref = false ;
2399- late_depth += 1 ;
2400- }
2401- // Any other kind of nested binders: just increase late depth.
2402- ( false , false ) => {
2403- late_depth += 1 ;
2404- }
2405- }
2408+ first_binder_depth = first_binder_depth. or ( Some ( binder_depth) ) ;
2409+ late_depth = first_binder_depth. unwrap_or ( binder_depth) - binder_depth + 1 ;
24062410 scope = s;
24072411 }
24082412
24092413 Scope :: Elision { s, .. }
24102414 | Scope :: ObjectLifetimeDefault { s, .. }
24112415 | Scope :: TraitRefHackInner { s, .. }
2412- | Scope :: Supertrait { s, .. } => {
2416+ | Scope :: Supertrait { s, .. }
2417+ | Scope :: TraitRefBoundary { s, .. } => {
24132418 scope = s;
24142419 }
24152420 }
@@ -3112,7 +3117,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
31123117
31133118 let span = lifetime_refs[ 0 ] . span ;
31143119 let mut late_depth = 0 ;
3115- let mut in_poly_trait_ref = false ;
3120+ let mut first_binder_depth = None ;
31163121 let mut scope = self . scope ;
31173122 let mut lifetime_names = FxHashSet :: default ( ) ;
31183123 let mut lifetime_spans = vec ! [ ] ;
@@ -3123,36 +3128,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
31233128
31243129 Scope :: Root => break None ,
31253130
3126- Scope :: TraitRefBoundary { s, .. } => {
3127- // We've exited nested poly trait refs; mark that we are no longer in nested trait refs.
3128- // We don't increase the late depth because this isn't a `Binder` scope
3129- in_poly_trait_ref = false ;
3130- scope = s;
3131- }
3132-
3133- Scope :: Binder { s, ref lifetimes, from_poly_trait_ref, .. } => {
3131+ Scope :: Binder { s, ref lifetimes, binder_depth, .. } => {
31343132 // collect named lifetimes for suggestions
31353133 for name in lifetimes. keys ( ) {
31363134 if let hir:: ParamName :: Plain ( name) = name {
31373135 lifetime_names. insert ( name. name ) ;
31383136 lifetime_spans. push ( name. span ) ;
31393137 }
31403138 }
3141- // See comments in `resolve_lifetime_ref`
3142- match ( from_poly_trait_ref, in_poly_trait_ref) {
3143- ( true , false ) => {
3144- in_poly_trait_ref = true ;
3145- late_depth += 1 ;
3146- }
3147- ( true , true ) => { }
3148- ( false , true ) => {
3149- in_poly_trait_ref = false ;
3150- late_depth += 1 ;
3151- }
3152- ( false , false ) => {
3153- late_depth += 1 ;
3154- }
3155- }
3139+ first_binder_depth = first_binder_depth. or ( Some ( binder_depth) ) ;
3140+ late_depth = first_binder_depth. unwrap_or ( binder_depth) - binder_depth + 1 ;
31563141 scope = s;
31573142 }
31583143
@@ -3202,7 +3187,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
32023187
32033188 Scope :: ObjectLifetimeDefault { s, .. }
32043189 | Scope :: TraitRefHackInner { s, .. }
3205- | Scope :: Supertrait { s, .. } => {
3190+ | Scope :: Supertrait { s, .. }
3191+ | Scope :: TraitRefBoundary { s, .. } => {
32063192 scope = s;
32073193 }
32083194 }
@@ -3308,32 +3294,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
33083294 fn resolve_object_lifetime_default ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
33093295 debug ! ( "resolve_object_lifetime_default(lifetime_ref={:?})" , lifetime_ref) ;
33103296 let mut late_depth = 0 ;
3311- let mut in_poly_trait_ref = false ;
3297+ let mut first_binder_depth = None ;
33123298 let mut scope = self . scope ;
33133299 let lifetime = loop {
33143300 match * scope {
3315- Scope :: TraitRefBoundary { s, .. } => {
3316- // We've exited nested poly trait refs; mark that we are no longer in nested trait refs.
3317- // We don't increase the late depth because this isn't a `Binder` scope
3318- in_poly_trait_ref = false ;
3319- scope = s;
3320- }
3321-
3322- Scope :: Binder { s, from_poly_trait_ref, .. } => {
3323- match ( from_poly_trait_ref, in_poly_trait_ref) {
3324- ( true , false ) => {
3325- in_poly_trait_ref = true ;
3326- late_depth += 1 ;
3327- }
3328- ( true , true ) => { }
3329- ( false , true ) => {
3330- in_poly_trait_ref = false ;
3331- late_depth += 1 ;
3332- }
3333- ( false , false ) => {
3334- late_depth += 1 ;
3335- }
3336- }
3301+ Scope :: Binder { s, binder_depth, .. } => {
3302+ first_binder_depth = first_binder_depth. or ( Some ( binder_depth) ) ;
3303+ late_depth = first_binder_depth. unwrap_or ( binder_depth) - binder_depth + 1 ;
33373304 scope = s;
33383305 }
33393306
@@ -3343,7 +3310,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
33433310
33443311 Scope :: ObjectLifetimeDefault { lifetime : Some ( l) , .. } => break l,
33453312
3346- Scope :: TraitRefHackInner { s, .. } | Scope :: Supertrait { s, .. } => {
3313+ Scope :: TraitRefHackInner { s, .. }
3314+ | Scope :: Supertrait { s, .. }
3315+ | Scope :: TraitRefBoundary { s, .. } => {
33473316 scope = s;
33483317 }
33493318 }
0 commit comments