remove use of depth from TyS and replace with a debruijn index
Co-authored-by: csmoe <35686186+csmoe@users.noreply.github.com>
This commit is contained in:
parent
8f15d1ea25
commit
7e15e0baff
6 changed files with 74 additions and 34 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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]) {
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,20 +63,22 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
|||
self.super_visit_with(visitor)
|
||||
}
|
||||
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.visit_with(&mut HasEscapingRegionsVisitor { depth: depth })
|
||||
}
|
||||
|
||||
/// True if `self` has any late-bound regions that are either
|
||||
/// bound by `binder` or bound by some binder outside of `binder`.
|
||||
/// If `binder` is `ty::DebruijnIndex::INNERMOST`, this indicates whether
|
||||
/// there are any late-bound regions that appear free.
|
||||
fn has_regions_bound_by_or_escaping(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.has_regions_escaping_depth(binder.depth - 1)
|
||||
fn has_regions_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.visit_with(&mut HasEscapingRegionsVisitor { outer_index: binder })
|
||||
}
|
||||
|
||||
/// True if this `self` has any regions that escape `binder` (and
|
||||
/// hence are not bound by it).
|
||||
fn has_regions_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
|
||||
self.has_regions_bound_at_or_above(binder.shifted_in(1))
|
||||
}
|
||||
|
||||
fn has_escaping_regions(&self) -> bool {
|
||||
self.has_regions_escaping_depth(0)
|
||||
self.has_regions_bound_at_or_above(ty::DebruijnIndex::INNERMOST)
|
||||
}
|
||||
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
|
|
@ -523,7 +525,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionReplacer<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !t.has_regions_bound_by_or_escaping(self.current_index) {
|
||||
if !t.has_regions_bound_at_or_above(self.current_index) {
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
@ -623,23 +625,32 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
/// represent the scope to which it is attached, etc. An escaping region represents a bound region
|
||||
/// for which this processing has not yet been done.
|
||||
struct HasEscapingRegionsVisitor {
|
||||
depth: u32,
|
||||
/// Anything bound by `outer_index` or "above" is escaping
|
||||
outer_index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasEscapingRegionsVisitor {
|
||||
fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &Binder<T>) -> bool {
|
||||
self.depth += 1;
|
||||
self.outer_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.depth -= 1;
|
||||
self.outer_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||
t.region_depth > self.depth
|
||||
// If the outer-exclusive-binder is *strictly greater* than
|
||||
// `outer_index`, that means that `t` contains some content
|
||||
// bound at `outer_index` or above (because
|
||||
// `outer_exclusive_binder` is always 1 higher than the
|
||||
// content in `t`). Therefore, `t` has some escaping regions.
|
||||
t.outer_exclusive_binder > self.outer_index
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||
r.escapes_depth(self.depth)
|
||||
// If the region is bound by `outer_index` or anything outside
|
||||
// of outer index, then it escapes the binders we have
|
||||
// visited.
|
||||
r.bound_at_or_above_binder(self.outer_index)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -488,8 +488,24 @@ pub struct TyS<'tcx> {
|
|||
pub sty: TypeVariants<'tcx>,
|
||||
pub flags: TypeFlags,
|
||||
|
||||
// the maximal depth of any bound regions appearing in this type.
|
||||
region_depth: u32,
|
||||
/// This is a kind of confusing thing: it stores the smallest
|
||||
/// binder such that
|
||||
///
|
||||
/// (a) the binder itself captures nothing but
|
||||
/// (b) all the late-bound things within the type are captured
|
||||
/// by some sub-binder.
|
||||
///
|
||||
/// So, for a type without any late-bound things, like `u32`, this
|
||||
/// will be INNERMOST, because that is the innermost binder that
|
||||
/// captures nothing. But for a type `&'D u32`, where `'D` is a
|
||||
/// late-bound region with debruijn index D, this would be D+1 --
|
||||
/// the binder itself does not capture D, but D is captured by an
|
||||
/// inner binder.
|
||||
///
|
||||
/// We call this concept an "exclusive" binder D (because all
|
||||
/// debruijn indices within the type are contained within `0..D`
|
||||
/// (exclusive)).
|
||||
outer_exclusive_binder: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'tcx> Ord for TyS<'tcx> {
|
||||
|
|
@ -560,7 +576,8 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::TyS<'gcx> {
|
|||
// The other fields just provide fast access to information that is
|
||||
// also contained in `sty`, so no need to hash them.
|
||||
flags: _,
|
||||
region_depth: _,
|
||||
|
||||
outer_exclusive_binder: _,
|
||||
} = *self;
|
||||
|
||||
sty.hash_stable(hcx, hasher);
|
||||
|
|
|
|||
|
|
@ -1332,9 +1332,9 @@ impl RegionKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn escapes_depth(&self, depth: u32) -> bool {
|
||||
pub fn bound_at_or_above_binder(&self, index: DebruijnIndex) -> bool {
|
||||
match *self {
|
||||
ty::ReLateBound(debruijn, _) => debruijn.depth > depth,
|
||||
ty::ReLateBound(debruijn, _) => debruijn >= index,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ use rustc::infer::LateBoundRegionConversionTime;
|
|||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::traits::error_reporting::ArgKind;
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::TypeFoldable;
|
||||
use std::cmp;
|
||||
use std::iter;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
|
@ -465,7 +465,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// Create a `PolyFnSig`. Note the oddity that late bound
|
||||
// regions appearing free in `expected_sig` are now bound up
|
||||
// in this binder we are creating.
|
||||
assert!(!expected_sig.sig.has_regions_escaping_depth(1));
|
||||
assert!(!expected_sig.sig.has_regions_bound_above(ty::DebruijnIndex::INNERMOST));
|
||||
let bound_sig = ty::Binder::bind(self.tcx.mk_fn_sig(
|
||||
expected_sig.sig.inputs().iter().cloned(),
|
||||
expected_sig.sig.output(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue