Rollup merge of #48072 - cramertj:impl-trait-lifetime-res, r=nikomatsakis
Fix nested impl trait lifetimes Fixes #46464 cc https://github.com/rust-lang/rust/issues/34511 r? @nikomatsakis
This commit is contained in:
commit
4941cb4796
|
@ -270,6 +270,19 @@ enum Scope<'a> {
|
|||
/// we should use for an early-bound region?
|
||||
next_early_index: u32,
|
||||
|
||||
/// Whether or not this binder would serve as the parent
|
||||
/// binder for abstract types introduced within. For example:
|
||||
///
|
||||
/// fn foo<'a>() -> impl for<'b> Trait<Item = impl Trait2<'a>>
|
||||
///
|
||||
/// Here, the abstract types we create for the `impl Trait`
|
||||
/// and `impl Trait2` references will both have the `foo` item
|
||||
/// as their parent. When we get to `impl Trait2`, we find
|
||||
/// that it is nested within the `for<>` binder -- this flag
|
||||
/// allows us to skip that when looking for the parent binder
|
||||
/// of the resulting abstract type.
|
||||
abstract_type_parent: bool,
|
||||
|
||||
s: ScopeRef<'a>,
|
||||
},
|
||||
|
||||
|
@ -498,6 +511,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
let scope = Scope::Binder {
|
||||
lifetimes,
|
||||
next_early_index,
|
||||
abstract_type_parent: true,
|
||||
s: ROOT_SCOPE,
|
||||
};
|
||||
self.with(scope, |old_scope, this| {
|
||||
|
@ -541,6 +555,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
.collect(),
|
||||
s: self.scope,
|
||||
next_early_index,
|
||||
abstract_type_parent: false,
|
||||
};
|
||||
self.with(scope, |old_scope, this| {
|
||||
// a bare fn has no bounds, so everything
|
||||
|
@ -614,7 +629,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
ref generics,
|
||||
ref bounds,
|
||||
} = *exist_ty;
|
||||
let mut index = self.next_early_index();
|
||||
|
||||
// We want to start our early-bound indices at the end of the parent scope,
|
||||
// not including any parent `impl Trait`s.
|
||||
let mut index = self.next_early_index_for_abstract_type();
|
||||
debug!("visit_ty: index = {}", index);
|
||||
|
||||
let mut elision = None;
|
||||
|
@ -638,7 +656,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
s: self.scope
|
||||
};
|
||||
self.with(scope, |_old_scope, this| {
|
||||
let scope = Scope::Binder { lifetimes, next_early_index, s: this.scope };
|
||||
let scope = Scope::Binder {
|
||||
lifetimes,
|
||||
next_early_index,
|
||||
s: this.scope,
|
||||
abstract_type_parent: false,
|
||||
};
|
||||
this.with(scope, |_old_scope, this| {
|
||||
this.visit_generics(generics);
|
||||
for bound in bounds {
|
||||
|
@ -647,7 +670,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
});
|
||||
});
|
||||
} else {
|
||||
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
|
||||
let scope = Scope::Binder {
|
||||
lifetimes,
|
||||
next_early_index,
|
||||
s: self.scope,
|
||||
abstract_type_parent: false,
|
||||
};
|
||||
self.with(scope, |_old_scope, this| {
|
||||
this.visit_generics(generics);
|
||||
for bound in bounds {
|
||||
|
@ -681,7 +709,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
.collect();
|
||||
|
||||
let next_early_index = index + generics.ty_params().count() as u32;
|
||||
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
|
||||
let scope = Scope::Binder {
|
||||
lifetimes,
|
||||
next_early_index,
|
||||
s: self.scope,
|
||||
abstract_type_parent: true,
|
||||
};
|
||||
self.with(scope, |_old_scope, this| {
|
||||
this.visit_generics(generics);
|
||||
for bound in bounds {
|
||||
|
@ -721,7 +754,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
.collect();
|
||||
|
||||
let next_early_index = index + generics.ty_params().count() as u32;
|
||||
let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope };
|
||||
let scope = Scope::Binder {
|
||||
lifetimes,
|
||||
next_early_index,
|
||||
s: self.scope,
|
||||
abstract_type_parent: true,
|
||||
};
|
||||
self.with(scope, |_old_scope, this| {
|
||||
this.visit_generics(generics);
|
||||
this.visit_ty(ty);
|
||||
|
@ -792,6 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
.collect(),
|
||||
s: self.scope,
|
||||
next_early_index,
|
||||
abstract_type_parent: false,
|
||||
};
|
||||
let result = self.with(scope, |old_scope, this| {
|
||||
this.check_lifetime_params(old_scope, &bound_generic_params);
|
||||
|
@ -853,6 +892,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
.collect(),
|
||||
s: self.scope,
|
||||
next_early_index,
|
||||
abstract_type_parent: false,
|
||||
};
|
||||
self.with(scope, |old_scope, this| {
|
||||
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
|
||||
|
@ -1046,6 +1086,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body) {
|
|||
ref lifetimes,
|
||||
s,
|
||||
next_early_index: _,
|
||||
abstract_type_parent: _,
|
||||
} => {
|
||||
// FIXME (#24278): non-hygienic comparison
|
||||
if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) {
|
||||
|
@ -1303,6 +1344,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
lifetimes,
|
||||
next_early_index,
|
||||
s: self.scope,
|
||||
abstract_type_parent: true,
|
||||
};
|
||||
self.with(scope, move |old_scope, this| {
|
||||
this.check_lifetime_params(old_scope, &generics.params);
|
||||
|
@ -1310,25 +1352,41 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
});
|
||||
}
|
||||
|
||||
/// Returns the next index one would use for an early-bound-region
|
||||
/// if extending the current scope.
|
||||
fn next_early_index(&self) -> u32 {
|
||||
fn next_early_index_helper(&self, only_abstract_type_parent: bool) -> u32 {
|
||||
let mut scope = self.scope;
|
||||
loop {
|
||||
match *scope {
|
||||
Scope::Root => return 0,
|
||||
|
||||
Scope::Binder {
|
||||
next_early_index, ..
|
||||
} => return next_early_index,
|
||||
next_early_index,
|
||||
abstract_type_parent,
|
||||
..
|
||||
} if (!only_abstract_type_parent || abstract_type_parent)
|
||||
=> return next_early_index,
|
||||
|
||||
Scope::Body { s, .. }
|
||||
Scope::Binder { s, .. }
|
||||
| Scope::Body { s, .. }
|
||||
| Scope::Elision { s, .. }
|
||||
| Scope::ObjectLifetimeDefault { s, .. } => scope = s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the next index one would use for an early-bound-region
|
||||
/// if extending the current scope.
|
||||
fn next_early_index(&self) -> u32 {
|
||||
self.next_early_index_helper(true)
|
||||
}
|
||||
|
||||
/// Returns the next index one would use for an `impl Trait` that
|
||||
/// is being converted into an `abstract type`. This will be the
|
||||
/// next early index from the enclosing item, for the most
|
||||
/// part. See the `abstract_type_parent` field for more info.
|
||||
fn next_early_index_for_abstract_type(&self) -> u32 {
|
||||
self.next_early_index_helper(false)
|
||||
}
|
||||
|
||||
fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
||||
debug!("resolve_lifetime_ref(lifetime_ref={:?})", lifetime_ref);
|
||||
// Walk up the scope chain, tracking the number of fn scopes
|
||||
|
@ -1353,6 +1411,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
ref lifetimes,
|
||||
s,
|
||||
next_early_index: _,
|
||||
abstract_type_parent: _,
|
||||
} => {
|
||||
if let Some(&def) = lifetimes.get(&lifetime_ref.name) {
|
||||
break Some(def.shifted(late_depth));
|
||||
|
@ -2102,6 +2161,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
ref lifetimes,
|
||||
s,
|
||||
next_early_index: _,
|
||||
abstract_type_parent: _,
|
||||
} => {
|
||||
if let Some(&def) = lifetimes.get(&lifetime.name) {
|
||||
let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap();
|
||||
|
|
|
@ -50,6 +50,14 @@ fn closure_hr_elided_return() -> impl Fn(&u32) -> &u32 { |x| x }
|
|||
fn closure_pass_through_elided_return(x: impl Fn(&u32) -> &u32) -> impl Fn(&u32) -> &u32 { x }
|
||||
fn closure_pass_through_reference_elided(x: &impl Fn(&u32) -> &u32) -> &impl Fn(&u32) -> &u32 { x }
|
||||
|
||||
fn nested_lifetime<'a>(input: &'a str)
|
||||
-> impl Iterator<Item = impl Iterator<Item = i32> + 'a> + 'a
|
||||
{
|
||||
input.lines().map(|line| {
|
||||
line.split_whitespace().map(|cell| cell.parse().unwrap())
|
||||
})
|
||||
}
|
||||
|
||||
fn pass_through_elision(x: &u32) -> impl Into<&u32> { x }
|
||||
fn pass_through_elision_with_fn_ptr(x: &fn(&u32) -> &u32) -> impl Into<&fn(&u32) -> &u32> { x }
|
||||
|
||||
|
|
Loading…
Reference in New Issue