@@ -249,6 +249,8 @@ enum Scope<'a> {
249
249
/// requires binders of nested trait refs to be merged.
250
250
from_poly_trait_ref : bool ,
251
251
252
+ binder_depth : u32 ,
253
+
252
254
/// The late bound vars for a given item are stored by `HirId` to be
253
255
/// queried later. However, if we enter an elision scope, we have to
254
256
/// 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> {
345
347
track_lifetime_uses,
346
348
opaque_type_parent,
347
349
from_poly_trait_ref,
350
+ binder_depth,
348
351
hir_id,
349
352
s : _,
350
353
} => f
@@ -354,6 +357,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
354
357
. field ( "track_lifetime_uses" , track_lifetime_uses)
355
358
. field ( "opaque_type_parent" , opaque_type_parent)
356
359
. field ( "from_poly_trait_ref" , from_poly_trait_ref)
360
+ . field ( "binder_depth" , binder_depth)
357
361
. field ( "hir_id" , hir_id)
358
362
. field ( "s" , & ".." )
359
363
. finish ( ) ,
@@ -618,6 +622,45 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::
618
622
}
619
623
}
620
624
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
+
621
664
impl < ' a , ' tcx > Visitor < ' tcx > for LifetimeContext < ' a , ' tcx > {
622
665
type Map = Map < ' tcx > ;
623
666
@@ -676,6 +719,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
676
719
track_lifetime_uses : true ,
677
720
opaque_type_parent : false ,
678
721
from_poly_trait_ref : false ,
722
+ binder_depth : self . depth ( false ) ,
679
723
} ;
680
724
self . with ( scope, move |_old_scope, this| {
681
725
intravisit:: walk_fn ( this, fk, fd, b, s, hir_id)
@@ -801,6 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
801
845
opaque_type_parent : true ,
802
846
track_lifetime_uses,
803
847
from_poly_trait_ref : false ,
848
+ binder_depth : self . depth ( false ) ,
804
849
s : ROOT_SCOPE ,
805
850
} ;
806
851
self . with ( scope, |old_scope, this| {
@@ -870,6 +915,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
870
915
track_lifetime_uses : true ,
871
916
opaque_type_parent : false ,
872
917
from_poly_trait_ref : false ,
918
+ binder_depth : self . depth ( false ) ,
873
919
} ;
874
920
self . with ( scope, |old_scope, this| {
875
921
// a bare fn has no bounds, so everything
@@ -1063,6 +1109,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1063
1109
track_lifetime_uses : true ,
1064
1110
opaque_type_parent : false ,
1065
1111
from_poly_trait_ref : false ,
1112
+ binder_depth : this. depth ( false ) ,
1066
1113
} ;
1067
1114
this. with ( scope, |_old_scope, this| {
1068
1115
this. visit_generics ( generics) ;
@@ -1083,6 +1130,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1083
1130
track_lifetime_uses : true ,
1084
1131
opaque_type_parent : false ,
1085
1132
from_poly_trait_ref : false ,
1133
+ binder_depth : self . depth ( false ) ,
1086
1134
} ;
1087
1135
self . with ( scope, |_old_scope, this| {
1088
1136
let scope = Scope :: TraitRefBoundary { s : this. scope } ;
@@ -1142,6 +1190,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1142
1190
track_lifetime_uses : true ,
1143
1191
opaque_type_parent : true ,
1144
1192
from_poly_trait_ref : false ,
1193
+ binder_depth : self . depth ( false ) ,
1145
1194
} ;
1146
1195
self . with ( scope, |old_scope, this| {
1147
1196
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -1211,6 +1260,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1211
1260
track_lifetime_uses : true ,
1212
1261
opaque_type_parent : true ,
1213
1262
from_poly_trait_ref : false ,
1263
+ binder_depth : self . depth ( false ) ,
1214
1264
} ;
1215
1265
self . with ( scope, |old_scope, this| {
1216
1266
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -1324,6 +1374,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1324
1374
track_lifetime_uses : true ,
1325
1375
opaque_type_parent : false ,
1326
1376
from_poly_trait_ref : true ,
1377
+ binder_depth : this. depth ( false ) ,
1327
1378
} ;
1328
1379
this. with ( scope, |old_scope, this| {
1329
1380
this. check_lifetime_params ( old_scope, & bound_generic_params) ;
@@ -1370,6 +1421,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1370
1421
track_lifetime_uses : true ,
1371
1422
opaque_type_parent : false ,
1372
1423
from_poly_trait_ref : false ,
1424
+ binder_depth : self . depth ( false ) ,
1373
1425
} ;
1374
1426
self . with ( scope, |_, this| {
1375
1427
intravisit:: walk_param_bound ( this, bound) ;
@@ -1516,6 +1568,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
1516
1568
track_lifetime_uses : true ,
1517
1569
opaque_type_parent : false ,
1518
1570
from_poly_trait_ref : true ,
1571
+ binder_depth : self . depth ( true ) ,
1519
1572
} ;
1520
1573
self . with ( scope, |old_scope, this| {
1521
1574
this. check_lifetime_params ( old_scope, & trait_ref. bound_generic_params ) ;
@@ -2266,6 +2319,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2266
2319
opaque_type_parent : true ,
2267
2320
track_lifetime_uses : false ,
2268
2321
from_poly_trait_ref : false ,
2322
+ binder_depth : self . depth ( false ) ,
2269
2323
} ;
2270
2324
self . with ( scope, move |old_scope, this| {
2271
2325
this. check_lifetime_params ( old_scope, & generics. params ) ;
@@ -2323,7 +2377,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2323
2377
// given name or we run out of scopes.
2324
2378
// search.
2325
2379
let mut late_depth = 0 ;
2326
- let mut in_poly_trait_ref = false ;
2380
+ let mut first_binder_depth = None ;
2327
2381
let mut scope = self . scope ;
2328
2382
let mut outermost_body = None ;
2329
2383
let result = loop {
@@ -2341,25 +2395,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2341
2395
break None ;
2342
2396
}
2343
2397
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, .. } => {
2363
2399
match lifetime_ref. name {
2364
2400
LifetimeName :: Param ( param_name) => {
2365
2401
if let Some ( & def) = lifetimes. get ( & param_name. normalize_to_macros_2_0 ( ) )
@@ -2369,47 +2405,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2369
2405
}
2370
2406
_ => bug ! ( "expected LifetimeName::Param" ) ,
2371
2407
}
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 ;
2406
2410
scope = s;
2407
2411
}
2408
2412
2409
2413
Scope :: Elision { s, .. }
2410
2414
| Scope :: ObjectLifetimeDefault { s, .. }
2411
2415
| Scope :: TraitRefHackInner { s, .. }
2412
- | Scope :: Supertrait { s, .. } => {
2416
+ | Scope :: Supertrait { s, .. }
2417
+ | Scope :: TraitRefBoundary { s, .. } => {
2413
2418
scope = s;
2414
2419
}
2415
2420
}
@@ -3112,7 +3117,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
3112
3117
3113
3118
let span = lifetime_refs[ 0 ] . span ;
3114
3119
let mut late_depth = 0 ;
3115
- let mut in_poly_trait_ref = false ;
3120
+ let mut first_binder_depth = None ;
3116
3121
let mut scope = self . scope ;
3117
3122
let mut lifetime_names = FxHashSet :: default ( ) ;
3118
3123
let mut lifetime_spans = vec ! [ ] ;
@@ -3123,36 +3128,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
3123
3128
3124
3129
Scope :: Root => break None ,
3125
3130
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, .. } => {
3134
3132
// collect named lifetimes for suggestions
3135
3133
for name in lifetimes. keys ( ) {
3136
3134
if let hir:: ParamName :: Plain ( name) = name {
3137
3135
lifetime_names. insert ( name. name ) ;
3138
3136
lifetime_spans. push ( name. span ) ;
3139
3137
}
3140
3138
}
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 ;
3156
3141
scope = s;
3157
3142
}
3158
3143
@@ -3202,7 +3187,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
3202
3187
3203
3188
Scope :: ObjectLifetimeDefault { s, .. }
3204
3189
| Scope :: TraitRefHackInner { s, .. }
3205
- | Scope :: Supertrait { s, .. } => {
3190
+ | Scope :: Supertrait { s, .. }
3191
+ | Scope :: TraitRefBoundary { s, .. } => {
3206
3192
scope = s;
3207
3193
}
3208
3194
}
@@ -3308,32 +3294,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
3308
3294
fn resolve_object_lifetime_default ( & mut self , lifetime_ref : & ' tcx hir:: Lifetime ) {
3309
3295
debug ! ( "resolve_object_lifetime_default(lifetime_ref={:?})" , lifetime_ref) ;
3310
3296
let mut late_depth = 0 ;
3311
- let mut in_poly_trait_ref = false ;
3297
+ let mut first_binder_depth = None ;
3312
3298
let mut scope = self . scope ;
3313
3299
let lifetime = loop {
3314
3300
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 ;
3337
3304
scope = s;
3338
3305
}
3339
3306
@@ -3343,7 +3310,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
3343
3310
3344
3311
Scope :: ObjectLifetimeDefault { lifetime : Some ( l) , .. } => break l,
3345
3312
3346
- Scope :: TraitRefHackInner { s, .. } | Scope :: Supertrait { s, .. } => {
3313
+ Scope :: TraitRefHackInner { s, .. }
3314
+ | Scope :: Supertrait { s, .. }
3315
+ | Scope :: TraitRefBoundary { s, .. } => {
3347
3316
scope = s;
3348
3317
}
3349
3318
}
0 commit comments