Make late and late_anon regions track the bound var position

This commit is contained in:
Jack Huey 2020-11-15 17:06:58 -05:00
parent 84f82d348c
commit 666859a6f8
6 changed files with 99 additions and 54 deletions

View file

@ -115,7 +115,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(
Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)),
Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)),
ty::BrAnon(br_index),
) => {
debug!(
@ -143,7 +143,7 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(
Some(rl::Region::LateBound(debruijn_index, id, _)),
Some(rl::Region::LateBound(debruijn_index, _, id, _)),
ty::BrNamed(def_id, _),
) => {
debug!(
@ -162,8 +162,8 @@ impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
rl::Region::Static
| rl::Region::Free(_, _)
| rl::Region::EarlyBound(_, _, _)
| rl::Region::LateBound(_, _, _)
| rl::Region::LateBoundAnon(_, _),
| rl::Region::LateBound(_, _, _, _)
| rl::Region::LateBoundAnon(_, _, _),
)
| None,
_,
@ -217,7 +217,10 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> {
fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
match (self.tcx.named_region(lifetime.hir_id), self.bound_region) {
// the lifetime of the TyPath!
(Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
(
Some(rl::Region::LateBoundAnon(debruijn_index, _, anon_index)),
ty::BrAnon(br_index),
) => {
if debruijn_index == self.current_index && anon_index == br_index {
self.found_it = true;
return;
@ -232,7 +235,7 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> {
}
}
(Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
(Some(rl::Region::LateBound(debruijn_index, _, id, _)), ty::BrNamed(def_id, _)) => {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
debug!("id={:?}", id);
debug!("def_id={:?}", def_id);
@ -246,8 +249,8 @@ impl Visitor<'tcx> for TyPathVisitor<'tcx> {
Some(
rl::Region::Static
| rl::Region::EarlyBound(_, _, _)
| rl::Region::LateBound(_, _, _)
| rl::Region::LateBoundAnon(_, _)
| rl::Region::LateBound(_, _, _, _)
| rl::Region::LateBoundAnon(_, _, _)
| rl::Region::Free(_, _),
)
| None,

View file

@ -39,8 +39,13 @@ impl LifetimeDefOrigin {
pub enum Region {
Static,
EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin),
LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId, LifetimeDefOrigin),
LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
LateBound(
ty::DebruijnIndex,
/* late-bound index */ u32,
/* lifetime decl */ DefId,
LifetimeDefOrigin,
),
LateBoundAnon(ty::DebruijnIndex, /* late-bound index */ u32, /* anon index */ u32),
Free(DefId, /* lifetime decl */ DefId),
}

View file

@ -42,9 +42,9 @@ pub enum LifetimeUseSet<'tcx> {
trait RegionExt {
fn early(hir_map: &Map<'_>, index: &mut u32, param: &GenericParam<'_>) -> (ParamName, Region);
fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region);
fn late(index: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region);
fn late_anon(index: &Cell<u32>) -> Region;
fn late_anon(named_late_bound_vars: u32, anon_index: &Cell<u32>) -> Region;
fn id(&self) -> Option<DefId>;
@ -67,7 +67,7 @@ impl RegionExt for Region {
(param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id.to_def_id(), origin))
}
fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) {
fn late(idx: u32, hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) {
let depth = ty::INNERMOST;
let def_id = hir_map.local_def_id(param.hir_id);
let origin = LifetimeDefOrigin::from_param(param);
@ -75,21 +75,24 @@ impl RegionExt for Region {
"Region::late: param={:?} depth={:?} def_id={:?} origin={:?}",
param, depth, def_id, origin,
);
(param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id.to_def_id(), origin))
(
param.name.normalize_to_macros_2_0(),
Region::LateBound(depth, idx, def_id.to_def_id(), origin),
)
}
fn late_anon(index: &Cell<u32>) -> Region {
fn late_anon(named_late_bound_vars: u32, index: &Cell<u32>) -> Region {
let i = index.get();
index.set(i + 1);
let depth = ty::INNERMOST;
Region::LateBoundAnon(depth, i)
Region::LateBoundAnon(depth, named_late_bound_vars + i, i)
}
fn id(&self) -> Option<DefId> {
match *self {
Region::Static | Region::LateBoundAnon(..) => None,
Region::EarlyBound(_, id, _) | Region::LateBound(_, id, _) | Region::Free(_, id) => {
Region::EarlyBound(_, id, _) | Region::LateBound(_, _, id, _) | Region::Free(_, id) => {
Some(id)
}
}
@ -97,11 +100,11 @@ impl RegionExt for Region {
fn shifted(self, amount: u32) -> Region {
match self {
Region::LateBound(debruijn, id, origin) => {
Region::LateBound(debruijn.shifted_in(amount), id, origin)
Region::LateBound(debruijn, idx, id, origin) => {
Region::LateBound(debruijn.shifted_in(amount), idx, id, origin)
}
Region::LateBoundAnon(debruijn, index) => {
Region::LateBoundAnon(debruijn.shifted_in(amount), index)
Region::LateBoundAnon(debruijn, index, anon_index) => {
Region::LateBoundAnon(debruijn.shifted_in(amount), index, anon_index)
}
_ => self,
}
@ -109,11 +112,11 @@ impl RegionExt for Region {
fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region {
match self {
Region::LateBound(debruijn, id, origin) => {
Region::LateBound(debruijn.shifted_out_to_binder(binder), id, origin)
Region::LateBound(debruijn, index, id, origin) => {
Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id, origin)
}
Region::LateBoundAnon(debruijn, index) => {
Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index)
Region::LateBoundAnon(debruijn, index, anon_index) => {
Region::LateBoundAnon(debruijn.shifted_out_to_binder(binder), index, anon_index)
}
_ => self,
}
@ -225,6 +228,8 @@ enum Scope<'a> {
/// of the resulting opaque type.
opaque_type_parent: bool,
named_late_bound_vars: u32,
s: ScopeRef<'a>,
},
@ -266,6 +271,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
next_early_index,
track_lifetime_uses,
opaque_type_parent,
named_late_bound_vars,
s: _,
} => f
.debug_struct("Binder")
@ -273,6 +279,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
.field("next_early_index", next_early_index)
.field("track_lifetime_uses", track_lifetime_uses)
.field("opaque_type_parent", opaque_type_parent)
.field("named_late_bound_vars", named_late_bound_vars)
.field("s", &"..")
.finish(),
Scope::Body { id, s: _ } => {
@ -294,8 +301,9 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
#[derive(Clone, Debug)]
enum Elide {
/// Use a fresh anonymous late-bound lifetime each time, by
/// incrementing the counter to generate sequential indices.
FreshLateAnon(Cell<u32>),
/// incrementing the counter to generate sequential indices. All
/// anonymous lifetimes must start *after* named bound vars.
FreshLateAnon(u32, Cell<u32>),
/// Always use this one lifetime.
Exact(Region),
/// Less or more than one lifetime were found, error on unspecified.
@ -626,6 +634,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
next_early_index: index + non_lifetime_count,
opaque_type_parent: true,
track_lifetime_uses,
named_late_bound_vars: 0,
s: ROOT_SCOPE,
};
self.with(scope, |old_scope, this| {
@ -676,9 +685,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
lifetimes: c
.generic_params
.iter()
.filter_map(|param| match param.kind {
.enumerate()
.filter_map(|(idx, param)| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir(), param))
Some(Region::late(idx as u32, &self.tcx.hir(), param))
}
_ => None,
})
@ -687,6 +697,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
named_late_bound_vars: c.generic_params.len() as u32,
};
self.with(scope, |old_scope, this| {
// a bare fn has no bounds, so everything
@ -721,7 +732,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// resolved the same as the `'_` in `&'_ Foo`.
//
// cc #48468
self.resolve_elided_lifetimes(vec![lifetime])
self.resolve_elided_lifetimes(&[lifetime])
}
LifetimeName::Param(_) | LifetimeName::Static => {
// If the user wrote an explicit name, use that.
@ -784,7 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.hir_id).cloned();
if let Some(Region::LateBound(_, def_id, _)) = def {
if let Some(Region::LateBound(_, _, def_id, _)) = def {
if let Some(def_id) = def_id.as_local() {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// Ensure that the parent of the def is an item, not HRTB
@ -874,6 +885,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
s: this.scope,
track_lifetime_uses: true,
opaque_type_parent: false,
named_late_bound_vars: 0,
};
this.with(scope, |_old_scope, this| {
this.visit_generics(generics);
@ -889,6 +901,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: false,
named_late_bound_vars: 0,
};
self.with(scope, |_old_scope, this| {
this.visit_generics(generics);
@ -941,6 +954,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: true,
named_late_bound_vars: 0,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
@ -1003,6 +1017,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
s: self.scope,
track_lifetime_uses: true,
opaque_type_parent: true,
named_late_bound_vars: 0,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
@ -1024,7 +1039,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
#[tracing::instrument(level = "debug", skip(self))]
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
if lifetime_ref.is_elided() {
self.resolve_elided_lifetimes(vec![lifetime_ref]);
self.resolve_elided_lifetimes(&[lifetime_ref]);
return;
}
if lifetime_ref.is_static() {
@ -1087,9 +1102,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}) => {
let lifetimes: FxHashMap<_, _> = bound_generic_params
.iter()
.filter_map(|param| match param.kind {
.enumerate()
.filter_map(|(idx, param)| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir(), param))
Some(Region::late(idx as u32, &self.tcx.hir(), param))
}
_ => None,
})
@ -1102,6 +1118,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
named_late_bound_vars: bound_generic_params.len() as u32,
};
let result = self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &bound_generic_params);
@ -1145,6 +1162,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
next_early_index: self.next_early_index(),
track_lifetime_uses: true,
opaque_type_parent: false,
named_late_bound_vars: 0,
};
self.with(scope, |_, this| {
intravisit::walk_param_bound(this, bound);
@ -1184,9 +1202,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
lifetimes: trait_ref
.bound_generic_params
.iter()
.filter_map(|param| match param.kind {
.enumerate()
.filter_map(|(idx, param)| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some(Region::late(&self.tcx.hir(), param))
Some(Region::late(idx as u32, &self.tcx.hir(), param))
}
_ => None,
})
@ -1195,6 +1214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
next_early_index,
track_lifetime_uses: true,
opaque_type_parent: false,
named_late_bound_vars: trait_ref.bound_generic_params.len() as u32,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
@ -1715,7 +1735,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
.values()
.flat_map(|region| match region {
Region::EarlyBound(_, def_id, _)
| Region::LateBound(_, def_id, _)
| Region::LateBound(_, _, def_id, _)
| Region::Free(_, def_id) => Some(*def_id),
Region::LateBoundAnon(..) | Region::Static => None,
@ -1886,13 +1906,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
let mut non_lifetime_count = 0;
let mut named_late_bound_vars = 0;
let lifetimes = generics
.params
.iter()
.filter_map(|param| match param.kind {
.enumerate()
.filter_map(|(idx, param)| match param.kind {
GenericParamKind::Lifetime { .. } => {
if self.map.late_bound.contains(&param.hir_id) {
Some(Region::late(&self.tcx.hir(), param))
named_late_bound_vars += 1;
Some(Region::late(idx as u32, &self.tcx.hir(), param))
} else {
Some(Region::early(&self.tcx.hir(), &mut index, param))
}
@ -1911,6 +1934,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
s: self.scope,
opaque_type_parent: true,
track_lifetime_uses: false,
named_late_bound_vars,
};
self.with(scope, move |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
@ -2025,7 +2049,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if !self.trait_definition_only && self.is_in_fn_syntax {
match def {
Region::EarlyBound(_, _, LifetimeDefOrigin::InBand)
| Region::LateBound(_, _, LifetimeDefOrigin::InBand) => {
| Region::LateBound(_, _, _, LifetimeDefOrigin::InBand) => {
struct_span_err!(
self.tcx.sess,
lifetime_ref.span,
@ -2044,6 +2068,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error,
)
| Region::LateBound(
_,
_,
_,
LifetimeDefOrigin::ExplicitOrElided | LifetimeDefOrigin::Error,
@ -2079,7 +2104,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
let mut elide_lifetimes = true;
let lifetimes = generic_args
let lifetimes: Vec<_> = generic_args
.args
.iter()
.filter_map(|arg| match arg {
@ -2093,7 +2118,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
})
.collect();
if elide_lifetimes {
self.resolve_elided_lifetimes(lifetimes);
self.resolve_elided_lifetimes(&lifetimes);
} else {
lifetimes.iter().for_each(|lt| self.visit_lifetime(lt));
}
@ -2261,7 +2286,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
inputs: &'tcx [hir::Ty<'tcx>],
output: Option<&'tcx hir::Ty<'tcx>>,
) {
let arg_scope = Scope::Elision { elide: Elide::FreshLateAnon(Cell::new(0)), s: self.scope };
debug!("visit_fn_like_elision: enter");
let named_late_bound_vars = match *self.scope {
Scope::Binder { named_late_bound_vars, .. } => named_late_bound_vars,
Scope::Body { .. } => 0,
_ => bug!("{:?}", self.scope),
};
let arg_scope = Scope::Elision {
elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)),
s: self.scope,
};
self.with(arg_scope, |_, this| {
for input in inputs {
this.visit_ty(input);
@ -2516,7 +2550,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.hir_id) {
match lifetime {
Region::LateBound(debruijn, _, _) | Region::LateBoundAnon(debruijn, _)
Region::LateBound(debruijn, _, _, _)
| Region::LateBoundAnon(debruijn, _, _)
if debruijn < self.outer_index =>
{
self.have_bound_regions = true;
@ -2530,7 +2565,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) {
fn resolve_elided_lifetimes(&mut self, lifetime_refs: &[&'tcx hir::Lifetime]) {
debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs);
if lifetime_refs.is_empty() {
@ -2563,9 +2598,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Elision { ref elide, ref s, .. } => {
let lifetime = match *elide {
Elide::FreshLateAnon(ref counter) => {
Elide::FreshLateAnon(named_late_bound_vars, ref counter) => {
for lifetime_ref in lifetime_refs {
let lifetime = Region::late_anon(counter).shifted(late_depth);
let lifetime = Region::late_anon(named_late_bound_vars, counter)
.shifted(late_depth);
self.insert_lifetime(lifetime_ref, lifetime);
}
return;
@ -2890,7 +2926,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// A lifetime only used in a fn argument could as well
// be replaced with `'_`, as that would generate a
// fresh name, too.
Scope::Elision { elide: Elide::FreshLateAnon(_), .. } => break true,
Scope::Elision { elide: Elide::FreshLateAnon(_, _), .. } => break true,
// In the return type or other such place, `'_` is not
// going to make a fresh name, so we cannot
@ -2919,7 +2955,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
Region::Free(_, def_id)
| Region::LateBound(_, def_id, _)
| Region::LateBound(_, _, def_id, _)
| Region::EarlyBound(_, def_id, _) => {
// A lifetime declared by the user.
let track_lifetime_uses = self.track_lifetime_uses();

View file

@ -210,14 +210,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let r = match tcx.named_region(lifetime.hir_id) {
Some(rl::Region::Static) => tcx.lifetimes.re_static,
Some(rl::Region::LateBound(debruijn, id, _)) => {
Some(rl::Region::LateBound(debruijn, _, id, _)) => {
let name = lifetime_name(id.expect_local());
let br = ty::BoundRegion { kind: ty::BrNamed(id, name) };
tcx.mk_region(ty::ReLateBound(debruijn, br))
}
Some(rl::Region::LateBoundAnon(debruijn, index)) => {
let br = ty::BoundRegion { kind: ty::BrAnon(index) };
Some(rl::Region::LateBoundAnon(debruijn, _index, anon_index)) => {
let br = ty::BoundRegion { kind: ty::BrAnon(anon_index) };
tcx.mk_region(ty::ReLateBound(debruijn, br))
}

View file

@ -1244,7 +1244,8 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
match self.tcx.named_region(lt.hir_id) {
Some(rl::Region::Static | rl::Region::EarlyBound(..)) => {}
Some(
rl::Region::LateBound(debruijn, _, _) | rl::Region::LateBoundAnon(debruijn, _),
rl::Region::LateBound(debruijn, _, _, _)
| rl::Region::LateBoundAnon(debruijn, _, _),
) if debruijn < self.outer_index => {}
Some(
rl::Region::LateBound(..)

View file

@ -352,7 +352,7 @@ impl Clean<Lifetime> for hir::Lifetime {
match def {
Some(
rl::Region::EarlyBound(_, node_id, _)
| rl::Region::LateBound(_, node_id, _)
| rl::Region::LateBound(_, _, node_id, _)
| rl::Region::Free(_, node_id),
) => {
if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {