Skip to content

Commit

Permalink
Auto merge of #32346 - nikomatsakis:no-erased-regions, r=eddyb
Browse files Browse the repository at this point in the history
Remove `ErasedRegions` from substs

This commit removes the `ErasedRegions` enum from `Substs`. Instead, in trans, we just generate a vector of `ReStatic` of suitable length. The goal is both general cleanup and to help pave the way for a glorious future where erasure is used in type check.

r? @eddyb

One concern: might be nice to do some profiling. Not sure the best way to do that. Perhaps I'll investigate running nrc's test suite locally.
  • Loading branch information
bors committed Mar 24, 2016
2 parents dcfb8d7 + c5d74be commit d7a7168
Show file tree
Hide file tree
Showing 33 changed files with 192 additions and 349 deletions.
126 changes: 28 additions & 98 deletions src/librustc/middle/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
// Type substitutions.

pub use self::ParamSpace::*;
pub use self::RegionSubsts::*;

use middle::cstore;
use middle::def_id::DefId;
Expand All @@ -34,24 +33,15 @@ use syntax::codemap::{Span, DUMMY_SP};
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Substs<'tcx> {
pub types: VecPerParamSpace<Ty<'tcx>>,
pub regions: RegionSubsts,
}

/// Represents the values to use when substituting lifetime parameters.
/// If the value is `ErasedRegions`, then this subst is occurring during
/// trans, and all region parameters will be replaced with `ty::ReStatic`.
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum RegionSubsts {
ErasedRegions,
NonerasedRegions(VecPerParamSpace<ty::Region>)
pub regions: VecPerParamSpace<ty::Region>,
}

impl<'tcx> Substs<'tcx> {
pub fn new(t: VecPerParamSpace<Ty<'tcx>>,
r: VecPerParamSpace<ty::Region>)
-> Substs<'tcx>
{
Substs { types: t, regions: NonerasedRegions(r) }
Substs { types: t, regions: r }
}

pub fn new_type(t: Vec<Ty<'tcx>>,
Expand All @@ -71,32 +61,15 @@ impl<'tcx> Substs<'tcx> {
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
}

pub fn erased(t: VecPerParamSpace<Ty<'tcx>>) -> Substs<'tcx>
{
Substs { types: t, regions: ErasedRegions }
}

pub fn empty() -> Substs<'tcx> {
Substs {
types: VecPerParamSpace::empty(),
regions: NonerasedRegions(VecPerParamSpace::empty()),
}
}

pub fn trans_empty() -> Substs<'tcx> {
Substs {
types: VecPerParamSpace::empty(),
regions: ErasedRegions
regions: VecPerParamSpace::empty(),
}
}

pub fn is_noop(&self) -> bool {
let regions_is_noop = match self.regions {
ErasedRegions => false, // may be used to canonicalize
NonerasedRegions(ref regions) => regions.is_empty(),
};

regions_is_noop && self.types.is_empty()
self.regions.is_empty() && self.types.is_empty()
}

pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
Expand All @@ -115,26 +88,9 @@ impl<'tcx> Substs<'tcx> {
}

pub fn erase_regions(self) -> Substs<'tcx> {
let Substs { types, regions: _ } = self;
Substs { types: types, regions: ErasedRegions }
}

/// Since ErasedRegions are only to be used in trans, most of the compiler can use this method
/// to easily access the set of region substitutions.
pub fn regions<'a>(&'a self) -> &'a VecPerParamSpace<ty::Region> {
match self.regions {
ErasedRegions => panic!("Erased regions only expected in trans"),
NonerasedRegions(ref r) => r
}
}

/// Since ErasedRegions are only to be used in trans, most of the compiler can use this method
/// to easily access the set of region substitutions.
pub fn mut_regions<'a>(&'a mut self) -> &'a mut VecPerParamSpace<ty::Region> {
match self.regions {
ErasedRegions => panic!("Erased regions only expected in trans"),
NonerasedRegions(ref mut r) => r
}
let Substs { types, regions } = self;
let regions = regions.map(|_| ty::ReStatic);
Substs { types: types, regions: regions }
}

pub fn with_method(self,
Expand All @@ -144,7 +100,7 @@ impl<'tcx> Substs<'tcx> {
{
let Substs { types, regions } = self;
let types = types.with_slice(FnSpace, &m_types);
let regions = regions.map(|r| r.with_slice(FnSpace, &m_regions));
let regions = regions.with_slice(FnSpace, &m_regions);
Substs { types: types, regions: regions }
}

Expand All @@ -154,27 +110,23 @@ impl<'tcx> Substs<'tcx> {
{
let Substs { types, regions } = self.clone();
let types = types.with_slice(FnSpace, meth_substs.types.get_slice(FnSpace));
let regions = regions.map(|r| {
r.with_slice(FnSpace, meth_substs.regions().get_slice(FnSpace))
});
let regions = regions.with_slice(FnSpace, meth_substs.regions.get_slice(FnSpace));
Substs { types: types, regions: regions }
}

pub fn with_method_from_subst(self, other: &Substs<'tcx>) -> Substs<'tcx> {
let Substs { types, regions } = self;
let types = types.with_slice(FnSpace, other.types.get_slice(FnSpace));
let regions = regions.map(|r| {
r.with_slice(FnSpace, other.regions().get_slice(FnSpace))
});
let regions = regions.with_slice(FnSpace, other.regions.get_slice(FnSpace));
Substs { types: types, regions: regions }
}

/// Creates a trait-ref out of this substs, ignoring the FnSpace substs
pub fn to_trait_ref(&self, tcx: &TyCtxt<'tcx>, trait_id: DefId)
-> ty::TraitRef<'tcx> {
let Substs { mut types, regions } = self.clone();
let Substs { mut types, mut regions } = self.clone();
types.truncate(FnSpace, 0);
let regions = regions.map(|mut r| { r.truncate(FnSpace, 0); r });
regions.truncate(FnSpace, 0);

ty::TraitRef {
def_id: trait_id,
Expand Down Expand Up @@ -212,24 +164,6 @@ impl<'tcx> Decodable for &'tcx Substs<'tcx> {
}
}

impl RegionSubsts {
pub fn map<F>(self, op: F) -> RegionSubsts where
F: FnOnce(VecPerParamSpace<ty::Region>) -> VecPerParamSpace<ty::Region>,
{
match self {
ErasedRegions => ErasedRegions,
NonerasedRegions(r) => NonerasedRegions(op(r))
}
}

pub fn is_erased(&self) -> bool {
match *self {
ErasedRegions => true,
NonerasedRegions(_) => false,
}
}
}

///////////////////////////////////////////////////////////////////////////
// ParamSpace

Expand Down Expand Up @@ -664,26 +598,22 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
// the specialized routine `ty::replace_late_regions()`.
match r {
ty::ReEarlyBound(data) => {
match self.substs.regions {
ErasedRegions => ty::ReStatic,
NonerasedRegions(ref regions) =>
match regions.opt_get(data.space, data.index as usize) {
Some(&r) => {
self.shift_region_through_binders(r)
}
None => {
let span = self.span.unwrap_or(DUMMY_SP);
self.tcx().sess.span_bug(
span,
&format!("Type parameter out of range \
when substituting in region {} (root type={:?}) \
(space={:?}, index={})",
data.name,
self.root_ty,
data.space,
data.index));
}
}
match self.substs.regions.opt_get(data.space, data.index as usize) {
Some(&r) => {
self.shift_region_through_binders(r)
}
None => {
let span = self.span.unwrap_or(DUMMY_SP);
self.tcx().sess.span_bug(
span,
&format!("Region parameter out of range \
when substituting in region {} (root type={:?}) \
(space={:?}, index={})",
data.name,
self.root_ty,
data.space,
data.index));
}
}
}
_ => r
Expand Down
8 changes: 0 additions & 8 deletions src/librustc/middle/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,6 @@ pub fn translate_substs<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
specialization_graph::Node::Trait(..) => source_trait_ref.substs.clone(),
};

// retain erasure mode
// NB: this must happen before inheriting method generics below
let target_substs = if source_substs.regions.is_erased() {
target_substs.erase_regions()
} else {
target_substs
};

// directly inherent the method generics, since those do not vary across impls
infcx.tcx.mk_substs(target_substs.with_method_from_subst(source_substs))
}
Expand Down
9 changes: 2 additions & 7 deletions src/librustc/middle/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,8 @@ impl FlagComputation {

fn add_substs(&mut self, substs: &subst::Substs) {
self.add_tys(substs.types.as_slice());
match substs.regions {
subst::ErasedRegions => {}
subst::NonerasedRegions(ref regions) => {
for &r in regions {
self.add_region(r);
}
}
for &r in &substs.regions {
self.add_region(r);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ impl<'tcx> TyCtxt<'tcx> {
fn fold_substs(&mut self,
substs: &subst::Substs<'tcx>)
-> subst::Substs<'tcx> {
subst::Substs { regions: subst::ErasedRegions,
subst::Substs { regions: substs.regions.fold_with(self),
types: substs.types.fold_with(self) }
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2605,7 +2605,7 @@ impl<'tcx> TyCtxt<'tcx> {

Substs {
types: types,
regions: subst::NonerasedRegions(regions)
regions: regions,
}
}

Expand Down
28 changes: 10 additions & 18 deletions src/librustc/middle/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! type equality, etc.
use middle::def_id::DefId;
use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs};
use middle::subst::{ParamSpace, Substs};
use middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use middle::ty::error::{ExpectedFound, TypeError};
use std::rc::Rc;
Expand Down Expand Up @@ -156,23 +156,15 @@ pub fn relate_substs<'a,'tcx:'a,R>(relation: &mut R,
substs.types.replace(space, tps);
}

match (&a_subst.regions, &b_subst.regions) {
(&ErasedRegions, _) | (_, &ErasedRegions) => {
substs.regions = ErasedRegions;
}

(&NonerasedRegions(ref a), &NonerasedRegions(ref b)) => {
for &space in &ParamSpace::all() {
let a_regions = a.get_slice(space);
let b_regions = b.get_slice(space);
let r_variances = variances.map(|v| v.regions.get_slice(space));
let regions = relate_region_params(relation,
r_variances,
a_regions,
b_regions)?;
substs.mut_regions().replace(space, regions);
}
}
for &space in &ParamSpace::all() {
let a_regions = a_subst.regions.get_slice(space);
let b_regions = b_subst.regions.get_slice(space);
let r_variances = variances.map(|v| v.regions.get_slice(space));
let regions = relate_region_params(relation,
r_variances,
a_regions,
b_regions)?;
substs.regions.replace(space, regions);
}

Ok(substs)
Expand Down
14 changes: 2 additions & 12 deletions src/librustc/middle/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,14 +487,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region {

impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let regions = match self.regions {
subst::ErasedRegions => subst::ErasedRegions,
subst::NonerasedRegions(ref regions) => {
subst::NonerasedRegions(regions.fold_with(folder))
}
};

subst::Substs { regions: regions,
subst::Substs { regions: self.regions.fold_with(folder),
types: self.types.fold_with(folder) }
}

Expand All @@ -503,10 +496,7 @@ impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.types.visit_with(visitor) || match self.regions {
subst::ErasedRegions => false,
subst::NonerasedRegions(ref regions) => regions.visit_with(visitor),
}
self.types.visit_with(visitor) || self.regions.visit_with(visitor)
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/librustc/middle/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1204,18 +1204,18 @@ impl<'tcx> TyS<'tcx> {
TyTrait(ref obj) => {
let mut v = vec![obj.bounds.region_bound];
v.extend_from_slice(obj.principal.skip_binder()
.substs.regions().as_slice());
.substs.regions.as_slice());
v
}
TyEnum(_, substs) |
TyStruct(_, substs) => {
substs.regions().as_slice().to_vec()
substs.regions.as_slice().to_vec()
}
TyClosure(_, ref substs) => {
substs.func_substs.regions().as_slice().to_vec()
substs.func_substs.regions.as_slice().to_vec()
}
TyProjection(ref data) => {
data.trait_ref.substs.regions().as_slice().to_vec()
data.trait_ref.substs.regions.as_slice().to_vec()
}
TyFnDef(..) |
TyFnPtr(_) |
Expand Down
Loading

0 comments on commit d7a7168

Please sign in to comment.