Auto merge of #34012 - eddyb:tick-erased, r=nikomatsakis

rustc: add ReErased to be used by trait selection, MIR and trans.

`ReErased` replaces `ReStatic` (i.e. `'static`) for erasing regions.
Using a distinct lifetime helps prevent accidental mix-ups between the two.
It also allows cleaner type printing (see test changes), including in symbol names:
```rust
str..pattern..CharSearcher$LT$$u27$static$GT$::drop.30560::h840c2f2afc03bbea // before
str..pattern..CharSearcher::drop.30561::h6bd31d2af614377a // after
```
Not that we should be producing symbols this way, but it's still better.
This commit is contained in:
bors 2016-06-07 00:04:53 -07:00
commit f35255038b
28 changed files with 92 additions and 71 deletions

View file

@ -337,8 +337,10 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
match r {
// Never make variables for regions bound within the type itself.
ty::ReLateBound(..) => { return r; }
// Never make variables for regions bound within the type itself,
// nor for erased regions.
ty::ReLateBound(..) |
ty::ReErased => { return r; }
// Early-bound regions should really have been substituted away before
// we get to this point.

View file

@ -216,7 +216,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
//
// We shouldn't really be having unification failures with ReVar
// and ReLateBound though.
ty::ReSkolemized(..) | ty::ReVar(_) | ty::ReLateBound(..) => {
ty::ReSkolemized(..) |
ty::ReVar(_) |
ty::ReLateBound(..) |
ty::ReErased => {
(format!("lifetime {:?}", region), None)
}
};

View file

@ -23,7 +23,7 @@
//! error messages or in any other form. Freshening is only really useful as an internal detail.
//!
//! __An important detail concerning regions.__ The freshener also replaces *all* regions with
//! 'static. The reason behind this is that, in general, we do not take region relationships into
//! 'erased. The reason behind this is that, in general, we do not take region relationships into
//! account when making type-overloaded decisions. This is important because of the design of the
//! region inferencer, which is not based on unification but rather on accumulating and then
//! solving a set of constraints. In contrast, the type inferencer assigns a value to each type
@ -96,9 +96,10 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::ReScope(_) |
ty::ReVar(_) |
ty::ReSkolemized(..) |
ty::ReEmpty => {
// replace all free regions with 'static
ty::ReStatic
ty::ReEmpty |
ty::ReErased => {
// replace all free regions with 'erased
ty::ReErased
}
}
}

View file

@ -25,7 +25,7 @@ use rustc_data_structures::unify::{self, UnificationTable};
use middle::free_region::FreeRegionMap;
use ty::{self, Ty, TyCtxt};
use ty::{BoundRegion, Region, RegionVid};
use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound};
use ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound, ReErased};
use ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
use std::cell::{Cell, RefCell};
@ -918,8 +918,10 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
(ReLateBound(..), _) |
(_, ReLateBound(..)) |
(ReEarlyBound(..), _) |
(_, ReEarlyBound(..)) => {
bug!("cannot relate bound region: LUB({:?}, {:?})", a, b);
(_, ReEarlyBound(..)) |
(ReErased, _) |
(_, ReErased) => {
bug!("cannot relate region: LUB({:?}, {:?})", a, b);
}
(ReStatic, _) | (_, ReStatic) => {

View file

@ -187,7 +187,7 @@ impl FlagComputation {
}
ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); }
ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); }
ty::ReStatic => {}
ty::ReStatic | ty::ReErased => {}
_ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); }
}

View file

