Skip to content

Commit 4941cb4

Browse files
authored
Rollup merge of rust-lang#48072 - cramertj:impl-trait-lifetime-res, r=nikomatsakis
Fix nested impl trait lifetimes Fixes rust-lang#46464 cc rust-lang#34511 r? @nikomatsakis
2 parents abf4d70 + dd481d5 commit 4941cb4

File tree

2 files changed

+79
-11
lines changed

2 files changed

+79
-11
lines changed

src/librustc/middle/resolve_lifetime.rs

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,19 @@ enum Scope<'a> {
270270
/// we should use for an early-bound region?
271271
next_early_index: u32,
272272

273+
/// Whether or not this binder would serve as the parent
274+
/// binder for abstract types introduced within. For example:
275+
///
276+
/// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
277+
///
278+
/// Here, the abstract types we create for the `impl Trait`
279+
/// and `impl Trait2` references will both have the `foo` item
280+
/// as their parent. When we get to `impl Trait2`, we find
281+
/// that it is nested within the `for<>` binder -- this flag
282+
/// allows us to skip that when looking for the parent binder
283+
/// of the resulting abstract type.
284+
abstract_type_parent: bool,
285+
273286
s: ScopeRef<'a>,
274287
},
275288

@@ -498,6 +511,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
498511
let scope = Scope::Binder {
499512
lifetimes,
500513
next_early_index,
514+
abstract_type_parent: true,
501515
s: ROOT_SCOPE,
502516
};
503517
self.with(scope, |old_scope, this| {
@@ -541,6 +555,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
541555
.collect(),
542556
s: self.scope,
543557
next_early_index,
558+
abstract_type_parent: false,
544559
};
545560
self.with(scope, |old_scope, this| {
546561
// a bare fn has no bounds, so everything
@@ -614,7 +629,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
614629
ref generics,
615630
ref bounds,
616631
} = *exist_ty;
617-
let mut index = self.next_early_index();
632+
633+
// We want to start our early-bound indices at the end of the parent scope,
634+
// not including any parent `impl Trait`s.
635+
let mut index = self.next_early_index_for_abstract_type();
618636
debug!("visit_ty: index = {}", index);
619637

620638
let mut elision = None;
@@ -638,7 +656,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
638656
s: self.scope
639657
};
640658
self.with(scope, |_old_scope, this| {
641-
let scope = Scope::Binder { lifetimes, next_early_index, s: this.scope };
659+
let scope = Scope::Binder {
660+
lifetimes,
661+
next_early_index,
662+
s: this.scope,
663+
abstract_type_parent: false,
664+
};
642665
this.with(scope, |_old_scope, this| {
643666
this.visit_generics(generics);
644667
for bound in bounds {
@@ -647,7 +670,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
647670
});
648671
});
649672
} else {
650-
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
673+
let scope = Scope::Binder {
674+
lifetimes,
675+
next_early_index,
676+
s: self.scope,
677+
abstract_type_parent: false,
678+
};
651679
self.with(scope, |_old_scope, this| {
652680
this.visit_generics(generics);
653681
for bound in bounds {
@@ -681,7 +709,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
681709
.collect();
682710

683711
let next_early_index = index + generics.ty_params().count() as u32;
684-
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
712+
let scope = Scope::Binder {
713+
lifetimes,
714+
next_early_index,
715+
s: self.scope,
716+
abstract_type_parent: true,
717+
};
685718
self.with(scope, |_old_scope, this| {
686719
this.visit_generics(generics);
687720
for bound in bounds {
@@ -721,7 +754,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
721754
.collect();
722755

723756
let next_early_index = index + generics.ty_params().count() as u32;
724-
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
757+
let scope = Scope::Binder {
758+
lifetimes,
759+
next_early_index,
760+
s: self.scope,
761+
abstract_type_parent: true,
762+
};
725763
self.with(scope, |_old_scope, this| {
726764
this.visit_generics(generics);
727765
this.visit_ty(ty);
@@ -792,6 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
792830
.collect(),
793831
s: self.scope,
794832
next_early_index,
833+
abstract_type_parent: false,
795834
};
796835
let result = self.with(scope, |old_scope, this| {
797836
this.check_lifetime_params(old_scope, &bound_generic_params);
@@ -853,6 +892,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
853892
.collect(),
854893
s: self.scope,
855894
next_early_index,
895+
abstract_type_parent: false,
856896
};
857897
self.with(scope, |old_scope, this| {
858898
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
@@ -1046,6 +1086,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body) {
10461086
ref lifetimes,
10471087
s,
10481088
next_early_index: _,
1089+
abstract_type_parent: _,
10491090
} => {
10501091
// FIXME (#24278): non-hygienic comparison
10511092
if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) {
@@ -1303,32 +1344,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
13031344
lifetimes,
13041345
next_early_index,
13051346
s: self.scope,
1347+
abstract_type_parent: true,
13061348
};
13071349
self.with(scope, move |old_scope, this| {
13081350
this.check_lifetime_params(old_scope, &generics.params);
13091351
this.hack(walk); // FIXME(#37666) workaround in place of `walk(this)`
13101352
});
13111353
}
13121354

1313-
/// Returns the next index one would use for an early-bound-region
1314-
/// if extending the current scope.
1315-
fn next_early_index(&self) -> u32 {
1355+
fn next_early_index_helper(&self, only_abstract_type_parent: bool) -> u32 {
13161356
let mut scope = self.scope;
13171357
loop {
13181358
match *scope {
13191359
Scope::Root => return 0,
13201360

13211361
Scope::Binder {
1322-
next_early_index, ..
1323-
} => return next_early_index,
1362+
next_early_index,
1363+
abstract_type_parent,
1364+
..
1365+
} if (!only_abstract_type_parent || abstract_type_parent)
1366+
=> return next_early_index,
13241367

1325-
Scope::Body { s, .. }
1368+
Scope::Binder { s, .. }
1369+
| Scope::Body { s, .. }
13261370
| Scope::Elision { s, .. }
13271371
| Scope::ObjectLifetimeDefault { s, .. } => scope = s,
13281372
}
13291373
}
13301374
}
13311375

1376+
/// Returns the next index one would use for an early-bound-region
1377+
/// if extending the current scope.
1378+
fn next_early_index(&self) -> u32 {
1379+
self.next_early_index_helper(true)
1380+
}
1381+
1382+
/// Returns the next index one would use for an `impl Trait` that
1383+
/// is being converted into an `abstract type`. This will be the
1384+
/// next early index from the enclosing item, for the most
1385+
/// part. See the `abstract_type_parent` field for more info.
1386+
fn next_early_index_for_abstract_type(&self) -> u32 {
1387+
self.next_early_index_helper(false)
1388+
}
1389+
13321390
fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
13331391
debug!("resolve_lifetime_ref(lifetime_ref={:?})", lifetime_ref);
13341392
// Walk up the scope chain, tracking the number of fn scopes
@@ -1353,6 +1411,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
13531411
ref lifetimes,
13541412
s,
13551413
next_early_index: _,
1414+
abstract_type_parent: _,
13561415
} => {
13571416
if let Some(&def) = lifetimes.get(&lifetime_ref.name) {
13581417
break Some(def.shifted(late_depth));
@@ -2102,6 +2161,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
21022161
ref lifetimes,
21032162
s,
21042163
next_early_index: _,
2164+
abstract_type_parent: _,
21052165
} => {
21062166
if let Some(&def) = lifetimes.get(&lifetime.name) {
21072167
let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap();

src/test/run-pass/impl-trait/lifetimes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ fn closure_hr_elided_return() -> impl Fn(&u32) -> &u32 { |x| x }
5050
fn closure_pass_through_elided_return(x: impl Fn(&u32) -> &u32) -> impl Fn(&u32) -> &u32 { x }
5151
fn closure_pass_through_reference_elided(x: &impl Fn(&u32) -> &u32) -> &impl Fn(&u32) -> &u32 { x }
5252

53+
fn nested_lifetime<'a>(input: &'a str)
54+
-> impl Iterator<Item = impl Iterator<Item = i32> + 'a> + 'a
55+
{
56+
input.lines().map(|line| {
57+
line.split_whitespace().map(|cell| cell.parse().unwrap())
58+
})
59+
}
60+
5361
fn pass_through_elision(x: &u32) -> impl Into<&u32> { x }
5462
fn pass_through_elision_with_fn_ptr(x: &fn(&u32) -> &u32) -> impl Into<&fn(&u32) -> &u32> { x }
5563

0 commit comments

Comments
 (0)