/// 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>,
},
let scope = Scope::Binder {
lifetimes,
next_early_index,
+ abstract_type_parent: true,
s: ROOT_SCOPE,
};
self.with(scope, |old_scope, this| {
.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
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;
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 {
});
});
} 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 {
.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 {
.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);
.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);
.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);
ref lifetimes,
s,
next_early_index: _,
+ abstract_type_parent: _,
} => {
// FIXME (#24278): non-hygienic comparison
if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) {
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);
});
}
- /// 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
ref lifetimes,
s,
next_early_index: _,
+ abstract_type_parent: _,
} => {
if let Some(&def) = lifetimes.get(&lifetime_ref.name) {
break Some(def.shifted(late_depth));
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();