Skip to content

Commit ba3d22e

Browse files
committed
Precompute inverse binder depth
1 parent 6df26f8 commit ba3d22e

File tree

1 file changed

+73
-104
lines changed

1 file changed

+73
-104
lines changed

compiler/rustc_resolve/src/late/lifetimes.rs

Lines changed: 73 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
621664
impl<'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

Comments
 (0)