Remove `ReCanonical` in favor of `ReLateBound`

This commit is contained in:
scalexm 2018-10-24 10:29:42 +02:00
parent 1f8de94f3b
commit 45be1ac0fc
23 changed files with 98 additions and 101 deletions

View File

@ -100,9 +100,6 @@ for ty::RegionKind {
ty::ReEmpty => {
// No variant fields to hash for these ...
}
ty::ReCanonical(c) => {
c.hash_stable(hcx, hasher);
}
ty::ReLateBound(db, ty::BrAnon(i)) => {
db.hash_stable(hcx, hasher);
i.hash_stable(hcx, hasher);

View File

@ -331,8 +331,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
| ty::ReErased => self.canonicalize_region_mode
.canonicalize_free_region(self, r),
ty::ReClosureBound(..) | ty::ReCanonical(_) => {
bug!("canonical region encountered during canonicalization")
ty::ReClosureBound(..) => {
bug!("closure bound region encountered during canonicalization")
}
}
}
@ -407,12 +407,6 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
where
V: TypeFoldable<'tcx> + Lift<'gcx>,
{
debug_assert!(
!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS),
"canonicalizing a canonical value: {:?}",
value,
);
let needs_canonical_flags = if canonicalize_region_mode.any() {
TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
} else {
@ -569,7 +563,11 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
let var = self.canonical_var(info, r.into());
self.tcx().mk_region(ty::ReCanonical(var))
let region = ty::ReLateBound(
self.binder_index,
ty::BoundRegion::BrAnon(var.index() as u32)
);
self.tcx().mk_region(region)
}
/// Given a type variable `ty_var` of the given kind, first check

View File

@ -20,7 +20,7 @@
//! - a map M (of type `CanonicalVarValues`) from those canonical
//! variables back to the original.
//!
//! We can then do queries using T2. These will give back constriants
//! We can then do queries using T2. These will give back constraints
//! on the canonical variables which can be translated, using the map
//! M, into constraints in our source context. This process of
//! translating the results back is done by the

View File

@ -308,11 +308,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
// ...also include the other query region constraints from the query.
output_query_region_constraints.extend(
query_response.value.region_constraints.iter().filter_map(|r_c| {
let &ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
let k1 = substitute_value(self.tcx, &result_subst, &k1);
let r2 = substitute_value(self.tcx, &result_subst, &r2);
if k1 != r2.into() {
Some(ty::Binder::bind(ty::OutlivesPredicate(k1, r2)))
let ty::OutlivesPredicate(k1, r2) = r_c.skip_binder(); // reconstructed below
let k1 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*k1));
let r2 = substitute_value(self.tcx, &result_subst, &ty::Binder::bind(*r2));
if k1 != r2.map_bound(|bound| bound.into()) {
let predicate = ty::OutlivesPredicate(*k1.skip_binder(), *r2.skip_binder());
Some(ty::Binder::bind(predicate))
} else {
None
}
@ -433,16 +434,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
UnpackedKind::Type(result_value) => {
// e.g., here `result_value` might be `?0` in the example above...
if let ty::Bound(b) = result_value.sty {
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(b.index, ty::INNERMOST);
// in which case we would set `canonical_vars[0]` to `Some(?U)`.
opt_values[b.var] = Some(*original_value);
}
}
UnpackedKind::Lifetime(result_value) => {
// e.g., here `result_value` might be `'?1` in the example above...
if let &ty::RegionKind::ReCanonical(index) = result_value {
// in which case we would set `canonical_vars[0]` to `Some('static)`.
opt_values[index] = Some(*original_value);
if let &ty::RegionKind::ReLateBound(index, br) = result_value {
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(index, ty::INNERMOST);
opt_values[br.as_bound_var()] = Some(*original_value);
}
}
}
@ -525,21 +531,23 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
.iter()
.map(move |constraint| {
let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
let k1 = substitute_value(self.tcx, result_subst, k1);
let r2 = substitute_value(self.tcx, result_subst, r2);
let k1 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*k1));
let r2 = substitute_value(self.tcx, result_subst, &ty::Binder::bind(*r2));
Obligation::new(
cause.clone(),
param_env,
match k1.unpack() {
match k1.skip_binder().unpack() {
UnpackedKind::Lifetime(r1) => ty::Predicate::RegionOutlives(
ty::Binder::dummy(
ty::OutlivesPredicate(r1, r2)
)),
ty::Binder::bind(
ty::OutlivesPredicate(r1, r2.skip_binder())
)
),
UnpackedKind::Type(t1) => ty::Predicate::TypeOutlives(
ty::Binder::dummy(ty::OutlivesPredicate(
t1, r2
)))
ty::Binder::bind(
ty::OutlivesPredicate(t1, r2.skip_binder())
)
),
}
)
})
@ -621,11 +629,11 @@ pub fn make_query_outlives<'tcx>(
}
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
})
.map(ty::Binder::dummy) // no bound regions in the code above
.map(ty::Binder::dummy) // no bound vars in the code above
.chain(
outlives_obligations
.map(|(ty, r)| ty::OutlivesPredicate(ty.into(), r))
.map(ty::Binder::dummy), // no bound regions in the code above
.map(ty::Binder::dummy) // no bound vars in the code above
)
.collect();

View File

@ -19,7 +19,7 @@
use infer::canonical::{Canonical, CanonicalVarValues};
use ty::fold::{TypeFoldable, TypeFolder};
use ty::subst::UnpackedKind;
use ty::{self, Ty, TyCtxt, TypeFlags};
use ty::{self, Ty, TyCtxt};
impl<'tcx, V> Canonical<'tcx, V> {
/// Instantiate the wrapped value, replacing each canonical value
@ -64,9 +64,9 @@ where
T: TypeFoldable<'tcx>,
{
if var_values.var_values.is_empty() {
debug_assert!(!value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS));
value.clone()
} else if !value.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
} else if !value.has_escaping_bound_vars() {
// There are no bound vars to substitute.
value.clone()
} else {
value.fold_with(&mut CanonicalVarValuesSubst {
@ -104,8 +104,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
match self.var_values.var_values[b.var].unpack() {
UnpackedKind::Type(ty) => ty::fold::shift_vars(
self.tcx,
self.binder_index.index() as u32,
&ty
&ty,
self.binder_index.index() as u32
),
r => bug!("{:?} is a type but value is {:?}", b, r),
}
@ -114,7 +114,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
}
}
_ => {
if !t.has_type_flags(TypeFlags::HAS_CANONICAL_VARS) {
if !t.has_vars_bound_at_or_above(self.binder_index) {
// Nothing more to substitute.
t
} else {
t.super_fold_with(self)
@ -125,10 +126,20 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match r {
ty::RegionKind::ReCanonical(c) => match self.var_values.var_values[*c].unpack() {
UnpackedKind::Lifetime(l) => l,
r => bug!("{:?} is a region but value is {:?}", c, r),
},
ty::RegionKind::ReLateBound(index, br) => {
if *index == self.binder_index {
match self.var_values.var_values[br.as_bound_var()].unpack() {
UnpackedKind::Lifetime(l) => ty::fold::shift_region(
self.tcx,
l,
self.binder_index.index() as u32,
),
r => bug!("{:?} is a region but value is {:?}", br, r),
}
} else {
r
}
}
_ => r.super_fold_with(self),
}
}

View File

@ -485,7 +485,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
}
}
ty::ReCanonical(..) |
ty::ReClosureBound(..) => {
span_bug!(
self.span,

View File

@ -152,7 +152,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
// We shouldn't encounter an error message with ReClosureBound.
ty::ReCanonical(..) | ty::ReClosureBound(..) => {
ty::ReClosureBound(..) => {
bug!("encountered unexpected ReClosureBound: {:?}", region,);
}
};

View File

@ -114,7 +114,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
self.tcx().types.re_erased
}
ty::ReCanonical(..) |
ty::ReClosureBound(..) => {
bug!(
"encountered unexpected region: {:?}",

View File

@ -260,9 +260,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
let tcx = self.tcx();
match (a, b) {
(&ty::ReCanonical(..), _)
| (_, &ty::ReCanonical(..))
| (&ty::ReClosureBound(..), _)
(&ty::ReClosureBound(..), _)
| (_, &ty::ReClosureBound(..))
| (&ReLateBound(..), _)
| (_, &ReLateBound(..))

View File

@ -833,10 +833,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
ty::ReCanonical(..) => bug!(
"region_universe(): encountered canonical region {:?}",
region
),
}
}

View File

@ -116,7 +116,6 @@ impl FlagComputation {
}
&ty::Bound(bound_ty) => {
self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
self.add_binder(bound_ty.index);
}
@ -127,7 +126,6 @@ impl FlagComputation {
ty::FreshTy(_) |
ty::FreshIntTy(_) |
ty::FreshFloatTy(_) => {
self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
}
ty::TyVar(_) |

View File

@ -672,10 +672,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
}
}
pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
pub fn shift_region<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
region: ty::Region<'tcx>,
amount: u32
) -> ty::Region<'tcx> {
match region {
ty::ReLateBound(debruijn, br) => {
ty::ReLateBound(debruijn.shifted_in(amount), br)
ty::ReLateBound(debruijn, br) if amount > 0 => {
tcx.mk_region(ty::ReLateBound(debruijn.shifted_in(amount), *br))
}
_ => {
region
@ -685,8 +689,8 @@ pub fn shift_region(region: ty::RegionKind, amount: u32) -> ty::RegionKind {
pub fn shift_vars<'a, 'gcx, 'tcx, T>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
amount: u32,
value: &T
value: &T,
amount: u32
) -> T where T: TypeFoldable<'tcx> {
debug!("shift_vars(value={:?}, amount={})",
value, amount);

View File

@ -463,13 +463,9 @@ bitflags! {
// Currently we can't normalize projections w/ bound regions.
const HAS_NORMALIZABLE_PROJECTION = 1 << 12;
// Set if this includes a "canonical" type or region var --
// ought to be true only for the results of canonicalization.
const HAS_CANONICAL_VARS = 1 << 13;
/// Does this have any `ReLateBound` regions? Used to check
/// if a global bound is safe to evaluate.
const HAS_RE_LATE_BOUND = 1 << 14;
const HAS_RE_LATE_BOUND = 1 << 13;
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
@ -490,7 +486,6 @@ bitflags! {
TypeFlags::HAS_TY_CLOSURE.bits |
TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
TypeFlags::KEEP_IN_LOCAL_TCX.bits |
TypeFlags::HAS_CANONICAL_VARS.bits |
TypeFlags::HAS_RE_LATE_BOUND.bits;
}
}

View File

@ -77,6 +77,17 @@ impl BoundRegion {
_ => false,
}
}
/// When canonicalizing, we replace unbound inference variables and free
/// regions with anonymous late bound regions. This method asserts that
/// we have an anonymous late bound region, which hence may refer to
/// a canonical variable.
pub fn as_bound_var(&self) -> BoundVar {
match *self {
BoundRegion::BrAnon(var) => BoundVar::from_u32(var),
_ => bug!("bound region is not anonymous"),
}
}
}
/// N.B., If you change this, you'll probably want to change the corresponding
@ -758,11 +769,11 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
}
}
/// Binder is a binder for higher-ranked lifetimes. It is part of the
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
/// (which would be represented by the type `PolyTraitRef ==
/// Binder<TraitRef>`). Note that when we instantiate,
/// erase, or otherwise "discharge" these bound regions, we change the
/// erase, or otherwise "discharge" these bound vars, we change the
/// type from `Binder<T>` to just `T` (see
/// e.g. `liberate_late_bound_regions`).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@ -770,7 +781,7 @@ pub struct Binder<T>(T);
impl<T> Binder<T> {
/// Wraps `value` in a binder, asserting that `value` does not
/// contain any bound regions that would be bound by the
/// contain any bound vars that would be bound by the
/// binder. This is commonly used to 'inject' a value T into a
/// different binding level.
pub fn dummy<'tcx>(value: T) -> Binder<T>
@ -780,9 +791,8 @@ impl<T> Binder<T> {
Binder(value)
}
/// Wraps `value` in a binder, binding late-bound regions (if any).
pub fn bind<'tcx>(value: T) -> Binder<T>
{
/// Wraps `value` in a binder, binding higher-ranked vars (if any).
pub fn bind<'tcx>(value: T) -> Binder<T> {
Binder(value)
}
@ -1169,9 +1179,6 @@ pub enum RegionKind {
/// `ClosureRegionRequirements` that are produced by MIR borrowck.
/// See `ClosureRegionRequirements` for more details.
ReClosureBound(RegionVid),
/// Canonicalized region, used only when preparing a trait query.
ReCanonical(BoundVar),
}
impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
@ -1381,7 +1388,6 @@ impl RegionKind {
RegionKind::ReEmpty => false,
RegionKind::ReErased => false,
RegionKind::ReClosureBound(..) => false,
RegionKind::ReCanonical(..) => false,
}
}
@ -1468,10 +1474,6 @@ impl RegionKind {
}
ty::ReErased => {
}
ty::ReCanonical(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_CANONICAL_VARS;
}
ty::ReClosureBound(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
}