@ -421,12 +421,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
collector.regions
}
/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
/// Replace any late-bound regions bound in `value` with `'erased`. Useful in trans but also
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<T>(self, value: &Binder<T>) -> T
where T : TypeFoldable<'tcx>
{
self.replace_late_bound_regions(value, |_| ty::ReStatic).0
self.replace_late_bound_regions(value, |_| ty::ReErased).0
}
/// Rewrite any late-bound regions so that they are anonymous. Region numbers are
@ -547,15 +547,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
// because late-bound regions affect subtyping, we can't
// erase the bound/free distinction, but we can replace
// all free regions with 'static.
// all free regions with 'erased.
//
// Note that we *CAN* replace early-bound regions -- the
// type system never "sees" those, they get substituted
// away. In trans, they will always be erased to 'static
// away. In trans, they will always be erased to 'erased
// whenever a substitution occurs.
match r {
ty::ReLateBound(..) => r,
_ => ty::ReStatic
_ => ty::ReErased
}
}
}
@ -651,7 +651,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
// does this represent a region that cannot be named
// in a global way? used in fulfillment caching.
match r {
ty::ReStatic | ty::ReEmpty => {}
ty::ReStatic | ty::ReEmpty | ty::ReErased => {}
_ => return true,
}
}

View file

@ -705,6 +705,9 @@ pub enum Region {
/// The only way to get an instance of ReEmpty is to have a region
/// variable with no constraints.
ReEmpty,
/// Erased region, used by trait selection, in MIR and during trans.
ReErased,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]

View file

@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
pub fn erase_regions(self) -> Substs<'tcx> {
let Substs { types, regions } = self;
let regions = regions.map(|_| ty::ReStatic);
let regions = regions.map(|_| ty::ReErased);
Substs { types: types, regions: regions }
}

View file

@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let region = |state: &mut SipHasher, r: ty::Region| {
match r {
ty::ReStatic => {}
ty::ReStatic | ty::ReErased => {}
ty::ReLateBound(db, ty::BrAnon(i)) => {
db.hash(state);
i.hash(state);

View file

@ -148,28 +148,36 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
write!(f, "{}", cont)
}
};
let print_region = |f: &mut fmt::Formatter, region: &ty::Region| -> _ {
if verbose {
write!(f, "{:?}", region)
} else {
let s = region.to_string();
if s.is_empty() {
// This happens when the value of the region
// parameter is not easily serialized. This may be
// because the user omitted it in the first place,
// or because it refers to some block in the code,
// etc. I'm not sure how best to serialize this.
write!(f, "'_")
let print_regions = |f: &mut fmt::Formatter, start: &str, regions: &[ty::Region]| {
// Don't print any regions if they're all erased.
if regions.iter().all(|r| *r == ty::ReErased) {
return Ok(());
}
for region in regions {
start_or_continue(f, start, ", ")?;
if verbose {
write!(f, "{:?}", region)?;
} else {
write!(f, "{}", s)
let s = region.to_string();
if s.is_empty() {
// This happens when the value of the region
// parameter is not easily serialized. This may be
// because the user omitted it in the first place,
// or because it refers to some block in the code,
// etc. I'm not sure how best to serialize this.
write!(f, "'_")?;
} else {
write!(f, "{}", s)?;
}
}
}
Ok(())
};
for region in substs.regions.get_slice(subst::TypeSpace) {
start_or_continue(f, "<", ", ")?;
print_region(f, region)?;
}
print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?;
let num_supplied_defaults = if verbose {
0
@ -211,10 +219,7 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
write!(f, "::{}", item_name)?;
}
for region in substs.regions.get_slice(subst::FnSpace) {
start_or_continue(f, "::<", ", ")?;
print_region(f, region)?;
}
print_regions(f, "::<", substs.regions.get_slice(subst::FnSpace))?;
// FIXME: consider being smart with defaults here too
for ty in substs.types.get_slice(subst::FnSpace) {
@ -536,7 +541,9 @@ impl fmt::Debug for ty::Region {
write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
}
ty::ReEmpty => write!(f, "ReEmpty")
ty::ReEmpty => write!(f, "ReEmpty"),
ty::ReErased => write!(f, "ReErased")
}
}
}
@ -600,7 +607,8 @@ impl fmt::Display for ty::Region {
write!(f, "{}", br)
}
ty::ReScope(_) |
ty::ReVar(_) => Ok(()),
ty::ReVar(_) |
ty::ReErased => Ok(()),
ty::ReStatic => write!(f, "'static"),
ty::ReEmpty => write!(f, "'<empty>"),
}