Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor DebruijnIndex to be 0-based #50475

Merged
merged 13 commits into from
May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,16 @@ for ty::RegionKind {
c.hash_stable(hcx, hasher);
}
ty::ReLateBound(db, ty::BrAnon(i)) => {
db.depth.hash_stable(hcx, hasher);
db.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);
}
ty::ReLateBound(db, ty::BrNamed(def_id, name)) => {
db.depth.hash_stable(hcx, hasher);
db.hash_stable(hcx, hasher);
def_id.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
ty::ReLateBound(db, ty::BrEnv) => {
db.depth.hash_stable(hcx, hasher);
db.hash_stable(hcx, hasher);
}
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, index, name }) => {
def_id.hash_stable(hcx, hasher);
Expand Down Expand Up @@ -821,10 +821,6 @@ impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
Free(call_site_scope_data, decl)
});

impl_stable_hash_for!(struct ty::DebruijnIndex {
depth
});

impl_stable_hash_for!(enum ty::cast::CastKind {
CoercionCast,
PtrPtrCast,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
tcx: self.tcx,
bound_region: *br,
found_type: None,
depth: 1,
current_index: ty::DebruijnIndex::INNERMOST,
};
nested_visitor.visit_ty(arg);
nested_visitor.found_type
Expand All @@ -99,7 +99,7 @@ struct FindNestedTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
// The type where the anonymous lifetime appears
// for e.g. Vec<`&u8`> and <`&u8`>
found_type: Option<&'gcx hir::Ty>,
depth: u32,
current_index: ty::DebruijnIndex,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
Expand All @@ -110,16 +110,16 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
match arg.node {
hir::TyBareFn(_) => {
self.depth += 1;
self.current_index.shift_in(1);
intravisit::walk_ty(self, arg);
self.depth -= 1;
self.current_index.shift_out(1);
return;
}

hir::TyTraitObject(ref bounds, _) => for bound in bounds {
self.depth += 1;
self.current_index.shift_in(1);
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
self.depth -= 1;
self.current_index.shift_out(1);
},

hir::TyRptr(ref lifetime, _) => {
Expand All @@ -135,11 +135,11 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
) => {
debug!(
"LateBoundAnon depth = {:?} anon_index = {:?} br_index={:?}",
debruijn_index.depth,
debruijn_index,
anon_index,
br_index
);
if debruijn_index.depth == self.depth && anon_index == br_index {
if debruijn_index == self.current_index && anon_index == br_index {
self.found_type = Some(arg);
return; // we can stop visiting now
}
Expand Down Expand Up @@ -170,11 +170,11 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
) => {
debug!(
"FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
debruijn_index.depth
debruijn_index
);
debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
debug!("def_id={:?}", def_id);
if debruijn_index.depth == self.depth && id == def_id {
if debruijn_index == self.current_index && id == def_id {
self.found_type = Some(arg);
return; // we can stop visiting now
}
Expand All @@ -196,7 +196,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
tcx: self.tcx,
found_it: false,
bound_region: self.bound_region,
depth: self.depth,
current_index: self.current_index,
};
intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
// this will visit only outermost type
Expand All @@ -222,7 +222,7 @@ struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
found_it: bool,
bound_region: ty::BoundRegion,
depth: u32,
current_index: ty::DebruijnIndex,
}

impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
Expand All @@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
match (self.tcx.named_region(hir_id), self.bound_region) {
// the lifetime of the TyPath!
(Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
if debruijn_index.depth == self.depth && anon_index == br_index {
if debruijn_index == self.current_index && anon_index == br_index {
self.found_it = true;
return;
}
Expand All @@ -257,11 +257,11 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
(Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
debug!(
"FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
debruijn_index.depth
debruijn_index,
);
debug!("id={:?}", id);
debug!("def_id={:?}", def_id);
if debruijn_index.depth == self.depth && id == def_id {
if debruijn_index == self.current_index && id == def_id {
self.found_it = true;
return; // we can stop visiting now
}
Expand Down
11 changes: 7 additions & 4 deletions src/librustc/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
{
for (a_br, a_r) in a_map {
if *a_r == r {
return infcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1), *a_br));
return infcx.tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::INNERMOST,
*a_br));
}
}
span_bug!(
Expand Down Expand Up @@ -473,7 +474,7 @@ fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
_ => true
});

fldr(region, ty::DebruijnIndex::new(current_depth))
fldr(region, current_depth)
})
}

