// Type substitutions.
pub use self::ParamSpace::*;
-pub use self::RegionSubsts::*;
use middle::cstore;
use middle::def_id::DefId;
#[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> {
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>>,
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> {
}
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,
{
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 }
}
{
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,
}
}
-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
// 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
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))
}
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);
}
}
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) }
}
}
Substs {
types: types,
- regions: subst::NonerasedRegions(regions)
+ regions: regions,
}
}
//! 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;
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)
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) }
}
}
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)
}
}
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(_) |
};
if verbose {
- match substs.regions {
- subst::ErasedRegions => {
- start_or_continue(f, "<", ", ")?;
- write!(f, "..")?;
- }
- subst::NonerasedRegions(ref regions) => {
- for region in regions {
- start_or_continue(f, "<", ", ")?;
- write!(f, "{:?}", region)?;
- }
- }
+ for region in &substs.regions {
+ start_or_continue(f, "<", ", ")?;
+ write!(f, "{:?}", region)?;
}
for &ty in &substs.types {
start_or_continue(f, "<", ", ")?;
}
}
- match substs.regions {
- subst::ErasedRegions => { }
- subst::NonerasedRegions(ref regions) => {
- for &r in regions {
- start_or_continue(f, "<", ", ")?;
- let s = r.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)?;
- }
- }
+ for &r in &substs.regions {
+ start_or_continue(f, "<", ", ")?;
+ let s = r.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)?;
}
}
}
}
-impl fmt::Debug for subst::RegionSubsts {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- subst::ErasedRegions => write!(f, "erased"),
- subst::NonerasedRegions(ref regions) => write!(f, "{:?}", regions)
- }
- }
-}
-
impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// when printing out the debug representation, we don't need
}
pub fn parse_substs(&mut self) -> subst::Substs<'tcx> {
- let regions = self.parse_region_substs();
+ let regions = self.parse_vec_per_param_space(|this| this.parse_region());
let types = self.parse_vec_per_param_space(|this| this.parse_ty());
subst::Substs { types: types, regions: regions }
}
- fn parse_region_substs(&mut self) -> subst::RegionSubsts {
- match self.next() {
- 'e' => subst::ErasedRegions,
- 'n' => {
- subst::NonerasedRegions(
- self.parse_vec_per_param_space(|this| this.parse_region()))
- }
- _ => panic!("parse_bound_region: bad input")
- }
- }
-
fn parse_bound_region(&mut self) -> ty::BoundRegion {
match self.next() {
'a' => {
pub fn enc_substs<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
substs: &subst::Substs<'tcx>) {
- enc_region_substs(w, cx, &substs.regions);
+ enc_vec_per_param_space(w, cx, &substs.regions,
+ |w, cx, &r| enc_region(w, cx, r));
enc_vec_per_param_space(w, cx, &substs.types,
|w, cx, &ty| enc_ty(w, cx, ty));
}
-fn enc_region_substs(w: &mut Cursor<Vec<u8>>, cx: &ctxt, substs: &subst::RegionSubsts) {
- match *substs {
- subst::ErasedRegions => {
- write!(w, "e");
- }
- subst::NonerasedRegions(ref regions) => {
- write!(w, "n");
- enc_vec_per_param_space(w, cx, regions,
- |w, cx, &r| enc_region(w, cx, r));
- }
- }
-}
-
pub fn enc_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, r: ty::Region) {
match r {
ty::ReLateBound(id, br) => {
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>)
-> CustomCoerceUnsized {
- let trait_substs = Substs::erased(subst::VecPerParamSpace::new(vec![target_ty],
- vec![source_ty],
- Vec::new()));
+ let trait_substs = Substs::new(subst::VecPerParamSpace::new(vec![target_ty],
+ vec![source_ty],
+ Vec::new()),
+ subst::VecPerParamSpace::empty());
+
let trait_ref = ty::Binder(ty::TraitRef {
def_id: ccx.tcx().lang_items.coerce_unsized_trait().unwrap(),
substs: ccx.tcx().mk_substs(trait_substs)
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
if collector::collecting_debug_information(ccx) {
- ccx.record_translation_item_as_generated(TransItem::Fn(Instance {
- def: def_id,
- params: ¶m_substs.types
- }))
+ ccx.record_translation_item_as_generated(
+ TransItem::Fn(Instance::new(def_id, param_substs)));
}
let _icx = push_ctxt("trans_closure");
// compilation unit that references the item, so it will still get
// translated everywhere it's needed.
for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.empty_substs_for_node_id(item.id);
let def_id = tcx.map.local_def_id(item.id);
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id);
if sig.generics.ty_params.is_empty() {
let trans_everywhere = attr::requests_inline(&impl_item.attrs);
for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.empty_substs_for_node_id(impl_item.id);
let def_id = tcx.map.local_def_id(impl_item.id);
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
trans_fn(ccx, &sig.decl, body, llfn, empty_substs, impl_item.id);
Ok(id) => id,
Err(s) => ccx.sess().fatal(&s)
};
- let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.tcx().mk_substs(Substs::empty());
let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx).val;
let args = {
let opaque_rust_main =
let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
//
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = tcx.mk_substs(Substs::empty());
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
// duplicate declarations
let tcx = ccx.tcx();
let substs = tcx.erase_regions(substs);
- let instance = Instance {
- def: closure_id,
- params: &substs.func_substs.types
- };
+ let instance = Instance::new(closure_id, &substs.func_substs);
if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
debug!("get_or_create_closure_declaration(): found closure {:?}: {:?}",
TransItem::Fn(instance) => {
1u8.hash(s);
instance.def.hash(s);
- (instance.params as *const _ as usize).hash(s);
+ (instance.substs as *const _ as usize).hash(s);
}
TransItem::Static(node_id) => {
2u8.hash(s);
mode: mode,
output: &mut roots,
enclosing_item: None,
- trans_empty_substs: ccx.tcx().mk_substs(Substs::trans_empty()),
};
ccx.tcx().map.krate().visit_all_items(&mut visitor);
ccx: ccx,
mir: &mir,
output: &mut neighbors,
- param_substs: ccx.tcx().mk_substs(Substs {
- types: instance.params.clone(),
- regions: subst::ErasedRegions
- })
+ param_substs: instance.substs
};
visitor.visit_mir(&mir);
let exchange_malloc_fn_trans_item =
create_fn_trans_item(self.ccx,
exchange_malloc_fn_def_id,
- &Substs::trans_empty(),
+ &Substs::empty(),
self.param_substs);
self.output.push(exchange_malloc_fn_trans_item);
let exchange_free_fn_trans_item =
create_fn_trans_item(ccx,
exchange_free_fn_def_id,
- &Substs::trans_empty(),
- &Substs::trans_empty());
+ &Substs::empty(),
+ &Substs::empty());
output.push(exchange_free_fn_trans_item);
}
.unwrap();
let self_type_substs = ccx.tcx().mk_substs(
- Substs::trans_empty().with_self_ty(ty));
+ Substs::empty().with_self_ty(ty));
let trait_ref = ty::TraitRef {
def_id: drop_trait_def_id,
let trans_item = create_fn_trans_item(ccx,
destructor_did,
substs,
- &Substs::trans_empty());
+ &Substs::empty());
output.push(trans_item);
}
}
fn_substs);
let concrete_substs = ccx.tcx().erase_regions(&concrete_substs);
- let trans_item = TransItem::Fn(Instance {
- def: def_id,
- params: &ccx.tcx().mk_substs(concrete_substs).types,
- });
+ let trans_item =
+ TransItem::Fn(Instance::new(def_id,
+ &ccx.tcx().mk_substs(concrete_substs)));
return trans_item;
}
Some(create_fn_trans_item(ccx,
impl_method.method.def_id,
&impl_method.substs,
- &Substs::trans_empty()))
+ &Substs::empty()))
} else {
None
}
mode: TransItemCollectionMode,
output: &'b mut Vec<TransItem<'tcx>>,
enclosing_item: Option<&'tcx hir::Item>,
- trans_empty_substs: &'tcx Substs<'tcx>
}
impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
if self.mode == TransItemCollectionMode::Eager {
create_trans_items_for_default_impls(self.ccx,
item,
- self.trans_empty_substs,
self.output);
}
}
fn create_trans_items_for_default_impls<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
item: &'tcx hir::Item,
- trans_empty_substs: &'tcx Substs<'tcx>,
output: &mut Vec<TransItem<'tcx>>) {
match item.node {
hir::ItemImpl(_,
}
if can_have_local_instance(ccx, default_impl.def_id) {
+ let empty_substs = ccx.tcx().mk_substs(ccx.tcx().erase_regions(mth.substs));
let item = create_fn_trans_item(ccx,
default_impl.def_id,
callee_substs,
- trans_empty_substs);
+ empty_substs);
output.push(item);
}
}
instance: Instance<'tcx>,
output: &mut String) {
push_item_name(ccx, instance.def, output);
- push_type_params(ccx, instance.params, &[], output);
+ push_type_params(ccx, &instance.substs.types, &[], output);
}
fn def_id_to_string(ccx: &CrateContext, def_id: DefId) -> String {
TransItem::Fn(instance) => {
format!("Fn({:?}, {})",
instance.def,
- instance.params as *const _ as usize)
+ instance.substs as *const _ as usize)
}
TransItem::Static(id) => {
format!("Static({:?})", id)
param_substs: &'tcx Substs<'tcx>)
-> Result<ValueRef, ConstEvalFailure> {
let expr = get_const_expr(ccx, def_id, ref_expr, param_substs);
- let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.tcx().mk_substs(Substs::empty());
match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
Err(Runtime(err)) => {
ccx.tcx().sess.span_err(expr.span, &err.description());
let def_id = ccx.tcx().map.local_def_id(id);
let datum = get_static(ccx, def_id);
- let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.tcx().mk_substs(Substs::empty());
let (v, _) = const_expr(
ccx,
expr,
use trans::monomorphize::Instance;
use trans::collector::{TransItem, TransItemState};
use trans::type_::{Type, TypeNames};
-use middle::subst::Substs;
+use middle::subst::{Substs, VecPerParamSpace};
use middle::ty::{self, Ty, TyCtxt};
use session::config::NoDebugInfo;
use session::Session;
self.local
}
-
/// Get a (possibly) different `CrateContext` from the same
/// `SharedCrateContext`.
pub fn rotate(&self) -> CrateContext<'b, 'tcx> {
codegen_items.insert(cgi, TransItemState::NotPredictedButGenerated);
}
}
+
+ /// Given the node-id of some local item that has no type
+ /// parameters, make a suitable "empty substs" for it.
+ pub fn empty_substs_for_node_id(&self, item_node_id: ast::NodeId)
+ -> &'tcx Substs<'tcx> {
+ let item_def_id = self.tcx().map.local_def_id(item_node_id);
+ self.empty_substs_for_def_id(item_def_id)
+ }
+
+ /// Given the def-id of some item that has no type parameters, make
+ /// a suitable "empty substs" for it.
+ pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
+ let scheme = self.tcx().lookup_item_type(item_def_id);
+ self.empty_substs_for_scheme(&scheme)
+ }
+
+ pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>)
+ -> &'tcx Substs<'tcx> {
+ assert!(scheme.generics.types.is_empty());
+ self.tcx().mk_substs(
+ Substs::new(VecPerParamSpace::empty(),
+ scheme.generics.regions.map(|_| ty::ReStatic)))
+ }
}
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
hir::ExprPath(..) => {
match bcx.def(expr.id) {
Def::Const(did) | Def::AssociatedConst(did) => {
- let empty_substs = bcx.tcx().mk_substs(Substs::trans_empty());
+ let empty_substs = bcx.tcx().mk_substs(Substs::empty());
let const_expr = consts::get_const_expr(bcx.ccx(), did, expr,
empty_substs);
// Temporarily get cleanup scopes out of the way,
let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.tcx().mk_substs(Substs::empty());
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &arena);
let trait_ref = ty::Binder(ty::TraitRef {
def_id: tcx.lang_items.drop_trait().unwrap(),
- substs: tcx.mk_substs(Substs::trans_empty().with_self_ty(t))
+ substs: tcx.mk_substs(Substs::empty().with_self_ty(t))
});
let vtbl = match fulfill_obligation(bcx.ccx(), DUMMY_SP, trait_ref) {
traits::VtableImpl(data) => data,
// performance.
AvailableExternallyLinkage
};
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = tcx.mk_substs(Substs::empty());
let def_id = tcx.map.local_def_id(item.id);
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
SetLinkage(llfn, linkage);
let impl_tpt = tcx.lookup_item_type(impl_did);
if impl_tpt.generics.types.is_empty() &&
sig.generics.ty_params.is_empty() {
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.empty_substs_for_node_id(impl_item.id);
let def_id = tcx.map.local_def_id(impl_item.id);
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
trans_fn(ccx,
sig: ty::Binder(sig)
});
let llfn = declare::define_internal_fn(ccx, name, rust_fn_ty);
- let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
+ let empty_substs = ccx.tcx().mk_substs(Substs::empty());
let (fcx, block_arena);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
use llvm::{ValueRef, get_params};
use middle::def_id::DefId;
use middle::infer;
-use middle::subst::{Subst, Substs};
+use middle::subst::{FnSpace, Subst, Substs};
use middle::subst;
use middle::traits::{self, ProjectionMode};
use trans::abi::FnType;
let function_name = link::mangle_internal_name_by_type_and_seq(ccx, method_ty, "object_shim");
let llfn = declare::define_internal_fn(ccx, &function_name, method_ty);
- let empty_substs = tcx.mk_substs(Substs::trans_empty());
+ let empty_substs = tcx.mk_substs(Substs::empty());
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
block_arena = TypedArena::new();
fcx = FunctionContext::new(ccx, llfn, fn_ty, None, empty_substs, &block_arena);
debug!("get_vtable_methods: trait_method_type={:?}",
trait_method_type);
+ // the method may have some early-bound lifetimes, add
+ // regions for those
+ let num_dummy_regions = trait_method_type.generics.regions.len(FnSpace);
+ let dummy_regions = vec![ty::ReStatic; num_dummy_regions];
+ let method_substs = substs.clone()
+ .with_method(vec![], dummy_regions);
+ let method_substs = tcx.mk_substs(method_substs);
+
// The substitutions we have are on the impl, so we grab
// the method type from the impl to substitute into.
- let mth = get_impl_method(tcx, impl_id, substs, name);
+ let mth = get_impl_method(tcx, impl_id, method_substs, name);
debug!("get_vtable_methods: mth={:?}", mth);
let _icx = push_ctxt("monomorphic_fn");
- let instance = Instance {
- def: fn_id,
- params: &psubsts.types
- };
+ let instance = Instance::new(fn_id, psubsts);
let item_ty = ccx.tcx().lookup_item_type(fn_id).ty;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
pub def: DefId,
- pub params: &'tcx subst::VecPerParamSpace<Ty<'tcx>>
+ pub substs: &'tcx Substs<'tcx>,
}
impl<'tcx> fmt::Display for Instance<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let substs = Substs {
- types: self.params.clone(),
- regions: subst::ErasedRegions
- };
- ppaux::parameterized(f, &substs, self.def, ppaux::Ns::Value, &[],
+ ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[],
|tcx| tcx.lookup_item_type(self.def).generics)
}
}
impl<'tcx> Instance<'tcx> {
+ pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
+ -> Instance<'tcx> {
+ assert!(substs.regions.iter().all(|&r| r == ty::ReStatic));
+ Instance { def: def_id, substs: substs }
+ }
pub fn mono(tcx: &TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
- Instance {
- def: def_id,
- params: &tcx.mk_substs(Substs::trans_empty()).types
- }
+ Instance::new(def_id, &tcx.mk_substs(Substs::empty()))
}
}
decl_generics, self_ty, types_provided,
region_substs);
- assert_eq!(region_substs.regions().len(TypeSpace), decl_generics.regions.len(TypeSpace));
+ assert_eq!(region_substs.regions.len(TypeSpace), decl_generics.regions.len(TypeSpace));
assert!(region_substs.types.is_empty());
// Convert the type parameters supplied by the user.
trait_to_impl_substs
.subst(tcx, impl_to_skol_substs)
.with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
- impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
+ impl_to_skol_substs.regions.get_slice(subst::FnSpace).to_vec());
debug!("compare_impl_method: trait_to_skol_substs={:?}",
trait_to_skol_substs);
trait_to_impl_substs
.subst(tcx, impl_to_skol_substs)
.with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
- impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
+ impl_to_skol_substs.regions.get_slice(subst::FnSpace).to_vec());
debug!("compare_const_impl: trait_to_skol_substs={:?}",
trait_to_skol_substs);
.generics.regions.get_slice(subst::FnSpace));
let subst::Substs { types, regions } = substs;
- let regions = regions.map(|r| r.with_slice(subst::FnSpace, &method_regions));
+ let regions = regions.with_slice(subst::FnSpace, &method_regions);
let mut final_substs = subst::Substs { types: types, regions: regions };
if num_supplied_types == 0 {
assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
trait_ref.substs.types.get_slice(subst::TypeSpace).len());
assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
- trait_ref.substs.regions().get_slice(subst::TypeSpace).len());
+ trait_ref.substs.regions.get_slice(subst::TypeSpace).len());
assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
trait_ref.substs.types.get_slice(subst::SelfSpace).len());
assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
- trait_ref.substs.regions().get_slice(subst::SelfSpace).len());
+ trait_ref.substs.regions.get_slice(subst::SelfSpace).len());
}
// Because this trait derives from a where-clause, it
// method yet. So create fresh variables here for those too,
// if there are any.
assert_eq!(substs.types.len(subst::FnSpace), 0);
- assert_eq!(substs.regions().len(subst::FnSpace), 0);
+ assert_eq!(substs.regions.len(subst::FnSpace), 0);
if self.mode == Mode::Path {
return impl_ty;
assert_eq!(substs.types.len(space), type_defs.len(space));
adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
- assert_eq!(substs.regions().len(space), region_defs.len(space));
+ assert_eq!(substs.regions.len(space), region_defs.len(space));
}
// The things we are substituting into the type should not contain
let impl_scheme = fcx.tcx().lookup_item_type(impl_def_id);
assert_eq!(substs.types.len(subst::TypeSpace),
impl_scheme.generics.types.len(subst::TypeSpace));
- assert_eq!(substs.regions().len(subst::TypeSpace),
+ assert_eq!(substs.regions.len(subst::TypeSpace),
impl_scheme.generics.regions.len(subst::TypeSpace));
let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
{
let region_count = region_defs.len(space);
- assert_eq!(substs.regions().len(space), 0);
+ assert_eq!(substs.regions.len(space), 0);
for (i, lifetime) in data.lifetimes.iter().enumerate() {
let r = ast_region_to_region(fcx.tcx(), lifetime);
if i < region_count {
- substs.mut_regions().push(space, r);
+ substs.regions.push(space, r);
} else if i == region_count {
span_err!(fcx.tcx().sess, lifetime.span, E0088,
"too many lifetime parameters provided: \
if region_count == 1 {""} else {"s"},
data.lifetimes.len(),
if data.lifetimes.len() == 1 {""} else {"s"});
- substs.mut_regions().truncate(space, 0);
+ substs.regions.truncate(space, 0);
break;
}
}
defs: &VecPerParamSpace<ty::RegionParameterDef>,
substs: &mut Substs)
{
- let provided_len = substs.mut_regions().len(space);
+ let provided_len = substs.regions.len(space);
let desired = defs.get_slice(space);
// Enforced by `push_explicit_parameters_from_segment_to_substs()`.
// If nothing was provided, just use inference variables.
if provided_len == 0 {
- substs.mut_regions().replace(
+ substs.regions.replace(
space,
fcx.infcx().region_vars_for_defs(span, desired));
return;
provided_len,
if provided_len == 1 {""} else {"s"});
- substs.mut_regions().replace(
+ substs.regions.replace(
space,
fcx.infcx().region_vars_for_defs(span, desired));
}
let origin = infer::ParameterInScope(origin, expr_span);
- for ®ion in substs.regions() {
+ for ®ion in &substs.regions {
rcx.fcx.mk_subr(origin.clone(), expr_region, region);
}
// edges, which winds up enforcing the same condition.
let needs_infer = {
projection_ty.trait_ref.substs.types.iter().any(|t| t.needs_infer()) ||
- projection_ty.trait_ref.substs.regions().iter().any(|r| r.needs_infer())
+ projection_ty.trait_ref.substs.regions.iter().any(|r| r.needs_infer())
};
if env_bounds.is_empty() && needs_infer {
debug!("projection_must_outlive: no declared bounds");
type_must_outlive(rcx, origin.clone(), component_ty, region);
}
- for &r in projection_ty.trait_ref.substs.regions() {
+ for &r in &projection_ty.trait_ref.substs.regions {
rcx.fcx.mk_subr(origin.clone(), region, r);
}
if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) {
let unique_bound = env_bounds[0];
debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound);
- if projection_ty.trait_ref.substs.regions()
+ if projection_ty.trait_ref.substs.regions
.iter()
.any(|r| env_bounds.contains(r))
{
}
fn parameters_for_regions_in_substs(substs: &subst::Substs) -> Vec<Parameter> {
- substs.regions()
+ substs.regions
.iter()
.filter_map(|r| parameters_for_region(r))
.collect()
self.declared_variance(p.def_id, def_id,
RegionParam, p.space, p.index as usize);
let variance_i = self.xform(variance, variance_decl);
- let substs_r = *substs.regions().get(p.space, p.index as usize);
+ let substs_r = *substs.regions.get(p.space, p.index as usize);
self.add_constraints_from_region(generics, substs_r, variance_i);
}
}
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
- let lifetimes = substs.regions().get_slice(subst::TypeSpace)
+ let lifetimes = substs.regions.get_slice(subst::TypeSpace)
.iter()
.filter_map(|v| v.clean(cx))
.collect();
impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
let mut v = Vec::new();
- v.extend(self.regions().iter().filter_map(|r| r.clean(cx)).map(RegionBound));
+ v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound));
v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
trait_: t.clean(cx),
lifetimes: vec![]