View File

@ -475,8 +475,8 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
}
/// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs
/// when we are substituting a type with escaping regions into a context where we have passed
/// through region binders. That's quite a mouthful. Let's see an example:
/// when we are substituting a type with escaping bound vars into a context where we have
/// passed through binders. That's quite a mouthful. Let's see an example:
///
/// ```
/// type Func<A> = fn(A);
@ -524,7 +524,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
return ty;
}
let result = ty::fold::shift_vars(self.tcx(), self.binders_passed, &ty);
let result = ty::fold::shift_vars(self.tcx(), &ty, self.binders_passed);
debug!("shift_vars: shifted result = {:?}", result);
result
@ -534,7 +534,7 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
if self.binders_passed == 0 || !region.has_escaping_bound_vars() {
return region;
}
self.tcx().mk_region(ty::fold::shift_region(*region, self.binders_passed))
ty::fold::shift_region(self.tcx, region, self.binders_passed)
}
}
@ -556,7 +556,8 @@ impl CanonicalUserSubsts<'tcx> {
self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
match kind.unpack() {
UnpackedKind::Type(ty) => match ty.sty {
ty::Bound(ref b) => {
ty::Bound(b) => {
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(b.index, ty::INNERMOST);
cvar == b.var
}
@ -564,7 +565,11 @@ impl CanonicalUserSubsts<'tcx> {
},
UnpackedKind::Lifetime(r) => match r {
ty::ReCanonical(cvar1) => cvar == *cvar1,
ty::ReLateBound(index, br) => {
// We only allow a `ty::INNERMOST` index in substitutions.
assert_eq!(*index, ty::INNERMOST);
cvar == br.as_bound_var()
}
_ => false,
},
}

View File

@ -790,9 +790,6 @@ define_print! {
ty::ReEarlyBound(ref data) => {
write!(f, "{}", data.name)
}
ty::ReCanonical(_) => {
write!(f, "'_")
}
ty::ReLateBound(_, br) |
ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
@ -860,10 +857,6 @@ define_print! {
write!(f, "{:?}", vid)
}
ty::ReCanonical(c) => {
write!(f, "'?{}", c.index())
}
ty::RePlaceholder(placeholder) => {
write!(f, "RePlaceholder({:?})", placeholder)
}

View File

@ -426,7 +426,6 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
// These cannot exist in borrowck
RegionKind::ReVar(..) |
RegionKind::ReCanonical(..) |
RegionKind::RePlaceholder(..) |
RegionKind::ReClosureBound(..) |
RegionKind::ReErased => span_bug!(borrow_span,

View File

@ -363,7 +363,6 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
ty::ReStatic => self.item_ub,
ty::ReCanonical(_) |
ty::ReEmpty |
ty::ReClosureBound(..) |
ty::ReLateBound(..) |

View File

@ -277,8 +277,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
| ty::RePlaceholder(..)
| ty::ReEmpty
| ty::ReErased
| ty::ReClosureBound(..)
| ty::ReCanonical(..) => None,
| ty::ReClosureBound(..) => None,
}
}

View File

@ -1748,7 +1748,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
self.region_bounds.iter().map(|&(region_bound, span)| {
// account for the binder being introduced below; no need to shift `param_ty`
// because, at present at least, it can only refer to early-bound regions
let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
let outlives = ty::OutlivesPredicate(param_ty, region_bound);
(ty::Binder::dummy(outlives).to_predicate(), span)
}).chain(

View File

@ -167,7 +167,6 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool
RegionKind::ReEmpty
| RegionKind::ReErased
| RegionKind::ReClosureBound(..)
| RegionKind::ReCanonical(..)
| RegionKind::ReScope(..)
| RegionKind::ReVar(..)
| RegionKind::RePlaceholder(..)

View File

@ -427,7 +427,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
// way early-bound regions do, so we skip them here.
}
ty::ReCanonical(_) |
ty::ReFree(..) |
ty::ReClosureBound(..) |
ty::ReScope(..) |

View File

@ -1260,7 +1260,6 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
ty::RePlaceholder(..) |
ty::ReEmpty |
ty::ReClosureBound(_) |
ty::ReCanonical(_) |
ty::ReErased => None
}
}