Expand Down Expand Up @@ -734,7 +735,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// trait checking, and all of the skolemized regions
// appear inside predicates, which always have
// binders, so this assert is satisfied.
assert!(current_depth > 1);
assert!(current_depth > ty::DebruijnIndex::INNERMOST);

// since leak-check passed, this skolemized region
// should only have incoming edges from variables
Expand All @@ -750,7 +751,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
r, br);

self.tcx.mk_region(ty::ReLateBound(
ty::DebruijnIndex::new(current_depth - 1), br.clone()))
current_depth.shifted_out(1),
br.clone(),
))
}
}
});
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(macro_at_most_once_rep)]
#![feature(inclusive_range_methods)]

#![recursion_limit="512"]

Expand Down
38 changes: 17 additions & 21 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl Region {
}

fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
let depth = ty::DebruijnIndex::new(1);
let depth = ty::DebruijnIndex::INNERMOST;
let def_id = hir_map.local_def_id(def.lifetime.id);
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
(def.lifetime.name, Region::LateBound(depth, def_id, origin))
Expand All @@ -107,7 +107,7 @@ impl Region {
fn late_anon(index: &Cell<u32>) -> Region {
let i = index.get();
index.set(i + 1);
let depth = ty::DebruijnIndex::new(1);
let depth = ty::DebruijnIndex::INNERMOST;
Region::LateBoundAnon(depth, i)
}

Expand All @@ -123,29 +123,25 @@ impl Region {

fn shifted(self, amount: u32) -> Region {
match self {
Region::LateBound(depth, id, origin) => {
Region::LateBound(depth.shifted(amount), id, origin)
Region::LateBound(debruijn, id, origin) => {
Region::LateBound(debruijn.shifted_in(amount), id, origin)
}
Region::LateBoundAnon(depth, index) => {
Region::LateBoundAnon(depth.shifted(amount), index)
Region::LateBoundAnon(debruijn, index) => {
Region::LateBoundAnon(debruijn.shifted_in(amount), index)
}
_ => self,
}
}

fn from_depth(self, depth: u32) -> Region {
fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region {
match self {
Region::LateBound(debruijn, id, origin) => Region::LateBound(
ty::DebruijnIndex {
depth: debruijn.depth - (depth - 1),
},
debruijn.shifted_out_to_binder(binder),
id,
origin,
),
Region::LateBoundAnon(debruijn, index) => Region::LateBoundAnon(
ty::DebruijnIndex {
depth: debruijn.depth - (depth - 1),
},
debruijn.shifted_out_to_binder(binder),
index,
),
_ => self,
Expand Down Expand Up @@ -1858,7 +1854,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
.map(|(i, input)| {
let mut gather = GatherLifetimes {
map: self.map,
binder_depth: 1,
outer_index: ty::DebruijnIndex::INNERMOST,
have_bound_regions: false,
lifetimes: FxHashSet(),
};
Expand Down Expand Up @@ -1899,7 +1895,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {

struct GatherLifetimes<'a> {
map: &'a NamedRegionMap,
binder_depth: u32,
outer_index: ty::DebruijnIndex,
have_bound_regions: bool,
lifetimes: FxHashSet<Region>,
}
Expand All @@ -1911,7 +1907,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {

fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyBareFn(_) = ty.node {
self.binder_depth += 1;
self.outer_index.shift_in(1);
}
if let hir::TyTraitObject(ref bounds, ref lifetime) = ty.node {
for bound in bounds {
Expand All @@ -1927,7 +1923,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(self, ty);
}
if let hir::TyBareFn(_) = ty.node {
self.binder_depth -= 1;
self.outer_index.shift_out(1);
}
}

Expand All @@ -1946,22 +1942,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
trait_ref: &hir::PolyTraitRef,
modifier: hir::TraitBoundModifier,
) {
self.binder_depth += 1;
self.outer_index.shift_in(1);
intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
self.binder_depth -= 1;
self.outer_index.shift_out(1);
}

fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.id) {
match lifetime {
Region::LateBound(debruijn, _, _) | Region::LateBoundAnon(debruijn, _)
if debruijn.depth < self.binder_depth =>
if debruijn < self.outer_index =>
{
self.have_bound_regions = true;
}
_ => {
self.lifetimes
.insert(lifetime.from_depth(self.binder_depth));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I suspect this is where the bug is coming from. The binder_depth in the "before code" is equal to index, but (if you look at the definition of from_depth) you will see that used to be computing adjusting by depth - 1, basically.

I think the way I would want to compute the "depth" by giving two debruijn indices. In particular, we might do something like self.outer_index.depth_from(INNERMOST), where we have:

impl DebruijnIndex {
    /// Assuming that these two debruijn indices are both in scope,
    /// returns the number of binding levels *between* them.
    /// This is often used if `outer` represents some starting binding
    /// and `self` represents the current innermost binding; it would then
    /// compute the number of bindings passed over so far.
    ///
    /// As the name suggests, `outer` is assumed  to be the
    /// outermost depth of the two.
    fn depth_from(self, outer: DebruijnIndex) -> usize {
        assert!(self.index >= other.index); // or return the absolute value
        self.index - other.index
    }
}

.insert(lifetime.shifted_out_to_binder(self.outer_index));
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
let ty_struct = TyS {
sty: st,
flags: flags.flags,
region_depth: flags.depth,
outer_exclusive_binder: flags.outer_exclusive_binder,
};

// Make sure we don't end up with inference
Expand All @@ -205,7 +205,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
let ty_struct = TyS {
sty: st,
flags: flags.flags,
region_depth: flags.depth,
outer_exclusive_binder: flags.outer_exclusive_binder,
};

// This is safe because all the types the ty_struct can point to
Expand Down
36 changes: 24 additions & 12 deletions src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ use ty::{self, Ty, TypeFlags, TypeFoldable};
pub struct FlagComputation {
pub flags: TypeFlags,

// maximum depth of any bound region that we have seen thus far
pub depth: u32,
// see `TyS::outer_exclusive_binder` for details
pub outer_exclusive_binder: ty::DebruijnIndex,
}

impl FlagComputation {
fn new() -> FlagComputation {
FlagComputation { flags: TypeFlags::empty(), depth: 0 }
FlagComputation {
flags: TypeFlags::empty(),
outer_exclusive_binder: ty::DebruijnIndex::INNERMOST,
}
}

pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation {
Expand All @@ -35,10 +38,17 @@ impl FlagComputation {
self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
}

fn add_depth(&mut self, depth: u32) {
if depth > self.depth {
self.depth = depth;
}
/// indicates that `self` refers to something at binding level `binder`
fn add_binder(&mut self, binder: ty::DebruijnIndex) {
let exclusive_binder = binder.shifted_in(1);
self.add_exclusive_binder(exclusive_binder);
}

/// indicates that `self` refers to something *inside* binding
/// level `binder` -- not bound by `binder`, but bound by the next
/// binder internal to it
fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) {
self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder);
}

/// Adds the flags/depth from a set of types that appear within the current type, but within a
Expand All @@ -49,9 +59,11 @@ impl FlagComputation {
// The types that contributed to `computation` occurred within
// a region binder, so subtract one from the region depth
// within when adding the depth to `self`.
let depth = computation.depth;
if depth > 0 {
self.add_depth(depth - 1);
let outer_exclusive_binder = computation.outer_exclusive_binder;
if outer_exclusive_binder > ty::DebruijnIndex::INNERMOST {
self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
} else {
// otherwise, this binder captures nothing
}
}

Expand Down Expand Up @@ -194,7 +206,7 @@ impl FlagComputation {

fn add_ty(&mut self, ty: Ty) {
self.add_flags(ty.flags);
self.add_depth(ty.region_depth);
self.add_exclusive_binder(ty.outer_exclusive_binder);
}

fn add_tys(&mut self, tys: &[Ty]) {
Expand All @@ -215,7 +227,7 @@ impl FlagComputation {
fn add_region(&mut self, r: ty::Region) {
self.add_flags(r.type_flags());
if let ty::ReLateBound(debruijn, _) = *r {
self.add_depth(debruijn.depth);
self.add_binder(debruijn);
}
}

Expand Down
Loading