Add BinderScopeType to replace binder_depth and from_poly_trait_ref

This commit is contained in:
Jack Huey 2021-04-13 16:58:00 -04:00
parent 32942ab807
commit 457c4c133a

View File

@ -244,12 +244,7 @@ enum Scope<'a> {
/// of the resulting opaque type.
opaque_type_parent: bool,
/// True only if this `Binder` scope is from the quantifiers on a
/// `PolyTraitRef`. This is necessary for `associated_type_bounds`, which
/// requires binders of nested trait refs to be merged.
from_poly_trait_ref: bool,
binder_depth: u32,
scope_type: BinderScopeType,
/// The late bound vars for a given item are stored by `HirId` to be
/// queried later. However, if we enter an elision scope, we have to
@ -335,6 +330,13 @@ enum Scope<'a> {
Root,
}
#[derive(Copy, Clone, Debug)]
enum BinderScopeType {
Other,
PolyTraitRef,
Concatenating,
}
// A helper struct for debugging scopes without printing parent scopes
struct TruncatedScopeDebug<'a>(&'a Scope<'a>);
@ -346,8 +348,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
next_early_index,
track_lifetime_uses,
opaque_type_parent,
from_poly_trait_ref,
binder_depth,
scope_type,
hir_id,
s: _,
} => f
@ -356,8 +357,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
.field("next_early_index", next_early_index)
.field("track_lifetime_uses", track_lifetime_uses)
.field("opaque_type_parent", opaque_type_parent)
.field("from_poly_trait_ref", from_poly_trait_ref)
.field("binder_depth", binder_depth)
.field("scope_type", scope_type)
.field("hir_id", hir_id)
.field("s", &"..")
.finish(),
@ -622,48 +622,6 @@ fn late_region_as_bound_region<'tcx>(tcx: TyCtxt<'tcx>, region: &Region) -> ty::
}
}
impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
fn depth(&self, concanetate: bool) -> u32 {
let mut passed_boundary = false;
let mut scope = self.scope;
loop {
match *scope {
Scope::Root => {
break 0;
}
Scope::TraitRefBoundary { s, .. } => {
passed_boundary = true;
scope = s;
}
Scope::Binder { binder_depth, from_poly_trait_ref, .. } => {
if concanetate && !passed_boundary && !from_poly_trait_ref {
bug!("{:?}", self.scope);
}
break if concanetate {
if passed_boundary || !from_poly_trait_ref {
binder_depth + 1
} else {
binder_depth
}
} else {
binder_depth + 1
};
}
Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::TraitRefHackInner { s, .. }
| Scope::Supertrait { s, .. }
| Scope::Body { s, .. } => {
scope = s;
}
}
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
type Map = Map<'tcx>;
@ -721,8 +679,7 @@ fn visit_fn(
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, move |_old_scope, this| {
intravisit::walk_fn(this, fk, fd, b, s, hir_id)
@ -847,8 +804,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
next_early_index: index + non_lifetime_count,
opaque_type_parent: true,
track_lifetime_uses,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
s: ROOT_SCOPE,
};
self.with(scope, |old_scope, this| {
@ -920,8 +876,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, |old_scope, this| {
// a bare fn has no bounds, so everything
@ -1117,8 +1072,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
s: this.scope,
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: false,
binder_depth: this.depth(false),
scope_type: BinderScopeType::Other,
};
this.with(scope, |_old_scope, this| {
this.visit_generics(generics);
@ -1138,8 +1092,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, |_old_scope, this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
@ -1198,8 +1151,7 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: true,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
@ -1268,8 +1220,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: true,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
@ -1373,29 +1324,28 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
})
.unzip();
this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
if !lifetimes.is_empty() {
let next_early_index = this.next_early_index();
let scope = Scope::Binder {
hir_id: bounded_ty.hir_id,
lifetimes,
s: this.scope,
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: true,
binder_depth: this.depth(false),
};
this.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &bound_generic_params);
this.visit_ty(&bounded_ty);
this.trait_ref_hack = Some(bounded_ty.hir_id);
walk_list!(this, visit_param_bound, bounds);
this.trait_ref_hack = None;
})
} else {
if !lifetimes.is_empty() {
let next_early_index = this.next_early_index();
let scope = Scope::Binder {
hir_id: bounded_ty.hir_id,
lifetimes,
s: this.scope,
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
scope_type: BinderScopeType::PolyTraitRef,
};
this.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &bound_generic_params);
this.visit_ty(&bounded_ty);
this.trait_ref_hack = Some(bounded_ty.hir_id);
walk_list!(this, visit_param_bound, bounds);
}
this.trait_ref_hack = None;
})
} else {
this.visit_ty(&bounded_ty);
walk_list!(this, visit_param_bound, bounds);
}
}
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
ref lifetime,
@ -1429,8 +1379,7 @@ fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
next_early_index: self.next_early_index(),
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, |_, this| {
intravisit::walk_param_bound(this, bound);
@ -1527,12 +1476,7 @@ fn visit_poly_trait_ref(
break vec![];
}
Scope::Binder { hir_id, from_poly_trait_ref, .. } => {
if !from_poly_trait_ref {
// We should only see super trait lifetimes if there is a `Binder` above
assert!(supertrait_lifetimes.is_empty());
break vec![];
}
Scope::Binder { hir_id, .. } => {
// Nested poly trait refs have the binders concatenated
let mut full_binders =
self.map.late_bound_vars.entry(*hir_id).or_default().clone();
@ -1569,6 +1513,33 @@ fn visit_poly_trait_ref(
self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
if trait_ref_hack.is_none() || has_lifetimes {
let scope_type = {
let mut scope = self.scope;
loop {
match *scope {
Scope::Root | Scope::TraitRefBoundary { .. } => {
break BinderScopeType::PolyTraitRef;
}
Scope::Binder { scope_type, .. } => {
if let BinderScopeType::Other = scope_type {
bug!(
"Expected all syntacic poly trait refs to be surrounded by a `TraitRefBoundary`"
)
}
break BinderScopeType::Concatenating;
}
Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::TraitRefHackInner { s, .. }
| Scope::Supertrait { s, .. }
| Scope::Body { s, .. } => {
scope = s;
}
}
}
};
let scope = Scope::Binder {
hir_id: trait_ref.trait_ref.hir_ref_id,
lifetimes,
@ -1576,8 +1547,7 @@ fn visit_poly_trait_ref(
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
from_poly_trait_ref: true,
binder_depth: self.depth(true),
scope_type,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
@ -2327,8 +2297,7 @@ fn visit_early_late<F>(
s: self.scope,
opaque_type_parent: true,
track_lifetime_uses: false,
from_poly_trait_ref: false,
binder_depth: self.depth(false),
scope_type: BinderScopeType::Other,
};
self.with(scope, move |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
@ -2386,7 +2355,6 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
// given name or we run out of scopes.
// search.
let mut late_depth = 0;
let mut first_binder_depth = None;
let mut scope = self.scope;
let mut outermost_body = None;
let result = loop {
@ -2404,7 +2372,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
break None;
}
Scope::Binder { ref lifetimes, s, binder_depth, .. } => {
Scope::Binder { ref lifetimes, scope_type, s, .. } => {
match lifetime_ref.name {
LifetimeName::Param(param_name) => {
if let Some(&def) = lifetimes.get(&param_name.normalize_to_macros_2_0())
@ -2414,8 +2382,11 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
}
_ => bug!("expected LifetimeName::Param"),
}
first_binder_depth = first_binder_depth.or(Some(binder_depth));
late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1;
match scope_type {
BinderScopeType::Other => late_depth += 1,
BinderScopeType::PolyTraitRef => late_depth += 1,
BinderScopeType::Concatenating => {}
}
scope = s;
}
@ -3126,7 +3097,6 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
let span = lifetime_refs[0].span;
let mut late_depth = 0;
let mut first_binder_depth = None;
let mut scope = self.scope;
let mut lifetime_names = FxHashSet::default();
let mut lifetime_spans = vec![];
@ -3137,7 +3107,7 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
Scope::Root => break None,
Scope::Binder { s, ref lifetimes, binder_depth, .. } => {
Scope::Binder { s, ref lifetimes, scope_type, .. } => {
// collect named lifetimes for suggestions
for name in lifetimes.keys() {
if let hir::ParamName::Plain(name) = name {
@ -3145,8 +3115,11 @@ fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
lifetime_spans.push(name.span);
}
}
first_binder_depth = first_binder_depth.or(Some(binder_depth));
late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1;
match scope_type {
BinderScopeType::Other => late_depth += 1,
BinderScopeType::PolyTraitRef => late_depth += 1,
BinderScopeType::Concatenating => {}
}
scope = s;
}
@ -3303,13 +3276,15 @@ fn report_elision_failure(
fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
let mut late_depth = 0;
let mut first_binder_depth = None;
let mut scope = self.scope;
let lifetime = loop {
match *scope {
Scope::Binder { s, binder_depth, .. } => {
first_binder_depth = first_binder_depth.or(Some(binder_depth));
late_depth = first_binder_depth.unwrap_or(binder_depth) - binder_depth + 1;
Scope::Binder { s, scope_type, .. } => {
match scope_type {
BinderScopeType::Other => late_depth += 1,
BinderScopeType::PolyTraitRef => late_depth += 1,
BinderScopeType::Concatenating => {}
}
scope = s;
}