diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index b0dec3277a9..21fccd2c613 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -1366,7 +1366,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { hir::TyPath(ref maybe_qself, ref path) => { match self.tcx.expect_def(cur_ty.id) { Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => { - let generics = self.tcx.lookup_item_type(did).generics; + let generics = self.tcx.lookup_generics(did); let expected = generics.regions.len(subst::TypeSpace) as u32; diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 1e360cd43da..1b65b5dae07 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -25,9 +25,7 @@ use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::region::CodeExtent; use mir::tcx::LvalueTy; -use ty::subst; -use ty::subst::Substs; -use ty::subst::Subst; +use ty::subst::{Subst, Substs}; use ty::adjustment; use ty::{TyVid, IntVid, FloatVid}; use ty::{self, Ty, TyCtxt}; @@ -1236,43 +1234,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Given a set of generics defined on a type or impl, returns a substitution mapping each /// type/region parameter to a fresh inference variable. - pub fn fresh_substs_for_generics(&self, - span: Span, - generics: &ty::Generics<'tcx>) - -> &'tcx subst::Substs<'tcx> - { - let substs = Substs::from_generics(generics, |def, _| { + pub fn fresh_substs_for_item(&self, + span: Span, + def_id: DefId) + -> &'tcx Substs<'tcx> { + Substs::for_item(self.tcx, def_id, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { self.type_var_for_def(span, def, substs) - }); - - self.tcx.mk_substs(substs) - } - - /// Given a set of generics defined on a trait, returns a substitution mapping each output - /// type/region parameter to a fresh inference variable, and mapping the self type to - /// `self_ty`. - pub fn fresh_substs_for_trait(&self, - span: Span, - generics: &ty::Generics<'tcx>, - self_ty: Ty<'tcx>) - -> &'tcx subst::Substs<'tcx> - { - assert!(generics.types.len(subst::SelfSpace) == 1); - assert!(generics.types.len(subst::FnSpace) == 0); - - let substs = Substs::from_generics(generics, |def, _| { - self.region_var_for_def(span, def) - }, |def, substs| { - if def.space == subst::SelfSpace { - self_ty - } else { - self.type_var_for_def(span, def, substs) - } - }); - - self.tcx.mk_substs(substs) + }) } pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region { diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 481fd332404..abb22783ddc 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -154,7 +154,7 @@ pub trait CrateStore<'tcx> { fn item_variances(&self, def: DefId) -> ty::ItemVariances; fn repr_attrs(&self, def: DefId) -> Vec; fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::TypeScheme<'tcx>; + -> Ty<'tcx>; fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap>; fn item_name(&self, def: DefId) -> ast::Name; fn opt_item_name(&self, def: DefId) -> Option; @@ -162,6 +162,8 @@ pub trait CrateStore<'tcx> { -> ty::GenericPredicates<'tcx>; fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx>; + fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> &'tcx ty::Generics<'tcx>; fn item_attrs(&self, def_id: DefId) -> Vec; fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>; fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>; @@ -187,8 +189,7 @@ pub trait CrateStore<'tcx> { fn impl_parent(&self, impl_def_id: DefId) -> Option; // trait/impl-item info - fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option; + fn trait_of_item(&self, def_id: DefId) -> Option; fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option>; @@ -334,7 +335,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn item_variances(&self, def: DefId) -> ty::ItemVariances { bug!("item_variances") } fn repr_attrs(&self, def: DefId) -> Vec { bug!("repr_attrs") } fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::TypeScheme<'tcx> { bug!("item_type") } + -> Ty<'tcx> { bug!("item_type") } fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap> { bug!("visible_parent_map") } @@ -344,6 +345,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { -> ty::GenericPredicates<'tcx> { bug!("item_predicates") } fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") } + fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> &'tcx ty::Generics<'tcx> { bug!("item_generics") } fn item_attrs(&self, def_id: DefId) -> Vec { bug!("item_attrs") } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx> { bug!("trait_def") } @@ -379,8 +382,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { fn impl_parent(&self, def: DefId) -> Option { bug!("impl_parent") } // trait/impl-item info - fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option { bug!("trait_of_item") } + fn trait_of_item(&self, def_id: DefId) -> Option { bug!("trait_of_item") } fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { bug!("impl_or_trait_item") } @@ -583,7 +585,7 @@ pub mod tls { pub trait DecodingContext<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>; fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>; - fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>; + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx>; fn translate_def_id(&self, def_id: DefId) -> DefId; } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 2b59e603cc8..7412b5fc804 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -18,7 +18,7 @@ use hir::{self, pat_util, PatKind}; use hir::intravisit::{self, Visitor}; use middle::privacy; -use ty::{self, TyCtxt}; +use ty::{self, subst, TyCtxt}; use hir::def::Def; use hir::def_id::{DefId}; use lint; @@ -88,15 +88,24 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_definition(&mut self, id: ast::NodeId) { use ty::TypeVariants::{TyEnum, TyStruct}; - // If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar` - self.tcx.tables.borrow().item_substs.get(&id) - .and_then(|substs| substs.substs.self_ty()) - .map(|ty| match ty.sty { - TyEnum(tyid, _) | TyStruct(tyid, _) => self.check_def_id(tyid.did), - _ => (), - }); - let def = self.tcx.expect_def(id); + + // If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar` + match def { + Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_) + if self.tcx.trait_of_item(def.def_id()).is_some() => { + if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) { + match substs.substs.types.get(subst::SelfSpace, 0).sty { + TyEnum(tyid, _) | TyStruct(tyid, _) => { + self.check_def_id(tyid.did) + } + _ => {} + } + } + } + _ => {} + } + match def { Def::Const(_) | Def::AssociatedConst(..) => { self.check_def_id(def.def_id()); diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 2bde3d6554f..f511d820fac 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -1073,10 +1073,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let variant_def = &adt_def.variants[variant]; ppaux::parameterized(fmt, substs, variant_def.did, - ppaux::Ns::Value, &[], - |tcx| { - Some(tcx.lookup_item_type(variant_def.did).generics) - })?; + ppaux::Ns::Value, &[])?; match variant_def.kind { ty::VariantKind::Unit => Ok(()), @@ -1169,9 +1166,7 @@ impl<'tcx> Debug for Literal<'tcx> { use self::Literal::*; match *self { Item { def_id, substs } => { - ppaux::parameterized( - fmt, substs, def_id, ppaux::Ns::Value, &[], - |tcx| Some(tcx.lookup_item_type(def_id).generics)) + ppaux::parameterized(fmt, substs, def_id, ppaux::Ns::Value, &[]) } Value { ref value } => { write!(fmt, "const ")?; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 5d50eac1716..e67c0ba8053 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -221,9 +221,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.lookup_trait_def(trait_ref.def_id) .for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| { - let ity = tcx.lookup_item_type(def_id); - let impl_substs = self.fresh_substs_for_generics(obligation.cause.span, - &ity.generics); + let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); let impl_trait_ref = tcx .impl_trait_ref(def_id) .unwrap() diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 1ee1dc50b71..3698027dca8 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -160,10 +160,9 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { // We can resolve the `impl Trait` to its concrete type. if let Some(ty_scheme) = tcx.opt_lookup_item_type(def_id) { let concrete_ty = ty_scheme.ty.subst(tcx, substs); - let concrete_substs = Substs::new_trait(vec![], vec![], concrete_ty); let predicate = ty::TraitRef { def_id: self.predicate.def_id(), - substs: tcx.mk_substs(concrete_substs) + substs: Substs::new_trait(tcx, vec![], vec![], concrete_ty) }.to_predicate(); let original_obligation = Obligation::new(self.cause.clone(), diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index dc0807ba38f..b86a54f01cf 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -17,7 +17,7 @@ pub use self::ObligationCauseCode::*; use hir::def_id::DefId; use middle::free_region::FreeRegionMap; -use ty::subst; +use ty::subst::Substs; use ty::{self, Ty, TyCtxt, TypeFoldable}; use infer::InferCtxt; @@ -272,7 +272,7 @@ pub enum Vtable<'tcx, N> { #[derive(Clone, PartialEq, Eq)] pub struct VtableImplData<'tcx, N> { pub impl_def_id: DefId, - pub substs: &'tcx subst::Substs<'tcx>, + pub substs: &'tcx Substs<'tcx>, pub nested: Vec } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 8ddb14e08e3..ecfa7930d02 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -166,25 +166,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn trait_has_sized_self(self, trait_def_id: DefId) -> bool { - let trait_def = self.lookup_trait_def(trait_def_id); - let trait_predicates = self.lookup_predicates(trait_def_id); - self.generics_require_sized_self(&trait_def.generics, &trait_predicates) + self.generics_require_sized_self(trait_def_id) } - fn generics_require_sized_self(self, - generics: &ty::Generics<'gcx>, - predicates: &ty::GenericPredicates<'gcx>) - -> bool - { + fn generics_require_sized_self(self, def_id: DefId) -> bool { let sized_def_id = match self.lang_items.sized_trait() { Some(def_id) => def_id, None => { return false; /* No Sized trait, can't require it! */ } }; // Search for a predicate like `Self : Sized` amongst the trait bounds. - let free_substs = self.construct_free_substs(generics, + let free_substs = self.construct_free_substs(def_id, self.region_maps.node_extent(ast::DUMMY_NODE_ID)); - let predicates = predicates.instantiate(self, &free_substs).predicates; + let predicates = self.lookup_predicates(def_id); + let predicates = predicates.instantiate(self, free_substs).predicates; elaborate_predicates(self, predicates) .any(|predicate| { match predicate { @@ -214,7 +209,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { // Any method that has a `Self : Sized` requisite is otherwise // exempt from the regulations. - if self.generics_require_sized_self(&method.generics, &method.predicates) { + if self.generics_require_sized_self(method.def_id) { return None; } @@ -231,7 +226,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { -> bool { // Any method that has a `Self : Sized` requisite can't be called. - if self.generics_require_sized_self(&method.generics, &method.predicates) { + if self.generics_require_sized_self(method.def_id) { return false; } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 73108e7d37f..9099d6cd740 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -42,6 +42,7 @@ use traits; use ty::fast_reject; use ty::relate::TypeRelation; +use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec}; use std::cell::RefCell; use std::fmt; @@ -1935,7 +1936,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // for `PhantomData`, we pass `T` ty::TyStruct(def, substs) if def.is_phantom_data() => { - substs.types.get_slice(TypeSpace).to_vec() + substs.types.as_full_slice().to_vec() } ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { @@ -2584,17 +2585,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else { return Err(Unimplemented); }; - let mut ty_params = vec![]; + let mut ty_params = BitVector::new(substs_a.types.len(TypeSpace)); + let mut found = false; for ty in field.walk() { if let ty::TyParam(p) = ty.sty { assert!(p.space == TypeSpace); - let idx = p.idx as usize; - if !ty_params.contains(&idx) { - ty_params.push(idx); - } + ty_params.insert(p.idx as usize); + found = true; } } - if ty_params.is_empty() { + if !found { return Err(Unimplemented); } @@ -2602,12 +2602,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // TyError and ensure they do not affect any other fields. // This could be checked after type collection for any struct // with a potentially unsized trailing field. - let mut new_substs = substs_a.clone(); - for &i in &ty_params { - new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err; - } + let types = substs_a.types.map_enumerated(|(_, i, ty)| { + if ty_params.contains(i) { + tcx.types.err + } else { + ty + } + }); + let substs = Substs::new(tcx, types, substs_a.regions.clone()); for &ty in fields.split_last().unwrap().1 { - if ty.subst(tcx, &new_substs).references_error() { + if ty.subst(tcx, substs).references_error() { return Err(Unimplemented); } } @@ -2618,11 +2622,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Check that the source structure with the target's // type parameters is a subtype of the target. - for &i in &ty_params { - let param_b = *substs_b.types.get(TypeSpace, i); - new_substs.types.get_mut_slice(TypeSpace)[i] = param_b; - } - let new_struct = tcx.mk_struct(def, tcx.mk_substs(new_substs)); + let types = substs_a.types.map_enumerated(|(_, i, ty)| { + if ty_params.contains(i) { + *substs_b.types.get(TypeSpace, i) + } else { + ty + } + }); + let substs = Substs::new(tcx, types, substs_a.regions.clone()); + let new_struct = tcx.mk_struct(def, substs); let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = self.infcx.sub_types(false, origin, new_struct, target) @@ -2691,12 +2699,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { snapshot); let skol_obligation_trait_ref = skol_obligation.trait_ref; - let impl_substs = util::fresh_type_vars_for_impl(self.infcx, - obligation.cause.span, - impl_def_id); + let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, + impl_def_id); let impl_trait_ref = impl_trait_ref.subst(self.tcx(), - &impl_substs); + impl_substs); let impl_trait_ref = project::normalize_with_depth(self, diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 38cccb9753d..42865ca927d 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -18,7 +18,7 @@ // fits together with the rest of the trait machinery. use super::{SelectionContext, FulfillmentContext}; -use super::util::{fresh_type_vars_for_impl, impl_trait_ref_and_oblig}; +use super::util::impl_trait_ref_and_oblig; use rustc_data_structures::fnv::FnvHashMap; use hir::def_id::DefId; @@ -101,7 +101,7 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, }; // directly inherent the method generics, since those do not vary across impls - infcx.tcx.mk_substs(target_substs.with_method_from_subst(source_substs)) + source_substs.rebase_onto(infcx.tcx, source_impl, target_substs) } /// Is impl1 a specialization of impl2? @@ -141,11 +141,8 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // create a parameter environment corresponding to a (skolemized) instantiation of impl1 - let scheme = tcx.lookup_item_type(impl1_def_id); - let predicates = tcx.lookup_predicates(impl1_def_id); let mut penv = tcx.construct_parameter_environment(DUMMY_SP, - &scheme.generics, - &predicates, + impl1_def_id, region::DUMMY_CODE_EXTENT); let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id) .unwrap() @@ -188,10 +185,10 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, target_impl: DefId) -> Result<&'tcx Substs<'tcx>, ()> { let selcx = &mut SelectionContext::new(&infcx); - let target_substs = fresh_type_vars_for_impl(&infcx, DUMMY_SP, target_impl); + let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl); let (target_trait_ref, obligations) = impl_trait_ref_and_oblig(selcx, target_impl, - &target_substs); + target_substs); // do the impls unify? If not, no specialization. if let Err(_) = infcx.eq_trait_refs(true, diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a47cd23c64a..13193e1b2d7 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -122,19 +122,18 @@ impl<'a, 'gcx, 'tcx> Children { if le == ge { // overlap, but no specialization; error out let trait_ref = impl_header.trait_ref.unwrap(); + let self_ty = trait_ref.self_ty(); Err(OverlapError { with_impl: possible_sibling, trait_desc: trait_ref.to_string(), - self_desc: trait_ref.substs.self_ty().and_then(|ty| { - // only report the Self type if it has at least - // some outer concrete shell; otherwise, it's - // not adding much information. - if ty.has_concrete_skeleton() { - Some(ty.to_string()) - } else { - None - } - }) + // only report the Self type if it has at least + // some outer concrete shell; otherwise, it's + // not adding much information. + self_desc: if self_ty.has_concrete_skeleton() { + Some(self_ty.to_string()) + } else { + None + } }) } else { Ok((le, ge)) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 80a3ad9122b..1954ce1993c 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -9,10 +9,8 @@ // except according to those terms. use hir::def_id::DefId; -use infer::InferCtxt; use ty::subst::{Subst, Substs}; use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; -use syntax_pos::Span; use util::common::ErrorReported; use util::nodemap::FnvHashSet; @@ -349,19 +347,6 @@ pub fn impl_trait_ref_and_oblig<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, (impl_trait_ref, impl_obligations) } -// determine the `self` type, using fresh variables for all variables -// declared on the impl declaration e.g., `impl for Box<[(A,B)]>` -// would return ($0, $1) where $0 and $1 are freshly instantiated type -// variables. -pub fn fresh_type_vars_for_impl<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - span: Span, - impl_def_id: DefId) - -> &'tcx Substs<'tcx> -{ - let impl_generics = infcx.tcx.lookup_item_type(impl_def_id).generics; - infcx.fresh_substs_for_generics(span, &impl_generics) -} - /// See `super::obligations_for_generics` pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, recursion_depth: usize, @@ -401,7 +386,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Ok(def_id) => { Ok(ty::TraitRef { def_id: def_id, - substs: self.mk_substs(Substs::empty().with_self_ty(param_ty)) + substs: Substs::new_trait(self, vec![], vec![], param_ty) }) } Err(e) => { @@ -421,7 +406,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { let trait_ref = ty::TraitRef { def_id: trait_def_id, - substs: self.mk_substs(Substs::new_trait(ty_params, vec![], param_ty)) + substs: Substs::new_trait(self, ty_params, vec![], param_ty) }; predicate_for_trait_ref(cause, trait_ref, recursion_depth) } @@ -509,10 +494,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { TupleArgumentsFlag::No => sig.0.inputs[0], TupleArgumentsFlag::Yes => self.mk_tup(sig.0.inputs.to_vec()), }; - let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty); let trait_ref = ty::TraitRef { def_id: fn_trait_def_id, - substs: self.mk_substs(trait_substs), + substs: Substs::new_trait(self, vec![arguments_tuple], vec![], self_ty), }; ty::Binder((trait_ref, sig.0.output)) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index dfb5482ad87..9356b408a51 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -63,6 +63,7 @@ pub struct CtxtArenas<'tcx> { layout: TypedArena, // references + generics: TypedArena>, trait_defs: TypedArena>, adt_defs: TypedArena>, } @@ -78,6 +79,7 @@ impl<'tcx> CtxtArenas<'tcx> { stability: TypedArena::new(), layout: TypedArena::new(), + generics: TypedArena::new(), trait_defs: TypedArena::new(), adt_defs: TypedArena::new() } @@ -341,7 +343,8 @@ pub struct GlobalCtxt<'tcx> { pub adt_defs: RefCell>>, /// Maps from the def-id of an item (trait/struct/enum/fn) to its - /// associated predicates. + /// associated generics and predicates. + pub generics: RefCell>>, pub predicates: RefCell>>, /// Maps from the def-id of a trait to the list of @@ -583,13 +586,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.tables.borrow_mut().node_types.insert(id, ty); } + pub fn alloc_generics(self, generics: ty::Generics<'gcx>) + -> &'gcx ty::Generics<'gcx> { + self.global_interners.arenas.generics.alloc(generics) + } + pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>) -> &'gcx ty::TraitDef<'gcx> { let did = def.trait_ref.def_id; - let interned = self.global_interners.arenas.trait_defs.alloc(def); + let interned = self.alloc_trait_def(def); if let Some(prev) = self.trait_defs.borrow_mut().insert(did, interned) { bug!("Tried to overwrite interned TraitDef: {:?}", prev) } + self.generics.borrow_mut().insert(did, interned.generics); interned } @@ -711,6 +720,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + generics: RefCell::new(DepTrackingMap::new(dep_graph.clone())), predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())), fulfilled_predicates: RefCell::new(fulfilled_predicates), diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 6cc759c420d..312b09cd27d 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ty::subst; +use ty::subst::{self, Substs}; use ty::{self, Ty, TypeFlags, TypeFoldable}; pub struct FlagComputation { @@ -207,7 +207,7 @@ impl FlagComputation { self.add_substs(projection_ty.trait_ref.substs); } - fn add_substs(&mut self, substs: &subst::Substs) { + fn add_substs(&mut self, substs: &Substs) { self.add_tys(substs.types.as_full_slice()); for &r in substs.regions.as_full_slice() { self.add_region(r); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 597261cca72..2e114a801d6 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -40,7 +40,7 @@ //! and does not need to visit anything else. use middle::region; -use ty::subst; +use ty::subst::Substs; use ty::adjustment; use ty::{self, Binder, Ty, TyCtxt, TypeFlags}; @@ -145,8 +145,8 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { } fn fold_substs(&mut self, - substs: &'tcx subst::Substs<'tcx>) - -> &'tcx subst::Substs<'tcx> { + substs: &'tcx Substs<'tcx>) + -> &'tcx Substs<'tcx> { substs.super_fold_with(self) } diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 57b1dd66bea..d5686906e6a 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -10,7 +10,7 @@ use dep_graph::{DepNode, DepTrackingMapConfig}; use hir::def_id::DefId; -use ty; +use ty::{self, Ty}; use std::marker::PhantomData; use std::rc::Rc; use syntax::{attr, ast}; @@ -30,7 +30,8 @@ macro_rules! dep_map_ty { } dep_map_ty! { ImplOrTraitItems: ImplOrTraitItems(DefId) -> ty::ImplOrTraitItem<'tcx> } -dep_map_ty! { Tcache: ItemSignature(DefId) -> ty::TypeScheme<'tcx> } +dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> } +dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> } dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { TraitItemDefIds: TraitItemDefIds(DefId) -> Rc> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6ac57a877a7..36784e40064 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -173,15 +173,14 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> { -> ImplHeader<'tcx> { let tcx = selcx.tcx(); - let impl_generics = tcx.lookup_item_type(impl_def_id).generics; - let impl_substs = selcx.infcx().fresh_substs_for_generics(DUMMY_SP, &impl_generics); + let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id); let header = ImplHeader { impl_def_id: impl_def_id, self_ty: tcx.lookup_item_type(impl_def_id).ty, trait_ref: tcx.impl_trait_ref(impl_def_id), predicates: tcx.lookup_predicates(impl_def_id).predicates - }.subst(tcx, &impl_substs); + }.subst(tcx, impl_substs); let traits::Normalized { value: mut header, obligations } = traits::normalize(selcx, traits::ObligationCause::dummy(), &header); @@ -348,7 +347,7 @@ impl Visibility { #[derive(Clone, Debug)] pub struct Method<'tcx> { pub name: Name, - pub generics: Generics<'tcx>, + pub generics: &'tcx Generics<'tcx>, pub predicates: GenericPredicates<'tcx>, pub fty: &'tcx BareFnTy<'tcx>, pub explicit_self: ExplicitSelfCategory, @@ -360,7 +359,7 @@ pub struct Method<'tcx> { impl<'tcx> Method<'tcx> { pub fn new(name: Name, - generics: ty::Generics<'tcx>, + generics: &'tcx ty::Generics<'tcx>, predicates: GenericPredicates<'tcx>, fty: &'tcx BareFnTy<'tcx>, explicit_self: ExplicitSelfCategory, @@ -453,7 +452,7 @@ pub struct MethodCallee<'tcx> { /// Impl method ID, for inherent methods, or trait method ID, otherwise. pub def_id: DefId, pub ty: Ty<'tcx>, - pub substs: &'tcx subst::Substs<'tcx> + pub substs: &'tcx Substs<'tcx> } /// With method calls, we store some extra information in @@ -760,6 +759,7 @@ impl RegionParameterDef { pub struct Generics<'tcx> { pub types: VecPerParamSpace>, pub regions: VecPerParamSpace, + pub has_self: bool, } impl<'tcx> Generics<'tcx> { @@ -767,6 +767,7 @@ impl<'tcx> Generics<'tcx> { Generics { types: VecPerParamSpace::empty(), regions: VecPerParamSpace::empty(), + has_self: false, } } @@ -1224,7 +1225,7 @@ impl<'tcx> TraitRef<'tcx> { } pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.self_ty().unwrap() + *self.substs.types.get(subst::SelfSpace, 0) } pub fn input_types(&self) -> &[Ty<'tcx>] { @@ -1298,23 +1299,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // so for now just grab environment for the impl let impl_id = tcx.map.get_parent(id); let impl_def_id = tcx.map.local_def_id(impl_id); - let scheme = tcx.lookup_item_type(impl_def_id); - let predicates = tcx.lookup_predicates(impl_def_id); tcx.construct_parameter_environment(impl_item.span, - &scheme.generics, - &predicates, + impl_def_id, tcx.region_maps.item_extent(id)) } hir::ImplItemKind::Method(_, ref body) => { let method_def_id = tcx.map.local_def_id(id); match tcx.impl_or_trait_item(method_def_id) { MethodTraitItem(ref method_ty) => { - let method_generics = &method_ty.generics; - let method_bounds = &method_ty.predicates; tcx.construct_parameter_environment( impl_item.span, - method_generics, - method_bounds, + method_ty.def_id, tcx.region_maps.call_site_extent(id, body.id)) } _ => { @@ -1332,11 +1327,8 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // so for now just grab environment for the trait let trait_id = tcx.map.get_parent(id); let trait_def_id = tcx.map.local_def_id(trait_id); - let trait_def = tcx.lookup_trait_def(trait_def_id); - let predicates = tcx.lookup_predicates(trait_def_id); tcx.construct_parameter_environment(trait_item.span, - &trait_def.generics, - &predicates, + trait_def_id, tcx.region_maps.item_extent(id)) } hir::MethodTraitItem(_, ref body) => { @@ -1346,8 +1338,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { let method_def_id = tcx.map.local_def_id(id); match tcx.impl_or_trait_item(method_def_id) { MethodTraitItem(ref method_ty) => { - let method_generics = &method_ty.generics; - let method_bounds = &method_ty.predicates; let extent = if let Some(ref body) = *body { // default impl: use call_site extent as free_id_outlive bound. tcx.region_maps.call_site_extent(id, body.id) @@ -1357,8 +1347,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { }; tcx.construct_parameter_environment( trait_item.span, - method_generics, - method_bounds, + method_ty.def_id, extent) } _ => { @@ -1375,13 +1364,10 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { hir::ItemFn(_, _, _, _, _, ref body) => { // We assume this is a function. let fn_def_id = tcx.map.local_def_id(id); - let fn_scheme = tcx.lookup_item_type(fn_def_id); - let fn_predicates = tcx.lookup_predicates(fn_def_id); tcx.construct_parameter_environment( item.span, - &fn_scheme.generics, - &fn_predicates, + fn_def_id, tcx.region_maps.call_site_extent(id, body.id)) } hir::ItemEnum(..) | @@ -1391,20 +1377,14 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { hir::ItemConst(..) | hir::ItemStatic(..) => { let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - let predicates = tcx.lookup_predicates(def_id); tcx.construct_parameter_environment(item.span, - &scheme.generics, - &predicates, + def_id, tcx.region_maps.item_extent(id)) } hir::ItemTrait(..) => { let def_id = tcx.map.local_def_id(id); - let trait_def = tcx.lookup_trait_def(def_id); - let predicates = tcx.lookup_predicates(def_id); tcx.construct_parameter_environment(item.span, - &trait_def.generics, - &predicates, + def_id, tcx.region_maps.item_extent(id)) } _ => { @@ -1425,11 +1405,8 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { } Some(ast_map::NodeForeignItem(item)) => { let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - let predicates = tcx.lookup_predicates(def_id); tcx.construct_parameter_environment(item.span, - &scheme.generics, - &predicates, + def_id, ROOT_CODE_EXTENT) } _ => { @@ -1462,7 +1439,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { /// `lookup_predicates`. #[derive(Clone, Debug)] pub struct TypeScheme<'tcx> { - pub generics: Generics<'tcx>, + pub generics: &'tcx Generics<'tcx>, pub ty: Ty<'tcx>, } @@ -1917,9 +1894,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { }; let sized_predicate = Binder(TraitRef { def_id: sized_trait, - substs: tcx.mk_substs(Substs::new_trait( - vec![], vec![], ty - )) + substs: Substs::new_trait(tcx, vec![], vec![], ty) }).to_predicate(); let predicates = tcx.lookup_predicates(self.did).predicates; if predicates.into_iter().any(|p| p == sized_predicate) { @@ -2170,7 +2145,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> { match self.tables.borrow().item_substs.get(&id) { None => ItemSubsts { - substs: self.global_tcx().mk_substs(Substs::empty()) + substs: Substs::empty(self.global_tcx()) }, Some(ts) => ts.clone(), } @@ -2508,27 +2483,36 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // Register a given item type - pub fn register_item_type(self, did: DefId, ty: TypeScheme<'gcx>) { - self.tcache.borrow_mut().insert(did, ty); + pub fn register_item_type(self, did: DefId, scheme: TypeScheme<'gcx>) { + self.tcache.borrow_mut().insert(did, scheme.ty); + self.generics.borrow_mut().insert(did, scheme.generics); } // If the given item is in an external crate, looks up its type and adds it to // the type cache. Returns the type parameters and type. pub fn lookup_item_type(self, did: DefId) -> TypeScheme<'gcx> { - lookup_locally_or_in_crate_store( + let ty = lookup_locally_or_in_crate_store( "tcache", did, &self.tcache, - || self.sess.cstore.item_type(self.global_tcx(), did)) + || self.sess.cstore.item_type(self.global_tcx(), did)); + + TypeScheme { + ty: ty, + generics: self.lookup_generics(did) + } } pub fn opt_lookup_item_type(self, did: DefId) -> Option> { - if let Some(scheme) = self.tcache.borrow_mut().get(&did) { - return Some(scheme.clone()); + if did.krate != LOCAL_CRATE { + return Some(self.lookup_item_type(did)); } - if did.krate == LOCAL_CRATE { - None + if let Some(ty) = self.tcache.borrow().get(&did).cloned() { + Some(TypeScheme { + ty: ty, + generics: self.lookup_generics(did) + }) } else { - Some(self.sess.cstore.item_type(self.global_tcx(), did)) + None } } @@ -2557,6 +2541,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.lookup_adt_def_master(did) } + /// Given the did of an item, returns its generics. + pub fn lookup_generics(self, did: DefId) -> &'gcx Generics<'gcx> { + lookup_locally_or_in_crate_store( + "generics", did, &self.generics, + || self.sess.cstore.item_generics(self.global_tcx(), did)) + } + /// Given the did of an item, returns its full set of predicates. pub fn lookup_predicates(self, did: DefId) -> GenericPredicates<'gcx> { lookup_locally_or_in_crate_store( @@ -2812,18 +2803,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// If the given def ID describes an item belonging to a trait (either a - /// default method or an implementation of a trait method), return the ID of - /// the trait that the method belongs to. Otherwise, return `None`. + /// If the given def ID describes an item belonging to a trait, + /// return the ID of the trait that the trait item belongs to. + /// Otherwise, return `None`. pub fn trait_of_item(self, def_id: DefId) -> Option { if def_id.krate != LOCAL_CRATE { - return self.sess.cstore.trait_of_item(self.global_tcx(), def_id); + return self.sess.cstore.trait_of_item(def_id); } - match self.impl_or_trait_items.borrow().get(&def_id).cloned() { + match self.impl_or_trait_items.borrow().get(&def_id) { Some(impl_or_trait_item) => { match impl_or_trait_item.container() { TraitContainer(def_id) => Some(def_id), - ImplContainer(def_id) => self.trait_id_of_impl(def_id), + ImplContainer(_) => None } } None => None @@ -2837,18 +2828,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// the same). /// Otherwise, return `None`. pub fn trait_item_of_item(self, def_id: DefId) -> Option { - let impl_item = match self.impl_or_trait_items.borrow().get(&def_id) { + let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) { Some(m) => m.clone(), None => return None, }; - let name = impl_item.name(); - match self.trait_of_item(def_id) { - Some(trait_did) => { - self.trait_items(trait_did).iter() - .find(|item| item.name() == name) - .map(|item| item.id()) + match impl_or_trait_item.container() { + TraitContainer(_) => Some(impl_or_trait_item.id()), + ImplContainer(def_id) => { + self.trait_id_of_impl(def_id).and_then(|trait_did| { + let name = impl_or_trait_item.name(); + self.trait_items(trait_did).iter() + .find(|item| item.name() == name) + .map(|item| item.id()) + }) } - None => None } } @@ -2860,7 +2853,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // regions, so it shouldn't matter what we use for the free id let free_id_outlive = self.region_maps.node_extent(ast::DUMMY_NODE_ID); ty::ParameterEnvironment { - free_substs: self.mk_substs(Substs::empty()), + free_substs: Substs::empty(self), caller_bounds: Vec::new(), implicit_region_bound: ty::ReEmpty, free_id_outlive: free_id_outlive @@ -2872,28 +2865,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// In general, this means converting from bound parameters to /// free parameters. Since we currently represent bound/free type /// parameters in the same way, this only has an effect on regions. - pub fn construct_free_substs(self, generics: &Generics<'gcx>, - free_id_outlive: CodeExtent) -> Substs<'gcx> { - // map T => T - let types = generics.types.map(|def| { - debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", - def); + pub fn construct_free_substs(self, def_id: DefId, + free_id_outlive: CodeExtent) + -> &'gcx Substs<'gcx> { + + let substs = Substs::for_item(self.global_tcx(), def_id, |def, _| { + // map bound 'a => free 'a + ReFree(FreeRegion { scope: free_id_outlive, + bound_region: def.to_bound_region() }) + }, |def, _| { + // map T => T self.global_tcx().mk_param_from_def(def) }); - // map bound 'a => free 'a - let regions = generics.regions.map(|def| { - let region = - ReFree(FreeRegion { scope: free_id_outlive, - bound_region: def.to_bound_region() }); - debug!("push_region_params {:?}", region); - region - }); - - Substs { - types: types, - regions: regions, - } + debug!("construct_parameter_environment: {:?}", substs); + substs } /// See `ParameterEnvironment` struct def'n for details. @@ -2901,8 +2887,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// for the `free_id_outlive` parameter. (But note that that is not always quite right.) pub fn construct_parameter_environment(self, span: Span, - generics: &ty::Generics<'gcx>, - generic_predicates: &ty::GenericPredicates<'gcx>, + def_id: DefId, free_id_outlive: CodeExtent) -> ParameterEnvironment<'gcx> { @@ -2910,14 +2895,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Construct the free substs. // - let free_substs = self.construct_free_substs(generics, free_id_outlive); + let free_substs = self.construct_free_substs(def_id, free_id_outlive); // // Compute the bounds on Self and the type parameters. // let tcx = self.global_tcx(); - let bounds = generic_predicates.instantiate(tcx, &free_substs); + let generic_predicates = tcx.lookup_predicates(def_id); + let bounds = generic_predicates.instantiate(tcx, free_substs); let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds)); let predicates = bounds.predicates; @@ -2935,7 +2921,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // let unnormalized_env = ty::ParameterEnvironment { - free_substs: tcx.mk_substs(free_substs), + free_substs: free_substs, implicit_region_bound: ty::ReScope(free_id_outlive), caller_bounds: predicates, free_id_outlive: free_id_outlive, diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index aa48474e50c..388e8926403 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -14,7 +14,7 @@ //! type equality, etc. use hir::def_id::DefId; -use ty::subst::{ParamSpace, Substs}; +use ty::subst::Substs; use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::error::{ExpectedFound, TypeError}; use std::rc::Rc; @@ -145,82 +145,44 @@ pub fn relate_substs<'a, 'gcx, 'tcx, R>(relation: &mut R, -> RelateResult<'tcx, &'tcx Substs<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let mut substs = Substs::empty(); + let tcx = relation.tcx(); + let mut result = Ok(()); - for &space in &ParamSpace::all() { - let a_tps = a_subst.types.get_slice(space); - let b_tps = b_subst.types.get_slice(space); - let t_variances = variances.map(|v| v.types.get_slice(space)); - let tps = relate_type_params(relation, t_variances, a_tps, b_tps)?; - substs.types.replace(space, tps); - } + let types = a_subst.types.map_enumerated(|(space, i, a_ty)| { + if result.is_err() { return tcx.types.err; } - 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); - } + let b_ty = b_subst.types.get(space, i); + let variance = variances.map_or(ty::Invariant, |v| { + *v.types.get(space, i) + }); + match relation.relate_with_variance(variance, a_ty, b_ty) { + Ok(ty) => ty, + Err(e) => { + result = Err(e); + tcx.types.err + } + } + }); + result?; - Ok(relation.tcx().mk_substs(substs)) -} + let regions = a_subst.regions.map_enumerated(|(space, i, a_r)| { + if result.is_err() { return ty::ReStatic; } -fn relate_type_params<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&[ty::Variance]>, - a_tys: &[Ty<'tcx>], - b_tys: &[Ty<'tcx>]) - -> RelateResult<'tcx, Vec>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a -{ - if a_tys.len() != b_tys.len() { - return Err(TypeError::TyParamSize(expected_found(relation, - &a_tys.len(), - &b_tys.len()))); - } + let b_r = b_subst.regions.get(space, i); + let variance = variances.map_or(ty::Invariant, |v| { + *v.regions.get(space, i) + }); + match relation.relate_with_variance(variance, a_r, b_r) { + Ok(r) => r, + Err(e) => { + result = Err(e); + ty::ReStatic + } + } + }); + result?; - (0 .. a_tys.len()) - .map(|i| { - let a_ty = a_tys[i]; - let b_ty = b_tys[i]; - let v = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(v, &a_ty, &b_ty) - }) - .collect() -} - -fn relate_region_params<'a, 'gcx, 'tcx, R>(relation: &mut R, - variances: Option<&[ty::Variance]>, - a_rs: &[ty::Region], - b_rs: &[ty::Region]) - -> RelateResult<'tcx, Vec> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a -{ - let num_region_params = a_rs.len(); - - debug!("relate_region_params(a_rs={:?}, \ - b_rs={:?}, variances={:?})", - a_rs, - b_rs, - variances); - - assert_eq!(num_region_params, - variances.map_or(num_region_params, - |v| v.len())); - - assert_eq!(num_region_params, b_rs.len()); - - (0..a_rs.len()) - .map(|i| { - let a_r = a_rs[i]; - let b_r = b_rs[i]; - let variance = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(variance, &a_r, &b_r) - }) - .collect() + Ok(Substs::new(tcx, types, regions)) } impl<'tcx> Relate<'tcx> for &'tcx ty::BareFnTy<'tcx> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 14005c1bd8b..9021b0587a0 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -9,7 +9,7 @@ // except according to those terms. use infer::type_variable; -use ty::subst::{self, VecPerParamSpace}; +use ty::subst::{Substs, VecPerParamSpace}; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -702,13 +702,11 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Region { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx subst::Substs<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx Substs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - let substs = subst::Substs { - regions: self.regions.fold_with(folder), - types: self.types.fold_with(folder) - }; - folder.tcx().mk_substs(substs) + let types = self.types.fold_with(folder); + let regions = self.regions.fold_with(folder); + Substs::new(folder.tcx(), types, regions) } fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { @@ -839,6 +837,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> { ty::Generics { types: self.types.fold_with(folder), regions: self.regions.fold_with(folder), + has_self: self.has_self } } @@ -1018,19 +1017,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TypeScheme<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TypeScheme { - generics: self.generics.fold_with(folder), - ty: self.ty.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.generics.visit_with(visitor) || self.ty.visit_with(visitor) - } -} - impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::error::ExpectedFound { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 91214873f19..f31b844f04f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -359,18 +359,7 @@ pub struct ExistentialTraitRef<'tcx> { pub substs: &'tcx Substs<'tcx>, } -impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { - pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_ref: ty::TraitRef<'tcx>) - -> ty::ExistentialTraitRef<'tcx> { - let mut substs = trait_ref.substs.clone(); - substs.types.pop(subst::SelfSpace); - ty::ExistentialTraitRef { - def_id: trait_ref.def_id, - substs: tcx.mk_substs(substs) - } - } - +impl<'tcx> ExistentialTraitRef<'tcx> { pub fn input_types(&self) -> &[Ty<'tcx>] { // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the @@ -382,7 +371,7 @@ impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { pub type PolyExistentialTraitRef<'tcx> = Binder>; -impl<'a, 'gcx, 'tcx> PolyExistentialTraitRef<'tcx> { +impl<'tcx> PolyExistentialTraitRef<'tcx> { pub fn def_id(&self) -> DefId { self.0.def_id } @@ -391,23 +380,6 @@ impl<'a, 'gcx, 'tcx> PolyExistentialTraitRef<'tcx> { // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> self.0.input_types() } - - /// Object types don't have a self-type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self-type. A common choice is `mk_err()` - /// or some skolemized type. - pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> ty::PolyTraitRef<'tcx> - { - // otherwise the escaping regions would be captured by the binder - assert!(!self_ty.has_escaping_regions()); - - self.map_bound(|trait_ref| TraitRef { - def_id: trait_ref.def_id, - substs: tcx.mk_substs(trait_ref.substs.with_self_ty(self_ty)), - }) - } } /// Binder is a binder for higher-ranked lifetimes. It is part of the diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 34e7899e2fd..00537f9d6c5 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -34,43 +34,45 @@ pub struct Substs<'tcx> { } impl<'a, 'gcx, 'tcx> Substs<'tcx> { - pub fn new(t: VecPerParamSpace>, + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: VecPerParamSpace>, r: VecPerParamSpace) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs { types: t, regions: r } + tcx.mk_substs(Substs { types: t, regions: r }) } - pub fn new_fn(t: Vec>, + pub fn new_fn(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, r: Vec) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(vec![], vec![], t), + Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], t), VecPerParamSpace::new(vec![], vec![], r)) } - pub fn new_type(t: Vec>, + pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, r: Vec) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(vec![], t, vec![]), + Substs::new(tcx, VecPerParamSpace::new(vec![], t, vec![]), VecPerParamSpace::new(vec![], r, vec![])) } - pub fn new_trait(t: Vec>, + pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, r: Vec, s: Ty<'tcx>) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(vec![s], t, vec![]), + Substs::new(tcx, VecPerParamSpace::new(vec![s], t, vec![]), VecPerParamSpace::new(vec![], r, vec![])) } - pub fn empty() -> Substs<'tcx> { - Substs { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty(), - } + pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { + Substs::new(tcx, VecPerParamSpace::empty(), + VecPerParamSpace::empty()) } /// Creates a Substs for generic parameter definitions, @@ -78,26 +80,57 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { /// The closures get to observe the Substs as they're /// being built, which can be used to correctly /// substitute defaults of type parameters. - pub fn from_generics(generics: &ty::Generics<'tcx>, - mut mk_region: FR, - mut mk_type: FT) - -> Substs<'tcx> + pub fn for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_id: DefId, + mut mk_region: FR, + mut mk_type: FT) + -> &'tcx Substs<'tcx> where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { - let mut substs = Substs::empty(); - for &space in &ParamSpace::all() { - for def in generics.regions.get_slice(space) { - let region = mk_region(def, &substs); - assert_eq!(substs.regions.len(def.space), def.index as usize); - substs.regions.push(def.space, region); + let defs = tcx.lookup_generics(def_id); + let mut substs = Substs { + types: VecPerParamSpace { + self_limit: 0, + type_limit: 0, + content: Vec::with_capacity(defs.types.content.len()) + }, + regions: VecPerParamSpace { + self_limit: 0, + type_limit: 0, + content: Vec::with_capacity(defs.regions.content.len()) } - for def in generics.types.get_slice(space) { + }; + + for &space in &ParamSpace::all() { + for def in defs.regions.get_slice(space) { + assert_eq!(def.space, space); + assert!(space != SelfSpace); + + let region = mk_region(def, &substs); + substs.regions.content.push(region); + + if space == TypeSpace { + substs.regions.type_limit += 1; + } + } + + for def in defs.types.get_slice(space) { + assert_eq!(def.space, space); + let ty = mk_type(def, &substs); - assert_eq!(substs.types.len(def.space), def.index as usize); - substs.types.push(def.space, ty); + substs.types.content.push(ty); + + if space == SelfSpace { + substs.types.self_limit += 1; + } + + if space <= TypeSpace { + substs.types.type_limit += 1; + } } } - substs + + Substs::new(tcx, substs.types, substs.regions) } pub fn is_noop(&self) -> bool { @@ -112,66 +145,32 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { *self.regions.get(def.space, def.index as usize) } - pub fn self_ty(&self) -> Option> { - self.types.get_self().cloned() - } + /// Transform from substitutions for a child of `source_ancestor` + /// (e.g. a trait or impl) to substitutions for the same child + /// in a different item, with `target_substs` as the base for + /// the target impl/trait, with the source child-specific + /// parameters (e.g. method parameters) on top of that base. + pub fn rebase_onto(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + source_ancestor: DefId, + target_substs: &Substs<'tcx>) + -> &'tcx Substs<'tcx> { + let defs = tcx.lookup_generics(source_ancestor); + assert_eq!(self.types.len(SelfSpace), defs.types.len(SelfSpace)); + assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace)); + assert_eq!(target_substs.types.len(FnSpace), 0); + assert_eq!(defs.types.len(FnSpace), 0); + assert_eq!(self.regions.len(TypeSpace), defs.regions.len(TypeSpace)); + assert_eq!(target_substs.regions.len(FnSpace), 0); + assert_eq!(defs.regions.len(FnSpace), 0); - pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> { - assert!(self.self_ty().is_none()); - let mut s = (*self).clone(); - s.types.push(SelfSpace, self_ty); - s - } - - pub fn erase_regions(self) -> Substs<'tcx> { - let Substs { types, regions } = self; - let regions = regions.map(|_| ty::ReErased); - Substs { types: types, regions: regions } - } - - pub fn with_method(self, - m_types: Vec>, - m_regions: Vec) - -> Substs<'tcx> - { - let Substs { types, regions } = self; - let types = types.with_slice(FnSpace, &m_types); - let regions = regions.with_slice(FnSpace, &m_regions); - Substs { types: types, regions: regions } - } - - pub fn with_method_from(&self, - meth_substs: &Substs<'tcx>) - -> Substs<'tcx> - { - let Substs { types, regions } = self.clone(); - let types = types.with_slice(FnSpace, meth_substs.types.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.clone(); - let types = types.with_slice(FnSpace, other.types.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<'a, 'gcx, 'tcx>, trait_id: DefId) - -> ty::TraitRef<'tcx> { - let Substs { mut types, mut regions } = self.clone(); - types.truncate(FnSpace, 0); - regions.truncate(FnSpace, 0); - - ty::TraitRef { - def_id: trait_id, - substs: tcx.mk_substs(Substs { types: types, regions: regions }) - } + let Substs { mut types, mut regions } = target_substs.clone(); + types.content.extend(&self.types.as_full_slice()[defs.types.content.len()..]); + regions.content.extend(&self.regions.as_full_slice()[defs.regions.content.len()..]); + Substs::new(tcx, types, regions) } } -impl<'tcx> Encodable for Substs<'tcx> { +impl<'tcx> Encodable for &'tcx Substs<'tcx> { fn encode(&self, s: &mut S) -> Result<(), S::Error> { cstore::tls::with_encoding_context(s, |ecx, rbml_w| { ecx.encode_substs(rbml_w, self); @@ -180,19 +179,10 @@ impl<'tcx> Encodable for Substs<'tcx> { } } -impl<'tcx> Decodable for Substs<'tcx> { - fn decode(d: &mut D) -> Result, D::Error> { - cstore::tls::with_decoding_context(d, |dcx, rbml_r| { - Ok(dcx.decode_substs(rbml_r)) - }) - } -} - impl<'tcx> Decodable for &'tcx Substs<'tcx> { fn decode(d: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error> { let substs = cstore::tls::with_decoding_context(d, |dcx, rbml_r| { - let substs = dcx.decode_substs(rbml_r); - dcx.tcx().mk_substs(substs) + dcx.decode_substs(rbml_r) }); Ok(substs) @@ -307,70 +297,6 @@ impl VecPerParamSpace { } } - /// Appends `value` to the vector associated with `space`. - /// - /// Unlike the `push` method in `Vec`, this should not be assumed - /// to be a cheap operation (even when amortized over many calls). - pub fn push(&mut self, space: ParamSpace, value: T) { - let (_, limit) = self.limits(space); - match space { - SelfSpace => { self.type_limit += 1; self.self_limit += 1; } - TypeSpace => { self.type_limit += 1; } - FnSpace => { } - } - self.content.insert(limit, value); - } - - /// Appends `values` to the vector associated with `space`. - /// - /// Unlike the `extend` method in `Vec`, this should not be assumed - /// to be a cheap operation (even when amortized over many calls). - pub fn extend>(&mut self, space: ParamSpace, values: I) { - // This could be made more efficient, obviously. - for item in values { - self.push(space, item); - } - } - - pub fn pop(&mut self, space: ParamSpace) -> Option { - let (start, limit) = self.limits(space); - if start == limit { - None - } else { - match space { - SelfSpace => { self.type_limit -= 1; self.self_limit -= 1; } - TypeSpace => { self.type_limit -= 1; } - FnSpace => {} - } - if self.content.is_empty() { - None - } else { - Some(self.content.remove(limit - 1)) - } - } - } - - pub fn truncate(&mut self, space: ParamSpace, len: usize) { - // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n). - while self.len(space) > len { - self.pop(space); - } - } - - pub fn replace(&mut self, space: ParamSpace, elems: Vec) { - // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n). - self.truncate(space, 0); - for t in elems { - self.push(space, t); - } - } - - pub fn get_self<'a>(&'a self) -> Option<&'a T> { - let v = self.get_slice(SelfSpace); - assert!(v.len() <= 1); - if v.is_empty() { None } else { Some(&v[0]) } - } - pub fn len(&self, space: ParamSpace) -> usize { self.get_slice(space).len() } @@ -384,19 +310,6 @@ impl VecPerParamSpace { &self.content[start.. limit] } - pub fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] { - let (start, limit) = self.limits(space); - &mut self.content[start.. limit] - } - - pub fn opt_get<'a>(&'a self, - space: ParamSpace, - index: usize) - -> Option<&'a T> { - let v = self.get_slice(space); - if index < v.len() { Some(&v[index]) } else { None } - } - pub fn get<'a>(&'a self, space: ParamSpace, index: usize) -> &'a T { &self.get_slice(space)[index] } @@ -409,12 +322,6 @@ impl VecPerParamSpace { &self.content } - pub fn all_vecs

(&self, mut pred: P) -> bool where - P: FnMut(&[T]) -> bool, - { - ParamSpace::all().iter().all(|&space| { pred(self.get_slice(space)) }) - } - pub fn all

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { self.as_full_slice().iter().all(pred) } @@ -424,7 +331,7 @@ impl VecPerParamSpace { } pub fn is_empty(&self) -> bool { - self.all_vecs(|v| v.is_empty()) + self.content.is_empty() } pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { @@ -442,18 +349,6 @@ impl VecPerParamSpace { self.self_limit, self.type_limit) } - - pub fn with_slice(mut self, space: ParamSpace, slice: &[T]) - -> VecPerParamSpace - where T: Clone - { - assert!(self.is_empty_in(space)); - for t in slice { - self.push(space, t.clone()); - } - - self - } } #[derive(Clone)] @@ -581,7 +476,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { // the specialized routine `ty::replace_late_regions()`. match r { ty::ReEarlyBound(data) => { - match self.substs.regions.opt_get(data.space, data.index as usize) { + match self.substs.regions.get_slice(data.space).get(data.index as usize) { Some(&r) => { self.shift_region_through_binders(r) } @@ -637,7 +532,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { // Look up the type in the substitutions. It really should be in there. - let opt_ty = self.substs.types.opt_get(p.space, p.idx as usize); + let opt_ty = self.substs.types.get_slice(p.space).get(p.idx as usize); let ty = match opt_ty { Some(t) => *t, None => { @@ -718,3 +613,67 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> { ty::fold::shift_region(region, self.region_binders_passed) } } + +// Helper methods that modify substitutions. + +impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> { + pub fn from_method(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_id: DefId, + substs: &Substs<'tcx>) + -> ty::TraitRef<'tcx> { + let Substs { mut types, mut regions } = substs.clone(); + let defs = tcx.lookup_generics(trait_id); + types.content.truncate(defs.types.type_limit); + regions.content.truncate(defs.regions.type_limit); + + ty::TraitRef { + def_id: trait_id, + substs: Substs::new(tcx, types, regions) + } + } +} + +impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> { + pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_ref: ty::TraitRef<'tcx>) + -> ty::ExistentialTraitRef<'tcx> { + let Substs { mut types, regions } = trait_ref.substs.clone(); + + assert_eq!(types.self_limit, 1); + types.self_limit = 0; + types.type_limit -= 1; + types.content.remove(0); + + ty::ExistentialTraitRef { + def_id: trait_ref.def_id, + substs: Substs::new(tcx, types, regions) + } + } +} + +impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> { + /// Object types don't have a self-type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self-type. A common choice is `mk_err()` + /// or some skolemized type. + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + self_ty: Ty<'tcx>) + -> ty::PolyTraitRef<'tcx> { + // otherwise the escaping regions would be captured by the binder + assert!(!self_ty.has_escaping_regions()); + + self.map_bound(|trait_ref| { + let Substs { mut types, regions } = trait_ref.substs.clone(); + + assert_eq!(types.self_limit, 0); + types.self_limit = 1; + types.type_limit += 1; + types.content.insert(0, self_ty); + + ty::TraitRef { + def_id: trait_ref.def_id, + substs: Substs::new(tcx, types, regions) + } + }) + } +} diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index a76dfc35dc1..61285e8f8b0 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -34,7 +34,7 @@ pub struct TraitDef<'tcx> { /// `Eq`, there is a single bound `Self : Eq`). This is so that /// default methods get to assume that the `Self` parameters /// implements the trait. - pub generics: ty::Generics<'tcx>, + pub generics: &'tcx ty::Generics<'tcx>, pub trait_ref: ty::TraitRef<'tcx>, @@ -76,7 +76,7 @@ pub struct TraitDef<'tcx> { impl<'a, 'gcx, 'tcx> TraitDef<'tcx> { pub fn new(unsafety: hir::Unsafety, paren_sugar: bool, - generics: ty::Generics<'tcx>, + generics: &'tcx ty::Generics<'tcx>, trait_ref: ty::TraitRef<'tcx>, associated_type_names: Vec) -> TraitDef<'tcx> { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 3c1f6e91992..5a73439beac 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -11,7 +11,6 @@ //! misc. type-system utilities too small to deserve their own file use hir::def_id::DefId; -use ty::subst; use infer::InferCtxt; use hir::pat_util; use traits::{self, Reveal}; @@ -695,12 +694,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> { return false; } - let types_a = substs_a.types.get_slice(subst::TypeSpace); - let types_b = substs_b.types.get_slice(subst::TypeSpace); + let types_a = substs_a.types.as_full_slice(); + let types_b = substs_b.types.as_full_slice(); - let mut pairs = types_a.iter().zip(types_b); - - pairs.all(|(&a, &b)| same_type(a, b)) + types_a.iter().zip(types_b).all(|(&a, &b)| same_type(a, b)) } _ => { a == b diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fb0b6413fab..cdbd3070523 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,7 +10,7 @@ use hir::def_id::DefId; -use ty::subst::{self, Subst}; +use ty::subst::{self, Subst, Substs}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{TyBool, TyChar, TyStruct, TyEnum}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; @@ -65,69 +65,57 @@ pub enum Ns { fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &subst::Substs, space: subst::ParamSpace, - generics: ty::Generics<'tcx>) + generics: &ty::Generics<'tcx>) -> usize { - let has_self = substs.self_ty().is_some(); let ty_params = generics.types.get_slice(space); let tps = substs.types.get_slice(space); if ty_params.last().map_or(false, |def| def.default.is_some()) { let substs = tcx.lift(&substs); ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| { - match def.default { - Some(default) => { - if !has_self && default.has_self_ty() { - // In an object type, there is no `Self`, and - // thus if the default value references Self, - // the user will be required to give an - // explicit value. We can't even do the - // substitution below to check without causing - // an ICE. (#18956). - false - } else { - let default = tcx.lift(&default); - substs.and_then(|substs| default.subst(tcx, substs)) - == Some(actual) - } - } - None => false - } + substs.and_then(|substs| def.default.subst(tcx, substs)) + == Some(actual) }).count() } else { 0 } } -pub fn parameterized(f: &mut fmt::Formatter, - substs: &subst::Substs, - did: DefId, - ns: Ns, - projections: &[ty::ProjectionPredicate], - get_generics: GG) - -> fmt::Result - where GG: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) - -> Option> -{ - if let (Ns::Value, Some(self_ty)) = (ns, substs.self_ty()) { - write!(f, "<{} as ", self_ty)?; - } +pub fn parameterized(f: &mut fmt::Formatter, + substs: &subst::Substs, + did: DefId, + ns: Ns, + projections: &[ty::ProjectionPredicate]) + -> fmt::Result { + let (fn_trait_kind, verbose, item_name, is_in_trait) = ty::tls::with(|tcx| { + let is_in_trait = ns == Ns::Value && tcx.trait_of_item(did).is_some(); + if is_in_trait { + write!(f, "<{} as ", substs.types.get(subst::SelfSpace, 0))?; + } - let (fn_trait_kind, verbose, item_name) = ty::tls::with(|tcx| { let (did, item_name) = if ns == Ns::Value { // Try to get the impl/trait parent, if this is an // associated value item (method or constant). - tcx.trait_of_item(did).or_else(|| tcx.impl_of_method(did)) - .map_or((did, None), |parent| (parent, Some(tcx.item_name(did)))) + tcx.trait_of_item(did).or_else(|| { + // An impl could be a trait impl or an inherent one. + tcx.impl_of_method(did).map(|impl_def_id| { + tcx.trait_id_of_impl(impl_def_id) + .unwrap_or(impl_def_id) + }) + }).map_or((did, None), |parent| (parent, Some(tcx.item_name(did)))) } else { (did, None) }; write!(f, "{}", tcx.item_path_str(did))?; - Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose(), item_name)) + Ok((tcx.lang_items.fn_trait_kind(did), + tcx.sess.verbose(), + item_name, + is_in_trait)) })?; if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; - if let TyTuple(ref args) = substs.types.get_slice(subst::TypeSpace)[0].sty { + if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 0).sty { return fn_sig(f, args, false, projection_ty); } } @@ -176,11 +164,8 @@ pub fn parameterized(f: &mut fmt::Formatter, 0 } else { ty::tls::with(|tcx| { - if let Some(generics) = get_generics(tcx) { - number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics) - } else { - 0 - } + let generics = tcx.lookup_generics(did); + number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics) }) }; @@ -204,7 +189,7 @@ pub fn parameterized(f: &mut fmt::Formatter, if ns == Ns::Value { empty.set(true); - if substs.self_ty().is_some() { + if is_in_trait { write!(f, ">")?; } @@ -288,7 +273,7 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, /// projection bounds, so we just stuff them altogether. But in /// reality we should eventually sort things out better. #[derive(Clone, Debug)] -struct TraitAndProjections<'tcx>(ty::ExistentialTraitRef<'tcx>, +struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec>); impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> { @@ -307,8 +292,7 @@ impl<'tcx> fmt::Display for TraitAndProjections<'tcx> { parameterized(f, trait_ref.substs, trait_ref.def_id, Ns::Type, - projection_bounds, - |tcx| Some(tcx.lookup_trait_def(trait_ref.def_id).generics.clone())) + projection_bounds) } } @@ -316,12 +300,16 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Generate the main trait ref, including associated types. ty::tls::with(|tcx| { - let principal = tcx.lift(&self.principal.0) - .expect("could not lift TraitRef for printing"); + // Use a type that can't appear in defaults of type parameters. + let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + + let principal = tcx.lift(&self.principal) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self).0; let projections = self.projection_bounds.iter().map(|p| { - let projection = tcx.lift(p) - .expect("could not lift projection for printing"); - projection.with_self_ty(tcx, tcx.types.err).0 + tcx.lift(p) + .expect("could not lift projection for printing") + .with_self_ty(tcx, dummy_self).0 }).collect(); let tap = ty::Binder(TraitAndProjections(principal, projections)); @@ -380,7 +368,7 @@ impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> { } } -impl<'tcx> fmt::Debug for subst::Substs<'tcx> { +impl<'tcx> fmt::Debug for Substs<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Substs[types={:?}, regions={:?}]", self.types, self.regions) @@ -404,7 +392,14 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", *self) + ty::tls::with(|tcx| { + let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + + let trait_ref = tcx.lift(&ty::Binder(*self)) + .expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self).0; + parameterized(f, trait_ref.substs, trait_ref.def_id, Ns::Type, &[]) + }) } } @@ -813,15 +808,7 @@ impl fmt::Display for ty::Binder> impl<'tcx> fmt::Display for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - parameterized(f, self.substs, self.def_id, Ns::Type, &[], - |tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone())) - } -} - -impl<'tcx> fmt::Display for ty::ExistentialTraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - parameterized(f, self.substs, self.def_id, Ns::Type, &[], - |tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone())) + parameterized(f, self.substs, self.def_id, Ns::Type, &[]) } } @@ -874,9 +861,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } write!(f, "{} {{", bare_fn.sig.0)?; - parameterized( - f, substs, def_id, Ns::Value, &[], - |tcx| tcx.opt_lookup_item_type(def_id).map(|t| t.generics))?; + parameterized(f, substs, def_id, Ns::Value, &[])?; write!(f, "}}") } TyFnPtr(ref bare_fn) => { @@ -899,12 +884,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { !tcx.tcache.borrow().contains_key(&def.did) { write!(f, "{}<..>", tcx.item_path_str(def.did)) } else { - parameterized( - f, substs, def.did, Ns::Type, &[], - |tcx| { - tcx.opt_lookup_item_type(def.did). - map(|t| t.generics) - }) + parameterized(f, substs, def.did, Ns::Type, &[]) } }) } @@ -916,7 +896,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { // by looking up the projections associated with the def_id. let item_predicates = tcx.lookup_predicates(def_id); let substs = tcx.lift(&substs).unwrap_or_else(|| { - tcx.mk_substs(subst::Substs::empty()) + Substs::empty(tcx) }); let bounds = item_predicates.instantiate(tcx, substs); diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index f6e9484eda1..df91ec2b98d 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -859,10 +859,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil())); let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = tcx.mk_substs(Substs::new( + let substs = Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], vec![ty]), - VecPerParamSpace::new(vec![], vec![], vec![]) - )); + VecPerParamSpace::new(vec![], vec![], vec![])); let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs); self.patch.new_block(BasicBlockData { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 73b54c4374f..d71add3258f 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -22,8 +22,9 @@ use rustc::traits; use rustc::hir::def::{Def, PathResolution}; use rustc::hir::def_id::DefId; use rustc::hir::pat_util::def_to_path; -use rustc::ty::{self, Ty, TyCtxt, subst}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; +use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; use rustc::util::nodemap::NodeMap; @@ -93,7 +94,7 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// This generally happens in late/trans const evaluation. pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - substs: Option<&'tcx subst::Substs<'tcx>>) + substs: Option<&'tcx Substs<'tcx>>) -> Option<(&'tcx Expr, Option>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { match tcx.map.find(node_id) { @@ -110,7 +111,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // If we have a trait item and the substitutions for it, // `resolve_trait_associated_const` will select an impl // or the default. - let trait_id = tcx.trait_of_item(def_id).unwrap(); + let trait_id = tcx.map.get_parent(node_id); + let trait_id = tcx.map.local_def_id(trait_id); resolve_trait_associated_const(tcx, ti, trait_id, substs) } else { // Technically, without knowing anything about the @@ -1045,16 +1047,14 @@ fn infer<'a, 'tcx>(i: ConstInt, fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ti: &'tcx hir::TraitItem, trait_id: DefId, - rcvr_substs: &'tcx subst::Substs<'tcx>) + rcvr_substs: &'tcx Substs<'tcx>) -> Option<(&'tcx Expr, Option>)> { - let trait_ref = ty::Binder( - rcvr_substs.clone().erase_regions().to_trait_ref(tcx, trait_id) - ); + let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); - tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); + tcx.populate_implementations_for_trait_if_necessary(trait_id); tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 7711091685d..c84b195dd4b 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -21,7 +21,7 @@ use rustc::middle::region::CodeExtentData; use rustc::middle::resolve_lifetime; use rustc::middle::stability; use rustc::ty::subst; -use rustc::ty::subst::Subst; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::infer::{self, InferOk, InferResult, TypeOrigin}; @@ -678,8 +678,8 @@ fn subst_ty_renumber_bound() { env.t_fn(&[t_param], env.t_nil()) }; - let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]); - let t_substituted = t_source.subst(env.infcx.tcx, &substs); + let substs = Substs::new_type(env.infcx.tcx, vec![t_rptr_bound1], vec![]); + let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = fn(&'a isize) let t_expected = { @@ -713,8 +713,8 @@ fn subst_ty_renumber_some_bounds() { env.t_pair(t_param, env.t_fn(&[t_param], env.t_nil())) }; - let substs = subst::Substs::new_type(vec![t_rptr_bound1], vec![]); - let t_substituted = t_source.subst(env.infcx.tcx, &substs); + let substs = Substs::new_type(env.infcx.tcx, vec![t_rptr_bound1], vec![]); + let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = (&'a isize, fn(&'a isize)) // @@ -775,8 +775,8 @@ fn subst_region_renumber_region() { env.t_fn(&[env.t_rptr(re_early)], env.t_nil()) }; - let substs = subst::Substs::new_type(vec![], vec![re_bound1]); - let t_substituted = t_source.subst(env.infcx.tcx, &substs); + let substs = Substs::new_type(env.infcx.tcx, vec![], vec![re_bound1]); + let t_substituted = t_source.subst(env.infcx.tcx, substs); // t_expected = fn(&'a isize) // diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ed17f3533d4..61d92723982 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -465,16 +465,14 @@ impl LateLintPass for MissingCopyImplementations { return; } let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id)); - (def, cx.tcx.mk_struct(def, - cx.tcx.mk_substs(Substs::empty()))) + (def, cx.tcx.mk_struct(def, Substs::empty(cx.tcx))) } hir::ItemEnum(_, ref ast_generics) => { if ast_generics.is_parameterized() { return; } let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id)); - (def, cx.tcx.mk_enum(def, - cx.tcx.mk_substs(Substs::empty()))) + (def, cx.tcx.mk_enum(def, Substs::empty(cx.tcx))) } _ => return, }; @@ -898,7 +896,7 @@ impl LateLintPass for UnconditionalRecursion { // A trait method, from any number of possible sources. // Attempt to select a concrete impl before checking. ty::TraitContainer(trait_def_id) => { - let trait_ref = callee_substs.to_trait_ref(tcx, trait_def_id); + let trait_ref = ty::TraitRef::from_method(tcx, trait_def_id, callee_substs); let trait_ref = ty::Binder(trait_ref); let span = tcx.map.span(expr_id); let obligation = @@ -918,8 +916,7 @@ impl LateLintPass for UnconditionalRecursion { // If `T` is `Self`, then this call is inside // a default method definition. Ok(Some(traits::VtableParam(_))) => { - let self_ty = callee_substs.self_ty(); - let on_self = self_ty.map_or(false, |t| t.is_self()); + let on_self = trait_ref.self_ty().is_self(); // We can only be recurring in a default // method if we're being called literally // on the `Self` type. diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index c552e612504..1b00eee76f6 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -34,7 +34,7 @@ use middle::const_qualif::ConstQualif; use rustc::hir::def::{self, Def}; use rustc::hir::def_id::DefId; use middle::region; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; @@ -507,7 +507,7 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> { Ok(this.read_ty(dcx)) }).unwrap(), substs: this.read_struct_field("substs", 3, |this| { - Ok(dcx.tcx.mk_substs(this.read_substs(dcx))) + Ok(this.read_substs(dcx)) }).unwrap() })) }).unwrap() @@ -525,7 +525,7 @@ trait rbml_writer_helpers<'tcx> { fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region); fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>); fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - substs: &subst::Substs<'tcx>); + substs: &Substs<'tcx>); fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture); fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, adj: &adjustment::AutoAdjustment<'tcx>); @@ -569,7 +569,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { } fn emit_substs<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - substs: &subst::Substs<'tcx>) { + substs: &Substs<'tcx>) { self.emit_opaque(|this| Ok(tyencode::enc_substs(&mut this.cursor, &ecx.ty_str_ctxt(), substs))); @@ -839,7 +839,7 @@ trait rbml_decoder_decoder_helpers<'tcx> { fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::Predicate<'tcx>; fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> subst::Substs<'tcx>; + -> &'tcx Substs<'tcx>; fn read_upvar_capture(&mut self, dcx: &DecodeContext) -> ty::UpvarCapture; fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) @@ -859,7 +859,7 @@ trait rbml_decoder_decoder_helpers<'tcx> { cdata: &cstore::CrateMetadata) -> Vec>; fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: &cstore::CrateMetadata) - -> subst::Substs<'tcx>; + -> &'tcx Substs<'tcx>; } impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { @@ -884,7 +884,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>, cdata: &cstore::CrateMetadata) - -> subst::Substs<'tcx> + -> &'tcx Substs<'tcx> { self.read_opaque(|_, doc| { Ok( @@ -946,7 +946,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { } fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> subst::Substs<'tcx> { + -> &'tcx Substs<'tcx> { self.read_opaque(|_, doc| { Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc, &mut |d| convert_def_id(dcx, d)) @@ -1140,7 +1140,7 @@ fn decode_side_tables(dcx: &DecodeContext, } c::tag_table_item_subst => { let item_substs = ty::ItemSubsts { - substs: dcx.tcx.mk_substs(val_dsr.read_substs(dcx)) + substs: val_dsr.read_substs(dcx) }; dcx.tcx.tables.borrow_mut().item_substs.insert( id, item_substs); diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 0011b59c70e..99a3f3b00c8 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -196,16 +196,11 @@ pub const tag_attribute_is_sugared_doc: usize = 0x8c; // GAP 0x8d pub const tag_items_data_region: usize = 0x8e; -pub const tag_region_param_def: usize = 0x8f; -pub const tag_region_param_def_ident: usize = 0x90; -pub const tag_region_param_def_def_id: usize = 0x91; -pub const tag_region_param_def_space: usize = 0x92; -pub const tag_region_param_def_index: usize = 0x93; +pub const tag_item_generics: usize = 0x8f; +// GAP 0x90, 0x91, 0x92, 0x93, 0x94 -pub const tag_type_param_def: usize = 0x94; - -pub const tag_item_generics: usize = 0x95; -pub const tag_method_ty_generics: usize = 0x96; +pub const tag_item_predicates: usize = 0x95; +// GAP 0x96 pub const tag_predicate: usize = 0x97; // GAP 0x98, 0x99 diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 2cdbd1b8601..f6d698eb969 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -86,7 +86,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> ty::TypeScheme<'tcx> + -> Ty<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); let cdata = self.get_crate_data(def.krate); @@ -109,6 +109,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_super_predicates(&cdata, def.index, tcx) } + fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> &'tcx ty::Generics<'tcx> + { + self.dep_graph.read(DepNode::MetaData(def)); + let cdata = self.get_crate_data(def.krate); + decoder::get_generics(&cdata, def.index, tcx) + } + fn item_attrs(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); @@ -231,11 +239,10 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_parent_impl(&*cdata, impl_def.index) } - fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option - { + fn trait_of_item(&self, def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def_id)); let cdata = self.get_crate_data(def_id.krate); - decoder::get_trait_of_item(&cdata, def_id.index, tcx) + decoder::get_trait_of_item(&cdata, def_id.index) } fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index eeb1859c013..e42825ef1e5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -264,11 +264,6 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: }) } -pub fn item_type<'a, 'tcx>(_item_id: DefId, item: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { - doc_type(item, tcx, cdata) -} - fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> ty::TraitRef<'tcx> { TyDecoder::with_doc(tcx, cdata.cnum, doc, @@ -383,7 +378,7 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> { let item_doc = cdata.lookup_item(item_id); - let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); + let generics = doc_generics(item_doc, tcx, cdata); let unsafety = parse_unsafety(item_doc); let associated_type_names = parse_associated_type_names(item_doc); let paren_sugar = parse_paren_sugar(item_doc); @@ -493,7 +488,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, // from the ctor. debug!("evaluating the ctor-type of {:?}", variant.name); - let ctor_ty = get_type(cdata, variant.did.index, tcx).ty; + let ctor_ty = get_type(cdata, variant.did.index, tcx); debug!("evaluating the ctor-type of {:?}.. {:?}", variant.name, ctor_ty); @@ -513,7 +508,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, } else { for field in &variant.fields { debug!("evaluating the type of {:?}::{:?}", variant.name, field.name); - let ty = get_type(cdata, field.did.index, tcx).ty; + let ty = get_type(cdata, field.did.index, tcx); field.fulfill_ty(ty); debug!("evaluating the type of {:?}::{:?}: {:?}", variant.name, field.name, ty); @@ -530,7 +525,7 @@ pub fn get_predicates<'a, 'tcx>(cdata: Cmd, -> ty::GenericPredicates<'tcx> { let item_doc = cdata.lookup_item(item_id); - doc_predicates(item_doc, tcx, cdata, tag_item_generics) + doc_predicates(item_doc, tcx, cdata, tag_item_predicates) } pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, @@ -542,17 +537,20 @@ pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd, doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates) } +pub fn get_generics<'a, 'tcx>(cdata: Cmd, + item_id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::Generics<'tcx> +{ + let item_doc = cdata.lookup_item(item_id); + doc_generics(item_doc, tcx, cdata) +} + pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::TypeScheme<'tcx> + -> Ty<'tcx> { let item_doc = cdata.lookup_item(id); - let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx, - cdata); - let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); - ty::TypeScheme { - generics: generics, - ty: t - } + doc_type(item_doc, tcx, cdata) } pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { @@ -960,8 +958,8 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a })) } Some('r') | Some('p') => { - let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics); - let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics); + let generics = doc_generics(item_doc, tcx, cdata); + let predicates = doc_predicates(item_doc, tcx, cdata, tag_item_predicates); let ity = tcx.lookup_item_type(def_id).ty; let fty = match ity.sty { ty::TyFnDef(_, _, fty) => fty, @@ -1393,10 +1391,7 @@ pub fn each_implementation_for_trait(cdata: Cmd, } } -pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option { +pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { let item_doc = cdata.lookup_item(id); let parent_item_id = match item_parent_item(cdata, item_doc) { None => return None, @@ -1405,10 +1400,6 @@ pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd, let parent_item_doc = cdata.lookup_item(parent_item_id.index); match item_family(parent_item_doc) { Trait => Some(item_def_id(parent_item_doc, cdata)), - Impl | DefaultImpl => { - reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref) - .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id) - } _ => None } } @@ -1537,11 +1528,7 @@ pub fn is_extern_item<'a, 'tcx>(cdata: Cmd, }; let applicable = match item_family(item_doc) { ImmStatic | MutStatic => true, - Fn => { - let ty::TypeScheme { generics, .. } = get_type(cdata, id, tcx); - let no_generics = generics.types.is_empty(); - no_generics - }, + Fn => get_generics(cdata, id, tcx).types.is_empty(), _ => false, }; @@ -1573,30 +1560,13 @@ pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool { fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: Cmd, - tag: usize) - -> ty::Generics<'tcx> + cdata: Cmd) + -> &'tcx ty::Generics<'tcx> { - let doc = reader::get_doc(base_doc, tag); - - let mut generics = ty::Generics::empty(); - for p in reader::tagged_docs(doc, tag_type_param_def) { - let bd = - TyDecoder::with_doc(tcx, cdata.cnum, p, - &mut |did| translate_def_id(cdata, did)) - .parse_type_param_def(); - generics.types.push(bd.space, bd); - } - - for p in reader::tagged_docs(doc, tag_region_param_def) { - let bd = - TyDecoder::with_doc(tcx, cdata.cnum, p, - &mut |did| translate_def_id(cdata, did)) - .parse_region_param_def(); - generics.regions.push(bd.space, bd); - } - - generics + let doc = reader::get_doc(base_doc, tag_item_generics); + TyDecoder::with_doc(tcx, cdata.cnum, doc, + &mut |did| translate_def_id(cdata, did)) + .parse_generics() } fn doc_predicate<'a, 'tcx>(cdata: Cmd, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d19eb639182..1e74b3c1ef4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -175,8 +175,7 @@ fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder, index: &mut CrateIndex<'a, 'tcx>, scheme: &ty::TypeScheme<'tcx>, predicates: &ty::GenericPredicates<'tcx>) { - encode_generics(rbml_w, ecx, index, - &scheme.generics, &predicates, tag_item_generics); + encode_generics(rbml_w, ecx, index, &scheme.generics, &predicates); encode_type(ecx, rbml_w, scheme.ty); } @@ -510,50 +509,26 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder, ecx: &EncodeContext<'a, 'tcx>, index: &mut CrateIndex<'a, 'tcx>, generics: &ty::Generics<'tcx>, - predicates: &ty::GenericPredicates<'tcx>, - tag: usize) + predicates: &ty::GenericPredicates<'tcx>) { - rbml_w.start_tag(tag); - - for param in generics.types.as_full_slice() { - rbml_w.start_tag(tag_type_param_def); - tyencode::enc_type_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); - rbml_w.mark_stable_position(); - rbml_w.end_tag(); - } - - // Region parameters - for param in generics.regions.as_full_slice() { - rbml_w.start_tag(tag_region_param_def); - tyencode::enc_region_param_def(rbml_w.writer, &ecx.ty_str_ctxt(), param); - rbml_w.mark_stable_position(); - rbml_w.end_tag(); - } - - encode_predicates_in_current_doc(rbml_w, ecx, index, predicates); - + rbml_w.start_tag(tag_item_generics); + tyencode::enc_generics(rbml_w.writer, &ecx.ty_str_ctxt(), generics); + rbml_w.mark_stable_position(); rbml_w.end_tag(); -} -fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder, - _ecx: &EncodeContext<'a,'tcx>, - index: &mut CrateIndex<'a, 'tcx>, - predicates: &ty::GenericPredicates<'tcx>) -{ - for predicate in &predicates.predicates { - rbml_w.wr_tagged_u32(tag_predicate, - index.add_xref(XRef::Predicate(predicate.clone()))); - } + encode_predicates(rbml_w, index, predicates, tag_item_predicates); } fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder, - ecx: &EncodeContext<'a,'tcx>, index: &mut CrateIndex<'a, 'tcx>, predicates: &ty::GenericPredicates<'tcx>, tag: usize) { rbml_w.start_tag(tag); - encode_predicates_in_current_doc(rbml_w, ecx, index, predicates); + for predicate in &predicates.predicates { + rbml_w.wr_tagged_u32(tag_predicate, + index.add_xref(XRef::Predicate(predicate.clone()))); + } rbml_w.end_tag(); } @@ -564,8 +539,7 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_def_id_and_key(ecx, rbml_w, method_ty.def_id); encode_name(rbml_w, method_ty.name); encode_generics(rbml_w, ecx, index, - &method_ty.generics, &method_ty.predicates, - tag_method_ty_generics); + &method_ty.generics, &method_ty.predicates); encode_visibility(rbml_w, method_ty.vis); encode_explicit_self(rbml_w, &method_ty.explicit_self); match method_ty.explicit_self { @@ -695,7 +669,7 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_attributes(rbml_w, &ii.attrs); encode_defaultness(rbml_w, ii.defaultness); } else { - encode_predicates(rbml_w, ecx, index, + encode_predicates(rbml_w, index, &ecx.tcx.lookup_predicates(associated_type.def_id), tag_item_generics); } @@ -1134,9 +1108,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id)); encode_associated_type_names(rbml_w, &trait_def.associated_type_names); encode_generics(rbml_w, ecx, index, - &trait_def.generics, &trait_predicates, - tag_item_generics); - encode_predicates(rbml_w, ecx, index, + &trait_def.generics, &trait_predicates); + encode_predicates(rbml_w, index, &tcx.lookup_super_predicates(def_id), tag_item_super_predicates); encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref); diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs index 23142ca80ef..6e78cbcd28e 100644 --- a/src/librustc_metadata/tls_context.rs +++ b/src/librustc_metadata/tls_context.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> { ty } - fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx> { + fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> &'tcx Substs<'tcx> { let def_id_convert = &mut |did| { decoder::translate_def_id(self.crate_metadata, did) }; diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 11c155cbd5b..3f0fa9073aa 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -20,8 +20,7 @@ use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use middle::region; -use rustc::ty::subst; -use rustc::ty::subst::VecPerParamSpace; +use rustc::ty::subst::{self, Substs, VecPerParamSpace}; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rbml; @@ -132,21 +131,31 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { fn parse_vec_per_param_space(&mut self, mut f: F) -> VecPerParamSpace where F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T, { - let mut r = VecPerParamSpace::empty(); - for &space in &subst::ParamSpace::all() { + let (mut a, mut b, mut c) = (vec![], vec![], vec![]); + for r in &mut [&mut a, &mut b, &mut c] { assert_eq!(self.next(), '['); while self.peek() != ']' { - r.push(space, f(self)); + r.push(f(self)); } assert_eq!(self.next(), ']'); } - r + VecPerParamSpace::new(a, b, c) } - pub fn parse_substs(&mut self) -> subst::Substs<'tcx> { + pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { 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 } + Substs::new(self.tcx, types, regions) + } + + pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> { + let regions = self.parse_vec_per_param_space(|this| this.parse_region_param_def()); + let types = self.parse_vec_per_param_space(|this| this.parse_type_param_def()); + self.tcx.alloc_generics(ty::Generics { + regions: regions, + types: types, + has_self: self.next() == 'S' + }) } fn parse_bound_region(&mut self) -> ty::BoundRegion { @@ -302,15 +311,17 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> { - let def = self.parse_def(); - let substs = self.tcx.mk_substs(self.parse_substs()); - ty::TraitRef {def_id: def, substs: substs} + ty::TraitRef { + def_id: self.parse_def(), + substs: self.parse_substs() + } } pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> { - let def = self.parse_def(); - let substs = self.tcx.mk_substs(self.parse_substs()); - ty::ExistentialTraitRef {def_id: def, substs: substs} + ty::ExistentialTraitRef { + def_id: self.parse_def(), + substs: self.parse_substs() + } } pub fn parse_ty(&mut self) -> Ty<'tcx> { @@ -342,7 +353,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let substs = self.parse_substs(); assert_eq!(self.next(), ']'); let def = self.tcx.lookup_adt_def(did); - return tcx.mk_enum(def, self.tcx.mk_substs(substs)); + return tcx.mk_enum(def, substs); } 'x' => { assert_eq!(self.next(), '['); @@ -406,7 +417,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'F' => { let def_id = self.parse_def(); - let substs = self.tcx.mk_substs(self.parse_substs()); + let substs = self.parse_substs(); return tcx.mk_fn_def(def_id, substs, self.parse_bare_fn_ty()); } 'G' => { @@ -452,7 +463,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let substs = self.parse_substs(); assert_eq!(self.next(), ']'); let def = self.tcx.lookup_adt_def(did); - return self.tcx.mk_struct(def, self.tcx.mk_substs(substs)); + return self.tcx.mk_struct(def, substs); } 'k' => { assert_eq!(self.next(), '['); @@ -464,7 +475,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } assert_eq!(self.next(), '.'); assert_eq!(self.next(), ']'); - return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys); + return self.tcx.mk_closure(did, substs, tys); } 'P' => { assert_eq!(self.next(), '['); @@ -477,7 +488,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let def_id = self.parse_def(); let substs = self.parse_substs(); assert_eq!(self.next(), ']'); - return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs)); + return self.tcx.mk_anon(def_id, substs); } 'e' => { return tcx.types.err; @@ -622,7 +633,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { + fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { let name = self.parse_name(':'); let def_id = self.parse_def(); let space = self.parse_param_space(); @@ -644,7 +655,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef { + fn parse_region_param_def(&mut self) -> ty::RegionParameterDef { let name = self.parse_name(':'); let def_id = self.parse_def(); let space = self.parse_param_space(); diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 8deb1eb6ac3..130d1548582 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -19,8 +19,7 @@ use std::io::prelude::*; use rustc::hir::def_id::DefId; use middle::region; -use rustc::ty::subst; -use rustc::ty::subst::VecPerParamSpace; +use rustc::ty::subst::{self, Substs, VecPerParamSpace}; use rustc::ty::ParamTy; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FnvHashMap; @@ -266,13 +265,27 @@ fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor>, } pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - substs: &subst::Substs<'tcx>) { + substs: &Substs<'tcx>) { 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)); } +pub fn enc_generics<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + generics: &ty::Generics<'tcx>) { + enc_vec_per_param_space(w, cx, &generics.regions, + |w, cx, r| enc_region_param_def(w, cx, r)); + enc_vec_per_param_space(w, cx, &generics.types, + |w, cx, ty| enc_type_param_def(w, cx, ty)); + + if generics.has_self { + write!(w, "S"); + } else { + write!(w, "N"); + } +} + pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { match r { ty::ReLateBound(id, br) => { @@ -420,8 +433,8 @@ fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBound write!(w, "."); } -pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - v: &ty::TypeParameterDef<'tcx>) { +fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + v: &ty::TypeParameterDef<'tcx>) { write!(w, "{}:{}|{}|{}|{}|", v.name, (cx.ds)(cx.tcx, v.def_id), v.space.to_uint(), v.index, (cx.ds)(cx.tcx, v.default_def_id)); @@ -429,8 +442,8 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx> enc_object_lifetime_default(w, cx, v.object_lifetime_default); } -pub fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, - v: &ty::RegionParameterDef) { +fn enc_region_param_def(w: &mut Cursor>, cx: &ctxt, + v: &ty::RegionParameterDef) { write!(w, "{}:{}|{}|{}|", v.name, (cx.ds)(cx.tcx, v.def_id), v.space.to_uint(), v.index); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 6af9ad02b91..22989048388 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -750,7 +750,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, -> TerminatorKind<'tcx> { let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) .unwrap_or_else(|e| tcx.sess.fatal(&e)); - let substs = tcx.mk_substs(Substs::new_fn(vec![data.item_ty], vec![])); + let substs = Substs::new_fn(tcx, vec![data.item_ty], vec![]); TerminatorKind::Call { func: Operand::Constant(Constant { span: data.span, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index df1fec75939..972e7f5be70 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -147,16 +147,16 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { params: Vec>) -> (Ty<'tcx>, Literal<'tcx>) { let method_name = token::intern(method_name); - let substs = Substs::new_trait(params, vec![], self_ty); + let substs = Substs::new_trait(self.tcx, params, vec![], self_ty); for trait_item in self.tcx.trait_items(trait_def_id).iter() { match *trait_item { ty::ImplOrTraitItem::MethodTraitItem(ref method) => { if method.name == method_name { let method_ty = self.tcx.lookup_item_type(method.def_id); - let method_ty = method_ty.ty.subst(self.tcx, &substs); + let method_ty = method_ty.ty.subst(self.tcx, substs); return (method_ty, Literal::Item { def_id: method.def_id, - substs: self.tcx.mk_substs(substs), + substs: substs, }); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 16cd9186ce9..6c9cf1a5625 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -299,8 +299,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let mut result = String::from("<"); result.push_str(&rustc::hir::print::ty_to_string(&ty)); - if let Some(def_id) = self.tcx - .trait_of_item(self.tcx.map.local_def_id(id)) { + if let Some(def_id) = self.tcx.trait_id_of_impl(impl_id) { result.push_str(" as "); result.push_str(&self.tcx.item_path_str(def_id)); } diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 27a8c1f1df4..d6866b27f98 100644 --- a/src/librustc_trans/_match.rs +++ b/src/librustc_trans/_match.rs @@ -895,7 +895,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>, &format!("comparison of `{}`", rhs_t), StrEqFnLangItem); let args = [lhs_data, lhs_len, rhs_data, rhs_len]; - Callee::def(bcx.ccx(), did, bcx.tcx().mk_substs(Substs::empty())) + Callee::def(bcx.ccx(), did, Substs::empty(bcx.tcx())) .call(bcx, debug_loc, ArgVals(&args), None) } diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 23c4258caf7..d48ec98a20d 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -48,7 +48,7 @@ use std; use std::rc::Rc; use llvm::{ValueRef, True, IntEQ, IntNE}; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use syntax::ast; use syntax::attr; @@ -544,7 +544,7 @@ impl<'tcx> Case<'tcx> { fn get_cases<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, adt: ty::AdtDef<'tcx>, - substs: &subst::Substs<'tcx>) + substs: &Substs<'tcx>) -> Vec> { adt.variants.iter().map(|vi| { let field_tys = vi.fields.iter().map(|field| { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 749a7495421..ee5d1d11fa0 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -218,7 +218,7 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Allocate space: let def_id = require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem); - let r = Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty())) + let r = Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx())) .call(bcx, debug_loc, ArgVals(&[size, align]), None); Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr)) @@ -670,11 +670,9 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx source_ty: Ty<'tcx>, target_ty: Ty<'tcx>) -> CustomCoerceUnsized { - let trait_substs = Substs::new_trait(vec![target_ty], vec![], source_ty); - let trait_ref = ty::Binder(ty::TraitRef { def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(), - substs: scx.tcx().mk_substs(trait_substs) + substs: Substs::new_trait(scx.tcx(), vec![target_ty], vec![], source_ty) }); match fulfill_obligation(scx, DUMMY_SP, trait_ref) { @@ -1410,7 +1408,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { common::validate_substs(instance.substs); (instance.substs, Some(instance.def), Some(inlined_id)) } - None => (ccx.tcx().mk_substs(Substs::empty()), None, None) + None => (Substs::empty(ccx.tcx()), None, None) }; let local_id = def_id.and_then(|id| ccx.tcx().map.as_local_node_id(id)); @@ -2175,7 +2173,7 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) { Ok(id) => id, Err(s) => ccx.sess().fatal(&s) }; - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(ccx.tcx()); let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx).val; let args = { let opaque_rust_main = diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index aaec2a47025..d50959b5ab3 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -22,7 +22,7 @@ use back::symbol_names; use llvm::{self, ValueRef, get_params}; use middle::cstore::LOCAL_CRATE; use rustc::hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::hir::map as hir_map; use abi::{Abi, FnType}; @@ -105,13 +105,12 @@ impl<'tcx> Callee<'tcx> { /// Function or method definition. pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Callee<'tcx> { let tcx = ccx.tcx(); - if substs.self_ty().is_some() { - // Only trait methods can have a Self parameter. - return Callee::trait_method(ccx, def_id, substs); + if let Some(trait_id) = tcx.trait_of_item(def_id) { + return Callee::trait_method(ccx, trait_id, def_id, substs); } let maybe_node_id = inline::get_local_instance(ccx, def_id) @@ -144,24 +143,21 @@ impl<'tcx> Callee<'tcx> { /// Trait method, which has to be resolved to an impl method. pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>, + trait_id: DefId, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Callee<'tcx> { let tcx = ccx.tcx(); - let method_item = tcx.impl_or_trait_item(def_id); - let trait_id = method_item.container().id(); - let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id)); - let trait_ref = tcx.normalize_associated_type(&trait_ref); + let trait_ref = ty::TraitRef::from_method(tcx, trait_id, substs); + let trait_ref = tcx.normalize_associated_type(&ty::Binder(trait_ref)); match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) { traits::VtableImpl(vtable_impl) => { let impl_did = vtable_impl.impl_def_id; let mname = tcx.item_name(def_id); // create a concatenated set of substitutions which includes // those from the impl and those from the method: - let impl_substs = vtable_impl.substs.with_method_from(&substs); - let substs = tcx.mk_substs(impl_substs); - let mth = meth::get_impl_method(tcx, impl_did, substs, mname); + let mth = meth::get_impl_method(tcx, substs, impl_did, vtable_impl.substs, mname); // Translate the function, bypassing Callee::def. // That is because default methods have the same ID as the @@ -275,7 +271,7 @@ impl<'tcx> Callee<'tcx> { /// Given a DefId and some Substs, produces the monomorphic item type. fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { let ty = tcx.lookup_item_type(def_id).ty; monomorphize::apply_param_substs(tcx, substs, &ty) @@ -427,7 +423,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( /// - `substs`: values for each of the fn/method's parameters fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Datum<'tcx, Rvalue> { let tcx = ccx.tcx(); diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 277110347d0..82c86928783 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -732,7 +732,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, create_fn_trans_item(scx.tcx(), exchange_free_fn_def_id, fn_substs, - scx.tcx().mk_substs(Substs::empty())); + Substs::empty(scx.tcx())); output.push(exchange_free_fn_trans_item); } @@ -753,8 +753,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, .drop_trait() .unwrap(); - let self_type_substs = scx.tcx().mk_substs( - Substs::empty().with_self_ty(ty)); + let self_type_substs = Substs::new_trait(scx.tcx(), vec![], vec![], ty); let trait_ref = ty::TraitRef { def_id: drop_trait_def_id, @@ -770,7 +769,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let trans_item = create_fn_trans_item(scx.tcx(), destructor_did, substs, - scx.tcx().mk_substs(Substs::empty())); + Substs::empty(scx.tcx())); output.push(trans_item); } @@ -854,26 +853,15 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, fn_substs, param_substs); - let is_trait_method = scx.tcx().trait_of_item(fn_def_id).is_some(); - - if is_trait_method { + if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) { match scx.tcx().impl_or_trait_item(fn_def_id) { ty::MethodTraitItem(ref method) => { - match method.container { - ty::TraitContainer(trait_def_id) => { - debug!(" => trait method, attempting to find impl"); - do_static_trait_method_dispatch(scx, - method, - trait_def_id, - fn_substs, - param_substs) - } - ty::ImplContainer(_) => { - // This is already a concrete implementation - debug!(" => impl method"); - Some((fn_def_id, fn_substs)) - } - } + debug!(" => trait method, attempting to find impl"); + do_static_trait_method_dispatch(scx, + method, + trait_def_id, + fn_substs, + param_substs) } _ => bug!() } @@ -903,13 +891,12 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, callee_substs, param_substs); + let rcvr_substs = monomorphize::apply_param_substs(tcx, param_substs, &callee_substs); - - let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id)); - let trait_ref = tcx.normalize_associated_type(&trait_ref); - let vtbl = fulfill_obligation(scx, DUMMY_SP, trait_ref); + let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); + let vtbl = fulfill_obligation(scx, DUMMY_SP, ty::Binder(trait_ref)); // Now that we know which impl is being used, we can dispatch to // the actual function: @@ -919,10 +906,10 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, substs: impl_substs, nested: _ }) => { - let callee_substs = impl_substs.with_method_from(&rcvr_substs); let impl_method = meth::get_impl_method(tcx, + rcvr_substs, impl_did, - tcx.mk_substs(callee_substs), + impl_substs, trait_method.name); Some((impl_method.method.def_id, &impl_method.substs)) } @@ -1076,7 +1063,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, Some(create_fn_trans_item(scx.tcx(), impl_method.method.def_id, impl_method.substs, - scx.tcx().mk_substs(Substs::empty()))) + Substs::empty(scx.tcx()))) } else { None } @@ -1248,9 +1235,13 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The substitutions we have are on the impl, so we grab // the method type from the impl to substitute into. + let impl_substs = Substs::for_item(tcx, impl_def_id, + |_, _| ty::ReErased, + |_, _| tcx.types.err); let mth = meth::get_impl_method(tcx, - impl_def_id, callee_substs, + impl_def_id, + impl_substs, default_impl.name); assert!(mth.is_provided); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 79cf77cd9d3..b1aaea7d984 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -523,7 +523,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { let tcx = ccx.tcx(); match tcx.lang_items.eh_personality() { Some(def_id) if !base::wants_msvc_seh(ccx.sess()) => { - Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())).reify(ccx).val + Callee::def(ccx, def_id, Substs::empty(tcx)).reify(ccx).val } _ => { if let Some(llpersonality) = ccx.eh_personality().get() { @@ -550,7 +550,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> { let tcx = ccx.tcx(); assert!(ccx.sess().target.target.options.custom_unwind_resume); if let Some(def_id) = tcx.lang_items.eh_unwind_resume() { - return Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())); + return Callee::def(ccx, def_id, Substs::empty(tcx)); } let ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 3ecba3691d2..0e989889677 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -208,7 +208,7 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let arg_ids = args.iter().map(|arg| arg.pat.id); let fn_args = arg_ids.zip(arg_vals.iter().cloned()).collect(); - let substs = ccx.tcx().mk_substs(substs.clone().erase_regions()); + let substs = ccx.tcx().erase_regions(&substs); let substs = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &substs); @@ -222,7 +222,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs: &'tcx Substs<'tcx>) -> &'tcx hir::Expr { let substs = ccx.tcx().node_id_item_substs(ref_expr.id).substs; - let substs = ccx.tcx().mk_substs(substs.clone().erase_regions()); + let substs = ccx.tcx().erase_regions(&substs); let substs = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &substs); @@ -271,7 +271,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs: &'tcx Substs<'tcx>) -> Result { let expr = get_const_expr(ccx, def_id, ref_expr, param_substs); - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(ccx.tcx()); match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) { Err(Runtime(err)) => { report_const_eval_err(ccx.tcx(), &err, expr.span, "expression").emit(); @@ -1160,7 +1160,7 @@ pub fn trans_static(ccx: &CrateContext, let v = if use_mir { ::mir::trans_static_initializer(ccx, def_id) } else { - let empty_substs = ccx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(ccx.tcx()); const_expr(ccx, expr, empty_substs, None, TrueConst::Yes) .map(|(v, _)| v) }.map_err(|e| e.into_inner())?; diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 65eea1bbb63..c31dbf8943e 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -30,7 +30,7 @@ use monomorphize::Instance; use partitioning::CodegenUnit; use trans_item::TransItem; use type_::{Type, TypeNames}; -use rustc::ty::subst::{Substs, VecPerParamSpace}; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use session::config::NoDebugInfo; use session::Session; @@ -571,16 +571,9 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { /// 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::ReErased))) + Substs::for_item(self.tcx(), item_def_id, |_, _| ty::ReErased, |_, _| { + bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id) + }) } pub fn symbol_hasher(&self) -> &RefCell { @@ -999,11 +992,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { self.shared().empty_substs_for_def_id(item_def_id) } - - pub fn empty_substs_for_scheme(&self, scheme: &ty::TypeScheme<'tcx>) - -> &'tcx Substs<'tcx> { - self.shared().empty_substs_for_scheme(scheme) - } } pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>); diff --git a/src/librustc_trans/controlflow.rs b/src/librustc_trans/controlflow.rs index 8845f124218..8b3a8a2bfcc 100644 --- a/src/librustc_trans/controlflow.rs +++ b/src/librustc_trans/controlflow.rs @@ -401,7 +401,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let expr_file_line = consts::addr_of(ccx, expr_file_line_const, align, "panic_loc"); let args = vec!(expr_file_line); let did = langcall(bcx.tcx(), Some(call_info.span), "", PanicFnLangItem); - Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty())) + Callee::def(ccx, did, Substs::empty(ccx.tcx())) .call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx } @@ -429,6 +429,6 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let file_line = consts::addr_of(ccx, file_line_const, align, "panic_bounds_check_loc"); let args = vec!(file_line, index, len); let did = langcall(bcx.tcx(), Some(call_info.span), "", PanicBoundsCheckFnLangItem); - Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty())) + Callee::def(ccx, did, Substs::empty(ccx.tcx())) .call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 6a99f12b278..e80dd28c5e5 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -27,7 +27,7 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType}; use rustc::hir::def_id::DefId; use rustc::hir::pat_util; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::hir::map as hir_map; use rustc::hir::{self, PatKind}; use {type_of, adt, machine, monomorphize}; @@ -315,7 +315,7 @@ impl<'tcx> TypeMap<'tcx> { fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>, cx: &CrateContext<'a, 'tcx>, def_id: DefId, - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, output: &mut String) { // First, find out the 'real' def_id of the type. Items inlined from // other crates have to be mapped back to their source. @@ -346,7 +346,7 @@ impl<'tcx> TypeMap<'tcx> { // Add the def-index as the second part output.push_str(&format!("{:x}", def_id.index.as_usize())); - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = substs.types.as_full_slice(); if !tps.is_empty() { output.push('<'); @@ -1086,7 +1086,7 @@ impl<'tcx> MemberDescriptionFactory<'tcx> { // Creates MemberDescriptions for the fields of a struct struct StructMemberDescriptionFactory<'tcx> { variant: ty::VariantDef<'tcx>, - substs: &'tcx subst::Substs<'tcx>, + substs: &'tcx Substs<'tcx>, is_simd: bool, span: Span, } diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 1aae3b3127f..963cc09e1ab 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -266,7 +266,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Get_template_parameters() will append a `<...>` clause to the function // name if necessary. - let generics = cx.tcx().lookup_item_type(fn_def_id).generics; + let generics = cx.tcx().lookup_generics(fn_def_id); let template_parameters = get_template_parameters(cx, &generics, instance.substs, diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 4bca091ef95..20dbc8ac78e 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -12,7 +12,7 @@ use common::CrateContext; use rustc::hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; use rustc::hir; @@ -173,7 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // would be possible but with inlining and LTO we have to use the least // common denominator - otherwise we would run into conflicts. fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, output: &mut String) { if substs.types.is_empty() { return; diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs index 6c894ddad1a..beb589c80bf 100644 --- a/src/librustc_trans/expr.rs +++ b/src/librustc_trans/expr.rs @@ -175,7 +175,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, hir::ExprPath(..) => { match bcx.tcx().expect_def(expr.id) { Def::Const(did) | Def::AssociatedConst(did) => { - let empty_substs = bcx.tcx().mk_substs(Substs::empty()); + let empty_substs = Substs::empty(bcx.tcx()); let const_expr = consts::get_const_expr(bcx.ccx(), did, expr, empty_substs); // Temporarily get cleanup scopes out of the way, diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 93e5f4ba1e2..080844782f2 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -50,7 +50,7 @@ pub fn trans_exchange_free_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem); let args = [PointerCast(bcx, v, Type::i8p(bcx.ccx())), size, align]; - Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty())) + Callee::def(bcx.ccx(), def_id, Substs::empty(bcx.tcx())) .call(bcx, debug_loc, ArgVals(&args), None).bcx } @@ -356,7 +356,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let trait_ref = ty::Binder(ty::TraitRef { def_id: tcx.lang_items.drop_trait().unwrap(), - substs: tcx.mk_substs(Substs::empty().with_self_ty(t)) + substs: Substs::new_trait(tcx, vec![], vec![], t) }); let vtbl = match fulfill_obligation(bcx.ccx().shared(), DUMMY_SP, trait_ref) { traits::VtableImpl(data) => data, diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 7be173d17b4..133a98a2470 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -15,8 +15,7 @@ use intrinsics::{self, Intrinsic}; use libc; use llvm; use llvm::{ValueRef, TypeKind}; -use rustc::ty::subst; -use rustc::ty::subst::FnSpace; +use rustc::ty::subst::{FnSpace, Substs}; use abi::{Abi, FnType}; use adt; use base::*; @@ -1284,7 +1283,7 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { fn generic_simd_intrinsic<'blk, 'tcx, 'a> (bcx: Block<'blk, 'tcx>, name: &str, - substs: &'tcx subst::Substs<'tcx>, + substs: &'tcx Substs<'tcx>, callee_ty: Ty<'tcx>, args: Option<&[P]>, llargs: &[ValueRef], diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 169242fbf72..b051028ebda 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -15,8 +15,7 @@ use arena::TypedArena; use back::symbol_names; use llvm::{ValueRef, get_params}; use rustc::hir::def_id::DefId; -use rustc::ty::subst::{FnSpace, Subst, Substs}; -use rustc::ty::subst; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits::{self, Reveal}; use abi::FnType; use base::*; @@ -221,20 +220,20 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_id: DefId, - substs: &'tcx subst::Substs<'tcx>) + substs: &'tcx Substs<'tcx>) -> Vec>> { debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs); - let trt_id = match tcx.impl_trait_ref(impl_id) { + let trait_id = match tcx.impl_trait_ref(impl_id) { Some(t_id) => t_id.def_id, None => bug!("make_impl_vtable: don't know how to \ make a vtable for a type impl!") }; - tcx.populate_implementations_for_trait_if_necessary(trt_id); + tcx.populate_implementations_for_trait_if_necessary(trait_id); - let trait_item_def_ids = tcx.trait_item_def_ids(trt_id); + let trait_item_def_ids = tcx.trait_item_def_ids(trait_id); trait_item_def_ids .iter() @@ -260,7 +259,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let name = trait_method_type.name; // Some methods cannot be called on an object; skip those. - if !tcx.is_vtable_safe_method(trt_id, &trait_method_type) { + if !tcx.is_vtable_safe_method(trait_id, &trait_method_type) { debug!("get_vtable_methods: not vtable safe"); return None; } @@ -270,15 +269,13 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // 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::ReErased; num_dummy_regions]; - let method_substs = substs.clone() - .with_method(vec![], dummy_regions); - let method_substs = tcx.mk_substs(method_substs); + let method_substs = Substs::for_item(tcx, trait_method_def_id, + |_, _| ty::ReErased, + |_, _| tcx.types.err); // 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, method_substs, name); + let mth = get_impl_method(tcx, method_substs, impl_id, substs, name); debug!("get_vtable_methods: mth={:?}", mth); @@ -309,8 +306,9 @@ pub struct ImplMethod<'tcx> { /// Locates the applicable definition of a method, given its name. pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - impl_def_id: DefId, substs: &'tcx Substs<'tcx>, + impl_def_id: DefId, + impl_substs: &'tcx Substs<'tcx>, name: Name) -> ImplMethod<'tcx> { @@ -322,6 +320,7 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() { Some(node_item) => { let substs = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| { + let substs = substs.rebase_onto(tcx, trait_def_id, impl_substs); let substs = traits::translate_substs(&infcx, impl_def_id, substs, node_item.node); tcx.lift(&substs).unwrap_or_else(|| { diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 31fee560fe3..4da973bb7f9 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -232,12 +232,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { args: IndexVec>) -> Result, ConstEvalFailure> { // Try to resolve associated constants. - if instance.substs.self_ty().is_some() { - // Only trait items can have a Self parameter. - let trait_item = ccx.tcx().impl_or_trait_item(instance.def); - let trait_id = trait_item.container().id(); - let substs = instance.substs; - let trait_ref = ty::Binder(substs.to_trait_ref(ccx.tcx(), trait_id)); + if let Some(trait_id) = ccx.tcx().trait_of_item(instance.def) { + let trait_ref = ty::TraitRef::new(trait_id, instance.substs); + let trait_ref = ty::Binder(trait_ref); let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref); if let traits::VtableImpl(vtable_impl) = vtable { let name = ccx.tcx().item_name(instance.def); diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 663c5167d14..26278e886c2 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -12,7 +12,6 @@ use llvm::ValueRef; use llvm; use rustc::hir::def_id::DefId; use rustc::infer::TransNormalize; -use rustc::ty::subst; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Ty, TypeFoldable, TyCtxt}; use attributes; @@ -33,7 +32,7 @@ use trans_item::TransItem; pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_id: DefId, - psubsts: &'tcx subst::Substs<'tcx>) + psubsts: &'tcx Substs<'tcx>) -> (ValueRef, Ty<'tcx>) { debug!("monomorphic_fn(fn_id={:?}, real_substs={:?})", fn_id, psubsts); assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types()); @@ -174,7 +173,7 @@ pub struct Instance<'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[], |_| None) + ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[]) } } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index ade6e8abeb3..f24ab0f6557 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -125,6 +125,7 @@ use rustc::hir::map::DefPathData; use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER; use rustc::ty::TyCtxt; use rustc::ty::item_path::characteristic_def_id_of_type; +use rustc::ty::subst; use std::cmp::Ordering; use std::hash::{Hash, Hasher, SipHasher}; use std::sync::Arc; @@ -486,7 +487,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // its self-type. If the self-type does not provide a characteristic // DefId, we use the location of the impl after all. - if let Some(self_ty) = instance.substs.self_ty() { + if tcx.trait_of_item(instance.def).is_some() { + let self_ty = *instance.substs.types.get(subst::SelfSpace, 0); // This is an implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(instance.def)); } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 2dd07cf4405..ebd4a80deb9 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -28,7 +28,7 @@ use rustc::hir; use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::subst; +use rustc::ty::subst::{Substs, VecPerParamSpace}; use rustc_const_eval::fatal_const_eval_err; use std::hash::{Hash, Hasher}; use syntax::ast::{self, NodeId}; @@ -352,8 +352,7 @@ impl<'a, 'tcx> TransItem<'tcx> { }, TransItem::Static(node_id) => { let def_id = hir_map.local_def_id(node_id); - let instance = Instance::new(def_id, - tcx.mk_substs(subst::Substs::empty())); + let instance = Instance::new(def_id, Substs::empty(tcx)); to_string_internal(tcx, "static ", instance) }, }; @@ -561,7 +560,7 @@ fn push_item_name(tcx: TyCtxt, } fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - types: &'tcx subst::VecPerParamSpace>, + types: &'tcx VecPerParamSpace>, projections: &[ty::PolyExistentialProjection<'tcx>], output: &mut String) { if types.is_empty() && projections.is_empty() { diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index e6794149fcb..7e592d1b74d 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -11,7 +11,6 @@ #![allow(non_camel_case_types)] use rustc::hir::def_id::DefId; -use rustc::ty::subst; use abi::FnType; use adt; use common::*; @@ -257,7 +256,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // avoids creating more than one copy of the enum when one // of the enum's variants refers to the enum itself. let repr = adt::represent_type(cx, t); - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = substs.types.as_full_slice(); let name = llvm_type_name(cx, def.did, tps); adt::incomplete_type_of(cx, &repr, &name[..]) } @@ -336,7 +335,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // in *after* placing it into the type cache. This prevents // infinite recursion with recursive struct types. let repr = adt::represent_type(cx, t); - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = substs.types.as_full_slice(); let name = llvm_type_name(cx, def.did, tps); adt::incomplete_type_of(cx, &repr, &name[..]) } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 11ca012fded..5655c7c8e72 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -81,6 +81,10 @@ pub trait AstConv<'gcx, 'tcx> { /// A cache used for the result of `ast_ty_to_ty_cache` fn ast_ty_to_ty_cache(&self) -> &RefCell>>; + /// Returns the generic type and lifetime parameters for an item. + fn get_generics(&self, span: Span, id: DefId) + -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>; + /// Identify the type scheme for an item with a type, like a type /// alias, fn, or struct. This allows you to figure out the set of /// type parameters defined on the item. @@ -348,7 +352,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { rscope: &RegionScope, span: Span, param_mode: PathParamMode, - decl_generics: &ty::Generics<'tcx>, + def_id: DefId, item_segment: &hir::PathSegment) -> &'tcx Substs<'tcx> { @@ -362,11 +366,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .span_label(span, &format!("only traits may use parentheses")) .emit(); - return tcx.mk_substs(Substs::from_generics(decl_generics, |_, _| { + return Substs::for_item(tcx, def_id, |_, _| { ty::ReStatic }, |_, _| { tcx.types.err - })); + }); } } @@ -374,7 +378,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.create_substs_for_ast_path(rscope, span, param_mode, - decl_generics, + def_id, &item_segment.parameters, None); @@ -392,16 +396,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { rscope: &RegionScope, span: Span, param_mode: PathParamMode, - decl_generics: &ty::Generics<'tcx>, + def_id: DefId, parameters: &hir::PathParameters, self_ty: Option>) -> (&'tcx Substs<'tcx>, Vec>) { let tcx = self.tcx(); - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \ + debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ parameters={:?})", - decl_generics, self_ty, parameters); + def_id, self_ty, parameters); let (lifetimes, num_types_provided) = match *parameters { hir::AngleBracketedParameters(ref data) => { @@ -417,6 +421,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). + let decl_generics = match self.get_generics(span, def_id) { + Ok(generics) => generics, + Err(ErrorReported) => { + // No convenient way to recover from a cycle here. Just bail. Sorry! + self.tcx().sess.abort_if_errors(); + bug!("ErrorReported returned, but no errors reports?") + } + }; let expected_num_region_params = decl_generics.regions.len(TypeSpace); let supplied_num_region_params = lifetimes.len(); let regions = if expected_num_region_params == supplied_num_region_params { @@ -438,7 +450,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; // If a self-type was declared, one should be provided. - assert_eq!(decl_generics.types.get_self().is_some(), self_ty.is_some()); + assert_eq!(decl_generics.has_self, self_ty.is_some()); // Check the number of type parameters supplied by the user. if let Some(num_provided) = num_types_provided { @@ -460,7 +472,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let mut output_assoc_binding = None; - let substs = Substs::from_generics(decl_generics, |def, _| { + let substs = Substs::for_item(tcx, def_id, |def, _| { assert_eq!(def.space, TypeSpace); regions[def.index as usize] }, |def, substs| { @@ -532,7 +544,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { vec![output_assoc_binding.unwrap_or_else(|| { // This is an error condition, but we should // get the associated type binding anyway. - self.convert_parenthesized_parameters(rscope, &substs, data).1 + self.convert_parenthesized_parameters(rscope, substs, data).1 })] } }; @@ -540,7 +552,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", decl_generics, self_ty, substs); - (tcx.mk_substs(substs), assoc_bindings) + (substs, assoc_bindings) } /// Returns the appropriate lifetime to use for any output lifetimes @@ -803,7 +815,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.create_substs_for_ast_path(rscope, span, param_mode, - &trait_def.generics, + trait_def_id, &trait_segment.parameters, Some(self_ty)) } @@ -910,10 +922,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { -> Ty<'tcx> { let tcx = self.tcx(); - let (generics, decl_ty) = match self.get_item_type_scheme(span, did) { - Ok(ty::TypeScheme { generics, ty: decl_ty }) => { - (generics, decl_ty) - } + let decl_ty = match self.get_item_type_scheme(span, did) { + Ok(type_scheme) => type_scheme.ty, Err(ErrorReported) => { return tcx.types.err; } @@ -922,7 +932,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let substs = self.ast_path_substs_for_ty(rscope, span, param_mode, - &generics, + did, item_segment); // FIXME(#12938): This is a hack until we have full support for DST. @@ -1682,7 +1692,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Create the anonymized type. let def_id = tcx.map.local_def_id(ast_ty.id); if let Some(anon_scope) = rscope.anon_type_scope() { - let substs = anon_scope.fresh_substs(tcx); + let substs = anon_scope.fresh_substs(self, ast_ty.span); let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs); // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`. diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 04f22b19511..af24a7b5117 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -547,10 +547,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Type check the path. - let scheme = tcx.lookup_item_type(def.def_id()); - let predicates = tcx.lookup_predicates(def.def_id()); - let pat_ty = self.instantiate_value_path(segments, scheme, &predicates, - opt_ty, def, pat.span, pat.id); + let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); self.demand_suptype(pat.span, expected, pat_ty); } @@ -607,18 +604,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Type check the path. - let scheme = tcx.lookup_item_type(def.def_id()); - let scheme = if scheme.ty.is_fn() { + let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); + + let pat_ty = if pat_ty.is_fn() { // Replace constructor type with constructed type for tuple struct patterns. - let fn_ret = tcx.no_late_bound_regions(&scheme.ty.fn_ret()).unwrap(); - ty::TypeScheme { ty: fn_ret, generics: scheme.generics } + tcx.no_late_bound_regions(&pat_ty.fn_ret()).unwrap() } else { // Leave the type as is for unit structs (backward compatibility). - scheme + pat_ty }; - let predicates = tcx.lookup_predicates(def.def_id()); - let pat_ty = self.instantiate_value_path(segments, scheme, &predicates, - opt_ty, def, pat.span, pat.id); + self.write_ty(pat.id, pat_ty); self.demand_eqtype(pat.span, expected, pat_ty); // Type check subpatterns. diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 265422468fe..9a3cbabe553 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { Some(f) => f, None => return None }, - substs: tcx.mk_substs(Substs::new_trait(vec![], vec![], self.cur_ty)) + substs: Substs::new_trait(tcx, vec![], vec![], self.cur_ty) }; let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index d501a8a184c..3cb528eba63 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -194,10 +194,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Create mapping from trait to skolemized. let trait_to_skol_substs = - trait_to_impl_substs - .subst(tcx, impl_to_skol_substs).clone() - .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.rebase_onto(tcx, impl_m.container_id(), + trait_to_impl_substs.subst(tcx, impl_to_skol_substs)); debug!("compare_impl_method: trait_to_skol_substs={:?}", trait_to_skol_substs); @@ -208,7 +206,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_m, &trait_m.generics, &impl_m.generics, - &trait_to_skol_substs, + trait_to_skol_substs, impl_to_skol_substs) { return; } @@ -226,7 +224,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut fulfillment_cx = traits::FulfillmentContext::new(); // Normalize the associated types in the trait_bounds. - let trait_bounds = trait_m.predicates.instantiate(tcx, &trait_to_skol_substs); + let trait_bounds = trait_m.predicates.instantiate(tcx, trait_to_skol_substs); // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter @@ -323,7 +321,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, infcx.parameter_environment.free_id_outlive, &trait_m.fty.sig); let trait_sig = - trait_sig.subst(tcx, &trait_to_skol_substs); + trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = assoc::normalize_associated_types_in(&infcx, &mut fulfillment_cx, @@ -454,16 +452,14 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Create mapping from trait to skolemized. let trait_to_skol_substs = - trait_to_impl_substs - .subst(tcx, impl_to_skol_substs).clone() - .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.rebase_onto(tcx, impl_c.container.id(), + trait_to_impl_substs.subst(tcx, impl_to_skol_substs)); debug!("compare_const_impl: trait_to_skol_substs={:?}", trait_to_skol_substs); // Compute skolemized form of impl and trait const tys. let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs); - let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs); + let trait_ty = trait_c.ty.subst(tcx, trait_to_skol_substs); let mut origin = TypeOrigin::Misc(impl_c_span); let err = infcx.commit_if_ok(|_| { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 1e2446788ad..7d79fc4fbf8 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -15,7 +15,7 @@ use hir::def_id::DefId; use middle::free_region::FreeRegionMap; use rustc::infer; use middle::region; -use rustc::ty::subst::{self, Subst}; +use rustc::ty::subst::{self, Subst, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::traits::{self, Reveal}; use util::nodemap::FnvHashSet; @@ -41,16 +41,14 @@ use syntax_pos::{self, Span}; /// cannot do `struct S; impl Drop for S { ... }`). /// pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> { - let ty::TypeScheme { generics: ref dtor_generics, - ty: dtor_self_type } = ccx.tcx.lookup_item_type(drop_impl_did); + let dtor_self_type = ccx.tcx.lookup_item_type(drop_impl_did).ty; let dtor_predicates = ccx.tcx.lookup_predicates(drop_impl_did); match dtor_self_type.sty { ty::TyEnum(adt_def, self_to_impl_substs) | ty::TyStruct(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond(ccx, drop_impl_did, - dtor_generics, - &dtor_self_type, + dtor_self_type, adt_def.did)?; ensure_drop_predicates_are_implied_by_item_defn(ccx, @@ -73,8 +71,7 @@ pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, drop_impl_did: DefId, - drop_impl_generics: &ty::Generics<'tcx>, - drop_impl_ty: &ty::Ty<'tcx>, + drop_impl_ty: Ty<'tcx>, self_type_did: DefId) -> Result<(), ()> { let tcx = ccx.tcx; @@ -93,8 +90,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( let drop_impl_span = tcx.map.def_id_span(drop_impl_did, syntax_pos::DUMMY_SP); let fresh_impl_substs = - infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics); - let fresh_impl_self_ty = drop_impl_ty.subst(tcx, &fresh_impl_substs); + infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did); + let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs); if let Err(_) = infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span), named_type, fresh_impl_self_ty) { @@ -131,7 +128,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( drop_impl_did: DefId, dtor_predicates: &ty::GenericPredicates<'tcx>, self_type_did: DefId, - self_to_impl_substs: &subst::Substs<'tcx>) -> Result<(), ()> { + self_to_impl_substs: &Substs<'tcx>) -> Result<(), ()> { // Here is an example, analogous to that from // `compare_impl_method`. diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4334f043772..bfedb4fa6e1 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -36,11 +36,11 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let def_id = tcx.map.local_def_id(it.id); let i_ty = tcx.lookup_item_type(def_id); - let mut substs = Substs::empty(); - substs.types = i_ty.generics.types.map(|def| tcx.mk_param_from_def(def)); + let substs = Substs::for_item(tcx, def_id, + |_, _| ty::ReErased, + |def, _| tcx.mk_param_from_def(def)); - let fty = tcx.mk_fn_def(def_id, tcx.mk_substs(substs), - tcx.mk_bare_fn(ty::BareFnTy { + let fty = tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Unsafe, abi: abi, sig: ty::Binder(FnSig { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 250bf9265d1..c071fce9896 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -12,7 +12,7 @@ use super::probe; use check::{FnCtxt, callee}; use hir::def_id::DefId; -use rustc::ty::subst::{self}; +use rustc::ty::subst::{self, Substs}; use rustc::traits; use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -42,10 +42,6 @@ struct InstantiatedMethodSig<'tcx> { /// argument is the receiver. method_sig: ty::FnSig<'tcx>, - /// Substitutions for all types/early-bound-regions declared on - /// the method. - all_substs: subst::Substs<'tcx>, - /// Generic bounds on the method's parameters which must be added /// as pending obligations. method_predicates: ty::InstantiatedPredicates<'tcx>, @@ -105,9 +101,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Create the final signature for the method, replacing late-bound regions. let InstantiatedMethodSig { - method_sig, all_substs, method_predicates + method_sig, method_predicates } = self.instantiate_method_sig(&pick, all_substs); - let all_substs = self.tcx.mk_substs(all_substs); let method_self_ty = method_sig.inputs[0]; // Unify the (adjusted) self type with what the method expects. @@ -198,7 +193,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn fresh_receiver_substs(&mut self, self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) - -> &'tcx subst::Substs<'tcx> + -> &'tcx Substs<'tcx> { match pick.kind { probe::InherentImplPick => { @@ -256,16 +251,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { probe::TraitPick => { let trait_def_id = pick.item.container().id(); - let trait_def = self.tcx.lookup_trait_def(trait_def_id); // Make a trait reference `$0 : Trait<$1...$n>` // consisting entirely of type variables. Later on in // the process we will unify the transformed-self-type // of the method with the actual type in order to // unify some of these variables. - self.fresh_substs_for_trait(self.span, - &trait_def.generics, - self.next_ty_var()) + self.fresh_substs_for_item(self.span, trait_def_id) } probe::WhereClausePick(ref poly_trait_ref) => { @@ -308,8 +300,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, mut supplied_method_types: Vec>, - substs: &subst::Substs<'tcx>) - -> subst::Substs<'tcx> + substs: &Substs<'tcx>) + -> &'tcx Substs<'tcx> { // Determine the values for the generic parameters of the method. // If they were not explicitly supplied, just construct fresh @@ -335,7 +327,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - subst::Substs::from_generics(&method.generics, |def, _| { + Substs::for_item(self.tcx, method.def_id, |def, _| { if def.space != subst::FnSpace { substs.region_for_def(def) } else { @@ -376,7 +368,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_sig(&mut self, pick: &probe::Pick<'tcx>, - all_substs: subst::Substs<'tcx>) + all_substs: &'tcx Substs<'tcx>) -> InstantiatedMethodSig<'tcx> { debug!("instantiate_method_sig(pick={:?}, all_substs={:?})", @@ -387,7 +379,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // type/early-bound-regions substitutions performed. There can // be no late-bound regions appearing here. let method_predicates = pick.item.as_opt_method().unwrap() - .predicates.instantiate(self.tcx, &all_substs); + .predicates.instantiate(self.tcx, all_substs); let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates); @@ -405,20 +397,19 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("late-bound lifetimes from method instantiated, method_sig={:?}", method_sig); - let method_sig = self.instantiate_type_scheme(self.span, &all_substs, &method_sig); + let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig); debug!("type scheme substituted, method_sig={:?}", method_sig); InstantiatedMethodSig { method_sig: method_sig, - all_substs: all_substs, method_predicates: method_predicates, } } fn add_obligations(&mut self, fty: Ty<'tcx>, - all_substs: &subst::Substs<'tcx>, + all_substs: &Substs<'tcx>, method_predicates: &ty::InstantiatedPredicates<'tcx>) { debug!("add_obligations: fty={:?} all_substs={:?} method_predicates={:?}", fty, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index ff34f37bde0..e5107af6ca0 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -13,7 +13,7 @@ use check::FnCtxt; use hir::def::Def; use hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty::subst::{self, Substs}; use rustc::traits; use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` - let substs = subst::Substs::from_generics(&trait_def.generics, |def, _| { + let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { self.region_var_for_def(span, def) }, |def, substs| { if def.space == subst::SelfSpace { @@ -201,7 +201,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }); - let trait_ref = ty::TraitRef::new(trait_def_id, self.tcx.mk_substs(substs)); + let trait_ref = ty::TraitRef::new(trait_def_id, substs); // Construct an obligation let poly_trait_ref = trait_ref.to_poly_trait_ref(); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index f6ac3235cf3..448ea243655 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,8 +16,7 @@ use super::suggest; use check::{FnCtxt}; use hir::def_id::DefId; use hir::def::Def; -use rustc::ty::subst; -use rustc::ty::subst::Subst; +use rustc::ty::subst::{self, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::infer::{InferOk, TypeOrigin}; @@ -80,9 +79,9 @@ struct Candidate<'tcx> { #[derive(Debug)] enum CandidateKind<'tcx> { - InherentImplCandidate(subst::Substs<'tcx>, + InherentImplCandidate(&'tcx Substs<'tcx>, /* Normalize obligations */ Vec>), - ExtensionImplCandidate(/* Impl */ DefId, subst::Substs<'tcx>, + ExtensionImplCandidate(/* Impl */ DefId, &'tcx Substs<'tcx>, /* Normalize obligations */ Vec>), ObjectCandidate, TraitCandidate, @@ -421,10 +420,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); - let impl_ty = impl_ty.subst(self.tcx, &impl_substs); + let impl_ty = impl_ty.subst(self.tcx, impl_substs); // Determine the receiver type that the method itself expects. - let xform_self_ty = self.xform_self_ty(&item, impl_ty, &impl_substs); + let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs); // We can't use normalize_associated_types_in as it will pollute the // fcx's fulfillment context after this probe is over. @@ -519,14 +518,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_ref, trait_ref.substs, m); - 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()); - 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()); + assert_eq!(m.generics.types.len(subst::TypeSpace), + trait_ref.substs.types.len(subst::TypeSpace)); + assert_eq!(m.generics.regions.len(subst::TypeSpace), + trait_ref.substs.regions.len(subst::TypeSpace)); + assert_eq!(m.generics.types.len(subst::SelfSpace), + trait_ref.substs.types.len(subst::SelfSpace)); + assert_eq!(m.generics.regions.len(subst::SelfSpace), + trait_ref.substs.regions.len(subst::SelfSpace)); } // Because this trait derives from a where-clause, it @@ -665,7 +664,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id) .unwrap() // we know this is a trait impl - .subst(self.tcx, &impl_substs); + .subst(self.tcx, impl_substs); debug!("impl_trait_ref={:?}", impl_trait_ref); @@ -753,14 +752,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // for the purposes of our method lookup, we only take // receiver type into account, so we can just substitute // fresh types here to use during substitution and subtyping. - let trait_def = self.tcx.lookup_trait_def(trait_def_id); - let substs = self.fresh_substs_for_trait(self.span, - &trait_def.generics, - step.self_ty); + let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { + self.region_var_for_def(self.span, def) + }, |def, substs| { + if def.space == subst::SelfSpace { + assert_eq!(def.index, 0); + step.self_ty + } else { + assert_eq!(def.space, subst::TypeSpace); + self.type_var_for_def(self.span, def, substs) + } + }); let xform_self_ty = self.xform_self_ty(&item, step.self_ty, - &substs); + substs); self.inherent_candidates.push(Candidate { xform_self_ty: xform_self_ty, item: item.clone(), @@ -1192,7 +1198,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn xform_self_ty(&self, item: &ty::ImplOrTraitItem<'tcx>, impl_ty: Ty<'tcx>, - substs: &subst::Substs<'tcx>) + substs: &Substs<'tcx>) -> Ty<'tcx> { match item.as_opt_method() { @@ -1205,7 +1211,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn xform_method_self_ty(&self, method: &Rc>, impl_ty: Ty<'tcx>, - substs: &subst::Substs<'tcx>) + substs: &Substs<'tcx>) -> Ty<'tcx> { debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", @@ -1236,7 +1242,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { method.generics.regions.is_empty_in(subst::FnSpace) { xform_self_ty.subst(self.tcx, substs) } else { - let substs = subst::Substs::from_generics(&method.generics, |def, _| { + let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { if def.space != subst::FnSpace { substs.region_for_def(def) } else { @@ -1251,14 +1257,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.type_var_for_def(self.span, def, cur_substs) } }); - xform_self_ty.subst(self.tcx, &substs) + xform_self_ty.subst(self.tcx, substs) } } /// Get the type of an impl and generate substitutions with placeholders. fn impl_ty_and_substs(&self, impl_def_id: DefId) - -> (Ty<'tcx>, subst::Substs<'tcx>) + -> (Ty<'tcx>, &'tcx Substs<'tcx>) { let impl_pty = self.tcx.lookup_item_type(impl_def_id); @@ -1270,8 +1276,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { impl_pty.generics.regions.map( |_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased - let substs = subst::Substs::new(type_vars, region_placeholders); - (impl_pty.ty, substs) + (impl_pty.ty, Substs::new(self.tcx, type_vars, region_placeholders)) } /// Replace late-bound-regions bound by `value` with `'static` using diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index dc6fa334b74..573dae46456 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -54,10 +54,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.autoderef(span, ty).any(|(ty, _)| self.probe(|_| { let fn_once_substs = - Substs::new_trait(vec![self.next_ty_var()], vec![], ty); - let trait_ref = - ty::TraitRef::new(fn_once, - tcx.mk_substs(fn_once_substs)); + Substs::new_trait(tcx, vec![self.next_ty_var()], vec![], ty); + let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs); let poly_trait_ref = trait_ref.to_poly_trait_ref(); let obligation = Obligation::misc(span, self.body_id, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c41bb1930d4..700fb2ecf42 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,7 +90,6 @@ use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; use rustc::ty::subst::{self, Subst, Substs}; use rustc::traits::{self, Reveal}; -use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility}; @@ -745,26 +744,20 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { let impl_def_id = ccx.tcx.map.local_def_id(it.id); match ccx.tcx.impl_trait_ref(impl_def_id) { Some(impl_trait_ref) => { - let trait_def_id = impl_trait_ref.def_id; - check_impl_items_against_trait(ccx, it.span, impl_def_id, &impl_trait_ref, impl_items); - check_on_unimplemented( - ccx, - &ccx.tcx.lookup_trait_def(trait_def_id).generics, - it, - ccx.tcx.item_name(trait_def_id)); + let trait_def_id = impl_trait_ref.def_id; + check_on_unimplemented(ccx, trait_def_id, it); } None => { } } } hir::ItemTrait(..) => { let def_id = ccx.tcx.map.local_def_id(it.id); - let generics = &ccx.tcx.lookup_trait_def(def_id).generics; - check_on_unimplemented(ccx, generics, it, it.name); + check_on_unimplemented(ccx, def_id, it); } hir::ItemStruct(..) => { check_struct(ccx, it.id, it.span); @@ -872,9 +865,9 @@ fn check_trait_fn_not_const<'a,'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - generics: &ty::Generics, - item: &hir::Item, - name: ast::Name) { + def_id: DefId, + item: &hir::Item) { + let generics = ccx.tcx.lookup_generics(def_id); if let Some(ref attr) = item.attrs.iter().find(|a| { a.check_name("rustc_on_unimplemented") }) { @@ -894,6 +887,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }) { Some(_) => (), None => { + let name = ccx.tcx.item_name(def_id); span_err!(ccx.tcx.sess, attr.span, E0230, "there is no type parameter \ {} on trait {}", @@ -1301,6 +1295,12 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { &self.ast_ty_to_ty_cache } + fn get_generics(&self, _: Span, id: DefId) + -> Result<&'tcx ty::Generics<'tcx>, ErrorReported> + { + Ok(self.tcx().lookup_generics(id)) + } + fn get_item_type_scheme(&self, _: Span, id: DefId) -> Result, ErrorReported> { @@ -1364,7 +1364,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn ty_infer_for_def(&self, ty_param_def: &ty::TypeParameterDef<'tcx>, - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, span: Span) -> Ty<'tcx> { self.type_var_for_def(span, ty_param_def, substs) } @@ -1690,25 +1690,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { node_id: ast::NodeId) -> Ty<'tcx> { debug!("instantiate_type_path(did={:?}, path={:?})", did, path); - let mut type_scheme = self.tcx.lookup_item_type(did); - if type_scheme.ty.is_fn() { + let mut ty = self.tcx.lookup_item_type(did).ty; + if ty.is_fn() { // Tuple variants have fn type even in type namespace, extract true variant type from it - let fn_ret = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap(); - type_scheme = ty::TypeScheme { ty: fn_ret, generics: type_scheme.generics } + ty = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap(); } let type_predicates = self.tcx.lookup_predicates(did); let substs = AstConv::ast_path_substs_for_ty(self, self, path.span, PathParamMode::Optional, - &type_scheme.generics, + did, path.segments.last().unwrap()); - debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs); + debug!("instantiate_type_path: ty={:?} substs={:?}", ty, substs); let bounds = self.instantiate_bounds(path.span, substs, &type_predicates); let cause = traits::ObligationCause::new(path.span, self.body_id, traits::ItemObligation(did)); self.add_obligations_for_parameters(cause, &bounds); - let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty); + let ty_substituted = self.instantiate_type_scheme(path.span, substs, &ty); self.write_ty(node_id, ty_substituted); self.write_substs(node_id, ty::ItemSubsts { substs: substs @@ -2775,7 +2774,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ity = self.tcx.lookup_item_type(did); debug!("impl_self_ty: ity={:?}", ity); - let substs = self.fresh_substs_for_generics(span, &ity.generics); + let substs = self.fresh_substs_for_item(span, did); let substd_ty = self.instantiate_type_scheme(span, &substs, &ity.ty); TypeAndSubsts { substs: substs, ty: substd_ty } @@ -3443,10 +3442,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path, expr.id, expr.span); if def != Def::Err { - let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span, - def); - self.instantiate_value_path(segments, scheme, &predicates, - opt_ty, def, expr.span, id); + self.instantiate_value_path(segments, opt_ty, def, expr.span, id); } else { self.set_tainted_by_errors(); self.write_error(id); @@ -4036,54 +4032,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { *self.ps.borrow_mut() = prev; } - // Returns the type parameter count and the type for the given definition. - fn type_scheme_and_predicates_for_def(&self, - sp: Span, - defn: Def) - -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) { - match defn { - Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => { - let typ = self.local_ty(sp, nid); - (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ }, - ty::GenericPredicates::empty()) - } - Def::Fn(id) | Def::Method(id) | - Def::Static(id, _) | Def::Variant(_, id) | - Def::Struct(id) | Def::Const(id) | Def::AssociatedConst(id) => { - (self.tcx.lookup_item_type(id), self.tcx.lookup_predicates(id)) - } - Def::Trait(_) | - Def::Enum(..) | - Def::TyAlias(..) | - Def::AssociatedTy(..) | - Def::PrimTy(_) | - Def::TyParam(..) | - Def::Mod(..) | - Def::ForeignMod(..) | - Def::Label(..) | - Def::SelfTy(..) | - Def::Err => { - span_bug!(sp, "expected value, found {:?}", defn); - } - } - } - // Instantiates the given path, which must refer to an item with the given // number of type parameters and type. pub fn instantiate_value_path(&self, segments: &[hir::PathSegment], - type_scheme: TypeScheme<'tcx>, - type_predicates: &ty::GenericPredicates<'tcx>, opt_self_ty: Option>, def: Def, span: Span, node_id: ast::NodeId) -> Ty<'tcx> { - debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})", + debug!("instantiate_value_path(path={:?}, def={:?}, node_id={})", segments, def, - node_id, - type_scheme); + node_id); // We need to extract the type parameters supplied by the user in // the path `path`. Due to the current setup, this is a bit of a @@ -4210,11 +4171,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::ForeignMod(..) | Def::Local(..) | Def::Label(..) | - Def::Upvar(..) => {} - - Def::Err => { - self.set_tainted_by_errors(); - } + Def::Upvar(..) | + Def::Err => {} } // In `>::method`, `A` and `B` are mandatory, but @@ -4232,6 +4190,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_segment.is_some() as usize; self.tcx.prohibit_type_params(&segments[..segments.len() - poly_segments]); + match def { + Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => { + let ty = self.local_ty(span, nid); + let ty = self.normalize_associated_types_in(span, &ty); + self.write_ty(node_id, ty); + self.write_substs(node_id, ty::ItemSubsts { + substs: Substs::empty(self.tcx) + }); + return ty; + } + _ => {} + } + let scheme = self.tcx.lookup_item_type(def.def_id()); + let type_predicates = self.tcx.lookup_predicates(def.def_id()); + // Now we have to compare the types that the user *actually* // provided against the types that were *expected*. If the user // did not provide any types, then we want to substitute inference @@ -4240,16 +4213,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // a problem. self.check_path_parameter_count(subst::TypeSpace, span, - &type_scheme.generics, + scheme.generics, !require_type_space, &mut type_segment); self.check_path_parameter_count(subst::FnSpace, span, - &type_scheme.generics, + scheme.generics, true, &mut fn_segment); - let substs = Substs::from_generics(&type_scheme.generics, |def, _| { + let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { let i = def.index as usize; let segment = match def.space { subst::SelfSpace => None, @@ -4307,9 +4280,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. - let substs = self.tcx.mk_substs(substs); assert!(!substs.has_escaping_regions()); - assert!(!type_scheme.has_escaping_regions()); + assert!(!scheme.ty.has_escaping_regions()); // Add all the obligations that are required, substituting and // normalized appropriately. @@ -4320,7 +4292,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Substitute the values for the type parameters into the type of // the referenced item. - let ty_substituted = self.instantiate_type_scheme(span, &substs, &type_scheme.ty); + let ty_substituted = self.instantiate_type_scheme(span, &substs, &scheme.ty); if let Some((ty::ImplContainer(impl_def_id), self_ty)) = ufcs_associated { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 5f8861f3099..6a475864f3b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -18,7 +18,6 @@ use hir::def_id::DefId; use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::fold::{TypeFolder,TypeFoldable}; -use rustc::ty::subst::ParamSpace; use rustc::infer::{InferCtxt, FixupError}; use rustc::util::nodemap::DefIdMap; use write_substs_to_tcx; @@ -68,7 +67,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_closures(); wbcx.visit_liberated_fn_sigs(); wbcx.visit_fru_field_types(); - wbcx.visit_anon_types(); + wbcx.visit_anon_types(item_id); wbcx.visit_deferred_obligations(item_id); } } @@ -104,22 +103,20 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } let free_substs = fcx.parameter_environment.free_substs; - for &space in &ParamSpace::all() { - for (i, r) in free_substs.regions.get_slice(space).iter().enumerate() { - match *r { - ty::ReFree(ty::FreeRegion { - bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. - }) => { - let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, - index: i as u32, - name: name, - }); - wbcx.free_to_bound_regions.insert(def_id, bound_region); - } - _ => { - bug!("{:?} is not a free region for an early-bound lifetime", r); - } + for (space, i, r) in free_substs.regions.iter_enumerated() { + match *r { + ty::ReFree(ty::FreeRegion { + bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. + }) => { + let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion { + space: space, + index: i as u32, + name: name, + }); + wbcx.free_to_bound_regions.insert(def_id, bound_region); + } + _ => { + bug!("{:?} is not a free region for an early-bound lifetime", r); } } } @@ -300,11 +297,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_anon_types(&self) { + fn visit_anon_types(&self, item_id: ast::NodeId) { if self.fcx.writeback_errors.get() { return } + let item_def_id = self.fcx.tcx.map.local_def_id(item_id); + let gcx = self.tcx().global_tcx(); for (&def_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() { let reason = ResolvingAnonTy(def_id); @@ -345,9 +344,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } }); - gcx.tcache.borrow_mut().insert(def_id, ty::TypeScheme { + gcx.register_item_type(def_id, ty::TypeScheme { ty: outside_ty, - generics: ty::Generics::empty() + generics: gcx.lookup_generics(item_def_id) }); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a2a162a7f5f..77723ea9733 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; -use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace}; +use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace}; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -120,6 +120,7 @@ struct ItemCtxt<'a,'tcx:'a> { #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstConvRequest { + GetGenerics(DefId), GetItemTypeScheme(DefId), GetTraitDef(DefId), EnsureSuperPredicates(DefId), @@ -187,6 +188,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { err.span_label(span, &format!("cyclic reference")); match cycle[0] { + AstConvRequest::GetGenerics(def_id) | AstConvRequest::GetItemTypeScheme(def_id) | AstConvRequest::GetTraitDef(def_id) => { err.note( @@ -209,6 +211,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { for request in &cycle[1..] { match *request { + AstConvRequest::GetGenerics(def_id) | AstConvRequest::GetItemTypeScheme(def_id) | AstConvRequest::GetTraitDef(def_id) => { err.note( @@ -231,6 +234,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> { } match cycle[0] { + AstConvRequest::GetGenerics(def_id) | AstConvRequest::GetItemTypeScheme(def_id) | AstConvRequest::GetTraitDef(def_id) => { err.note( @@ -303,6 +307,14 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { &self.ccx.ast_ty_to_ty_cache } + fn get_generics(&self, span: Span, id: DefId) + -> Result<&'tcx ty::Generics<'tcx>, ErrorReported> + { + self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || { + Ok(generics_of_def_id(self.ccx, id)) + }) + } + fn get_item_type_scheme(&self, span: Span, id: DefId) -> Result, ErrorReported> { @@ -544,7 +556,6 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, name: ast::Name, @@ -553,25 +564,22 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, sig: &hir::MethodSig, defaultness: hir::Defaultness, untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_generics: &ty::Generics<'tcx>, rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { - let ty_generics = ty_generics_for_fn(ccx, &sig.generics, rcvr_ty_generics); + let def_id = ccx.tcx.map.local_def_id(id); + let ty_generics = generics_of_def_id(ccx, def_id); let ty_generic_predicates = ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates); let (fty, explicit_self_category) = { let anon_scope = match container { - ImplContainer(_) => Some(AnonTypeScope::new(&ty_generics)), + ImplContainer(_) => Some(AnonTypeScope::new(def_id)), TraitContainer(_) => None }; AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), sig, untransformed_rcvr_ty, anon_scope) }; - let def_id = ccx.tcx.map.local_def_id(id); - let substs = mk_item_substs(ccx.tcx, &ty_generics); - let ty_method = ty::Method::new(name, ty_generics, ty_generic_predicates, @@ -582,16 +590,14 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, def_id, container); + let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), + ccx.tcx.map.span(id), def_id); let fty = ccx.tcx.mk_fn_def(def_id, substs, ty_method.fty); debug!("method {} (id {}) has type {:?}", name, id, fty); - ccx.tcx.register_item_type(def_id, TypeScheme { - generics: ty_method.generics.clone(), - ty: fty - }); - ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone()); - + ccx.tcx.tcache.borrow_mut().insert(def_id, fty); write_ty_to_tcx(ccx, id, fty); + ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone()); debug!("writing method type: def_id={:?} mty={:?}", def_id, ty_method); @@ -601,7 +607,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - struct_generics: &ty::Generics<'tcx>, + struct_generics: &'tcx ty::Generics<'tcx>, struct_predicates: &ty::GenericPredicates<'tcx>, field: &hir::StructField, ty_f: ty::FieldDefMaster<'tcx>) @@ -613,7 +619,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /* add the field to the tcache */ ccx.tcx.register_item_type(ccx.tcx.map.local_def_id(field.id), ty::TypeScheme { - generics: struct_generics.clone(), + generics: struct_generics, ty: tt }); ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(field.id), @@ -709,8 +715,9 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } } hir::ItemEnum(ref enum_definition, _) => { - let (scheme, predicates) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + let scheme = type_scheme_of_def_id(ccx, def_id); + let predicates = predicates_of_item(ccx, it); convert_enum_variant_types(ccx, tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)), scheme, @@ -737,7 +744,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Create generics from the generics specified in the impl head. debug!("convert: ast_generics={:?}", generics); let def_id = ccx.tcx.map.local_def_id(it.id); - let ty_generics = ty_generics_for_impl(ccx, generics); + let ty_generics = generics_of_def_id(ccx, def_id); let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); debug!("convert: impl_bounds={:?}", ty_predicates); @@ -746,7 +753,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { write_ty_to_tcx(ccx, it.id, selfty); tcx.register_item_type(def_id, - TypeScheme { generics: ty_generics.clone(), + TypeScheme { generics: ty_generics, ty: selfty }); let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| { AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), @@ -791,7 +798,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { .to_ty(&ExplicitRscope, &ty); tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id), TypeScheme { - generics: ty_generics.clone(), + generics: ty_generics, ty: ty, }); // Trait-associated constants are always public. @@ -829,7 +836,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { convert_method(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, method_vis, - sig, impl_item.defaultness, selfty, &ty_generics, + sig, impl_item.defaultness, selfty, &ty_predicates); } } @@ -856,7 +863,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { .to_ty(&ExplicitRscope, ty); tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), TypeScheme { - generics: trait_def.generics.clone(), + generics: trait_def.generics, ty: ty, }); convert_associated_const(ccx, @@ -898,7 +905,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { sig, hir::Defaultness::Default, tcx.mk_self_type(), - &trait_def.generics, &trait_predicates); } @@ -917,11 +923,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { trait_item_def_ids); }, hir::ItemStruct(ref struct_def, _) => { - let (scheme, predicates) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + let scheme = type_scheme_of_def_id(ccx, def_id); + let predicates = predicates_of_item(ccx, it); - let it_def_id = ccx.tcx.map.local_def_id(it.id); - let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant(); + let variant = tcx.lookup_adt_def_master(def_id).struct_variant(); for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) { convert_field(ccx, &scheme.generics, &predicates, f, ty_f) @@ -933,15 +939,14 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { }, hir::ItemTy(_, ref generics) => { ensure_no_ty_param_bounds(ccx, it.span, generics, "type"); - let (scheme, _) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + type_scheme_of_def_id(ccx, def_id); + predicates_of_item(ccx, it); }, _ => { - // This call populates the type cache with the converted type - // of the item in passing. All we have to do here is to write - // it into the node type table. - let (scheme, _) = convert_typed_item(ccx, it); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + type_scheme_of_def_id(ccx, def_id); + predicates_of_item(ccx, it); }, } } @@ -952,6 +957,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, scheme: ty::TypeScheme<'tcx>, predicates: ty::GenericPredicates<'tcx>) { let tcx = ccx.tcx; + let def_id = tcx.map.local_def_id(ctor_id); + tcx.generics.borrow_mut().insert(def_id, scheme.generics); let ctor_ty = match variant.kind { VariantKind::Unit | VariantKind::Struct => scheme.ty, VariantKind::Tuple => { @@ -960,8 +967,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .iter() .map(|field| field.unsubst_ty()) .collect(); - let def_id = tcx.map.local_def_id(ctor_id); - let substs = mk_item_substs(tcx, &scheme.generics); + let substs = mk_item_substs(&ccx.icx(&predicates), + ccx.tcx.map.span(ctor_id), def_id); tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, abi: abi::Abi::Rust, @@ -974,12 +981,8 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; write_ty_to_tcx(ccx, ctor_id, ctor_ty); + tcx.tcache.borrow_mut().insert(def_id, ctor_ty); tcx.predicates.borrow_mut().insert(tcx.map.local_def_id(ctor_id), predicates); - tcx.register_item_type(tcx.map.local_def_id(ctor_id), - TypeScheme { - generics: scheme.generics, - ty: ctor_ty - }); } fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1237,7 +1240,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } let (unsafety, generics, items) = match it.node { - hir::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items), + hir::ItemTrait(unsafety, ref generics, _, ref items) => { + (unsafety, generics, items) + } _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"), }; @@ -1253,9 +1258,8 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, err.emit(); } - let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics)); - - let ty_generics = ty_generics_for_trait(ccx, it.id, substs, generics); + let ty_generics = generics_of_def_id(ccx, def_id); + let substs = mk_item_substs(&ccx.icx(generics), it.span, def_id); let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| { match trait_item.node { @@ -1264,51 +1268,14 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }).collect(); - let trait_ref = ty::TraitRef { - def_id: def_id, - substs: substs, - }; - + let trait_ref = ty::TraitRef::new(def_id, substs); let trait_def = ty::TraitDef::new(unsafety, paren_sugar, ty_generics, trait_ref, associated_type_names); - return tcx.intern_trait_def(trait_def); - - fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - generics: &hir::Generics) - -> Substs<'tcx> - { - let tcx = ccx.tcx; - - // Creates a no-op substitution for the trait's type parameters. - let regions = - generics.lifetimes - .iter() - .enumerate() - .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion { - space: TypeSpace, - index: i as u32, - name: def.lifetime.name - })) - .collect(); - - // Start with the generics in the type parameters... - let types: Vec<_> = - generics.ty_params - .iter() - .enumerate() - .map(|(i, def)| tcx.mk_param(TypeSpace, - i as u32, def.name)) - .collect(); - - // ...and also create the `Self` parameter. - let self_ty = tcx.mk_self_type(); - - Substs::new_trait(types, regions, self_ty) - } + tcx.intern_trait_def(trait_def) } fn trait_defines_associated_type_named(ccx: &CrateCtxt, @@ -1410,105 +1377,243 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) } } -fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - def_id: DefId) - -> ty::TypeScheme<'tcx> -{ - if let Some(node_id) = ccx.tcx.map.as_local_node_id(def_id) { - match ccx.tcx.map.find(node_id) { - Some(hir_map::NodeItem(item)) => { - type_scheme_of_item(ccx, &item) +fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + def_id: DefId) + -> &'tcx ty::Generics<'tcx> { + let tcx = ccx.tcx; + let node_id = if let Some(id) = tcx.map.as_local_node_id(def_id) { + id + } else { + return tcx.lookup_generics(def_id); + }; + tcx.generics.memoize(def_id, || { + use rustc::hir::map::*; + use rustc::hir::*; + + let mut opt_self = None; + let mut base_def_id = None; + let mut allow_defaults = false; + + let no_generics = hir::Generics::empty(); + let (space, ast_generics) = match tcx.map.get(node_id) { + NodeImplItem(&ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) | + NodeTraitItem(&TraitItem { node: MethodTraitItem(ref sig, _), .. }) => { + let parent_id = tcx.map.get_parent(node_id); + base_def_id = Some(tcx.map.local_def_id(parent_id)); + (FnSpace, &sig.generics) } - Some(hir_map::NodeForeignItem(foreign_item)) => { + + NodeImplItem(_) | + NodeTraitItem(_) => { + let parent_id = tcx.map.get_parent(node_id); + base_def_id = Some(tcx.map.local_def_id(parent_id)); + (FnSpace, &no_generics) + } + + NodeItem(item) => { + match item.node { + ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics), + ItemImpl(_, _, ref generics, _, _, _) => (TypeSpace, generics), + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) => { + allow_defaults = true; + (TypeSpace, generics) + } + ItemTrait(_, ref generics, _, _) => { + // Add in the self type parameter. + // + // Something of a hack: use the node id for the trait, also as + // the node id for the Self type parameter. + let param_id = item.id; + + let parent = ccx.tcx.map.get_parent(param_id); + + let def = ty::TypeParameterDef { + space: SelfSpace, + index: 0, + name: keywords::SelfType.name(), + def_id: tcx.map.local_def_id(param_id), + default_def_id: tcx.map.local_def_id(parent), + default: None, + object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, + }; + tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); + opt_self = Some(def); + + allow_defaults = true; + (TypeSpace, generics) + } + _ => (TypeSpace, &no_generics) + } + } + + NodeForeignItem(item) => { + match item.node { + ForeignItemStatic(..) => (TypeSpace, &no_generics), + ForeignItemFn(_, ref generics) => (FnSpace, generics) + } + } + + _ => (TypeSpace, &no_generics) + }; + + let empty_generics = ty::Generics::empty(); + let base_generics = base_def_id.map_or(&empty_generics, |def_id| { + generics_of_def_id(ccx, def_id) + }); + + let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); + let regions = early_lifetimes.iter().enumerate().map(|(i, l)| { + ty::RegionParameterDef { + name: l.lifetime.name, + space: space, + index: i as u32, + def_id: tcx.map.local_def_id(l.lifetime.id), + bounds: l.bounds.iter().map(|l| { + ast_region_to_region(tcx, l) + }).collect() + } + }).collect(); + + // Now create the real type parameters. + let types = ast_generics.ty_params.iter().enumerate().map(|(i, _)| { + get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults) + }).collect(); + + let has_self = base_generics.has_self || opt_self.is_some(); + let (regions, types) = match space { + SelfSpace => bug!(), + TypeSpace => { + assert_eq!(base_generics.regions.as_full_slice().len(), 0); + assert_eq!(base_generics.types.as_full_slice().len(), 0); + (VecPerParamSpace::new(vec![], regions, vec![]), + VecPerParamSpace::new(opt_self.into_iter().collect(), types, vec![])) + } + FnSpace => { + assert_eq!(base_generics.regions.len(FnSpace), 0); + assert_eq!(base_generics.types.len(FnSpace), 0); + (VecPerParamSpace::new(base_generics.regions.get_slice(SelfSpace).to_vec(), + base_generics.regions.get_slice(TypeSpace).to_vec(), + regions), + VecPerParamSpace::new(base_generics.types.get_slice(SelfSpace).to_vec(), + base_generics.types.get_slice(TypeSpace).to_vec(), + types)) + } + }; + + // Debugging aid. + if tcx.has_attr(def_id, "rustc_object_lifetime_default") { + let object_lifetime_default_reprs: String = + types.as_full_slice().iter().map(|t| { + match t.object_lifetime_default { + ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), + d => format!("{:?}", d), + } + }).collect::>().join(","); + tcx.sess.span_err(tcx.map.span(node_id), &object_lifetime_default_reprs); + } + + tcx.alloc_generics(ty::Generics { + regions: regions, + types: types, + has_self: has_self + }) + }) +} + +fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + def_id: DefId) + -> Ty<'tcx> { + let node_id = if let Some(id) = ccx.tcx.map.as_local_node_id(def_id) { + id + } else { + return ccx.tcx.lookup_item_type(def_id).ty; + }; + ccx.tcx.tcache.memoize(def_id, || { + use rustc::hir::map::*; + use rustc::hir::*; + + let ty = match ccx.tcx.map.get(node_id) { + NodeItem(item) => { + match item.node { + ItemStatic(ref t, _, _) | ItemConst(ref t, _) => { + ccx.icx(&()).to_ty(&ExplicitRscope, &t) + } + ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { + let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl, + Some(AnonTypeScope::new(def_id))); + let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ccx.tcx.mk_fn_def(def_id, substs, tofd) + } + ItemTy(ref t, ref generics) => { + ccx.icx(generics).to_ty(&ExplicitRscope, &t) + } + ItemEnum(ref ei, ref generics) => { + let def = convert_enum_def(ccx, item, ei); + let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ccx.tcx.mk_enum(def, substs) + } + ItemStruct(ref si, ref generics) => { + let def = convert_struct_def(ccx, item, si); + let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id); + ccx.tcx.mk_struct(def, substs) + } + ItemDefaultImpl(..) | + ItemTrait(..) | + ItemImpl(..) | + ItemMod(..) | + ItemForeignMod(..) | + ItemExternCrate(..) | + ItemUse(..) => { + span_bug!( + item.span, + "compute_type_of_item: unexpected item type: {:?}", + item.node); + } + } + } + NodeForeignItem(foreign_item) => { let abi = ccx.tcx.map.get_foreign_abi(node_id); - type_scheme_of_foreign_item(ccx, &foreign_item, abi) + + match foreign_item.node { + ForeignItemFn(ref fn_decl, ref generics) => { + compute_type_of_foreign_fn_decl( + ccx, ccx.tcx.map.local_def_id(foreign_item.id), + fn_decl, generics, abi) + } + ForeignItemStatic(ref t, _) => { + ccx.icx(&()).to_ty(&ExplicitRscope, t) + } + } } x => { - bug!("unexpected sort of node in get_item_type_scheme(): {:?}", - x); + bug!("unexpected sort of node in type_of_def_id(): {:?}", x); } + }; + + write_ty_to_tcx(ccx, node_id, ty); + ty + }) +} + +fn type_scheme_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>, + def_id: DefId) + -> ty::TypeScheme<'tcx> { + if def_id.is_local() { + ty::TypeScheme { + generics: generics_of_def_id(ccx, def_id), + ty: type_of_def_id(ccx, def_id) } } else { ccx.tcx.lookup_item_type(def_id) } } -fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - item: &hir::Item) - -> ty::TypeScheme<'tcx> -{ - let item_def_id = ccx.tcx.map.local_def_id(item.id); - ccx.tcx.tcache.memoize(item_def_id, || { - // NB. Since the `memoized` function enters a new task, and we - // are giving this task access to the item `item`, we must - // register a read. - assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id)); - ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); - compute_type_scheme_of_item(ccx, item) - }) -} - -fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - it: &hir::Item) - -> ty::TypeScheme<'tcx> -{ - let tcx = ccx.tcx; - match it.node { - hir::ItemStatic(ref t, _, _) | hir::ItemConst(ref t, _) => { - let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &t); - ty::TypeScheme { ty: ty, generics: ty::Generics::empty() } - } - hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => { - let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty()); - let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl, - Some(AnonTypeScope::new(&ty_generics))); - let def_id = ccx.tcx.map.local_def_id(it.id); - let substs = mk_item_substs(tcx, &ty_generics); - let ty = tcx.mk_fn_def(def_id, substs, tofd); - ty::TypeScheme { ty: ty, generics: ty_generics } - } - hir::ItemTy(ref t, ref generics) => { - let ty_generics = ty_generics_for_type(ccx, generics); - let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &t); - ty::TypeScheme { ty: ty, generics: ty_generics } - } - hir::ItemEnum(ref ei, ref generics) => { - let def = convert_enum_def(ccx, it, ei); - let ty_generics = ty_generics_for_type(ccx, generics); - let substs = mk_item_substs(tcx, &ty_generics); - let t = tcx.mk_enum(def, substs); - ty::TypeScheme { ty: t, generics: ty_generics } - } - hir::ItemStruct(ref si, ref generics) => { - let def = convert_struct_def(ccx, it, si); - let ty_generics = ty_generics_for_type(ccx, generics); - let substs = mk_item_substs(tcx, &ty_generics); - let t = tcx.mk_struct(def, substs); - ty::TypeScheme { ty: t, generics: ty_generics } - } - hir::ItemDefaultImpl(..) | - hir::ItemTrait(..) | - hir::ItemImpl(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) | - hir::ItemExternCrate(..) | - hir::ItemUse(..) => { - span_bug!( - it.span, - "compute_type_scheme_of_item: unexpected item type: {:?}", - it.node); - } - } -} - -fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, +fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) - -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>) -{ - let tcx = ccx.tcx; - - let tag = type_scheme_of_item(ccx, it); - let scheme = TypeScheme { generics: tag.generics, ty: tag.ty }; + -> ty::GenericPredicates<'tcx> { + let def_id = ccx.tcx.map.local_def_id(it.id); let predicates = match it.node { hir::ItemStatic(..) | hir::ItemConst(..) => { ty::GenericPredicates::empty() @@ -1516,12 +1621,8 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ItemFn(_, _, _, _, ref ast_generics, _) => { ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty()) } - hir::ItemTy(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } - hir::ItemEnum(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } + hir::ItemTy(_, ref generics) | + hir::ItemEnum(_, ref generics) | hir::ItemStruct(_, ref generics) => { ty_generic_predicates_for_type_or_impl(ccx, generics) } @@ -1534,68 +1635,16 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, hir::ItemForeignMod(..) => { span_bug!( it.span, - "compute_type_scheme_of_item: unexpected item type: {:?}", + "predicates_of_item: unexpected item type: {:?}", it.node); } }; - let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - predicates.clone()); + let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, + predicates.clone()); assert!(prev_predicates.is_none()); - // Debugging aid. - if tcx.has_attr(ccx.tcx.map.local_def_id(it.id), "rustc_object_lifetime_default") { - let object_lifetime_default_reprs: String = - scheme.generics.types.as_full_slice().iter() - .map(|t| match t.object_lifetime_default { - ty::ObjectLifetimeDefault::Specific(r) => r.to_string(), - d => format!("{:?}", d), - }) - .collect::>() - .join(","); - - tcx.sess.span_err(it.span, &object_lifetime_default_reprs); - } - - return (scheme, predicates); -} - -fn type_scheme_of_foreign_item<'a, 'tcx>( - ccx: &CrateCtxt<'a, 'tcx>, - item: &hir::ForeignItem, - abi: abi::Abi) - -> ty::TypeScheme<'tcx> -{ - let item_def_id = ccx.tcx.map.local_def_id(item.id); - ccx.tcx.tcache.memoize(item_def_id, || { - // NB. Since the `memoized` function enters a new task, and we - // are giving this task access to the item `item`, we must - // register a read. - assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id)); - ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id)); - compute_type_scheme_of_foreign_item(ccx, item, abi) - }) -} - -fn compute_type_scheme_of_foreign_item<'a, 'tcx>( - ccx: &CrateCtxt<'a, 'tcx>, - it: &hir::ForeignItem, - abi: abi::Abi) - -> ty::TypeScheme<'tcx> -{ - match it.node { - hir::ForeignItemFn(ref fn_decl, ref generics) => { - compute_type_scheme_of_foreign_fn_decl( - ccx, ccx.tcx.map.local_def_id(it.id), - fn_decl, generics, abi) - } - hir::ForeignItemStatic(ref t, _) => { - ty::TypeScheme { - generics: ty::Generics::empty(), - ty: AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t) - } - } - } + predicates } fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -1605,11 +1654,8 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // map, and I regard each time that I use it as a personal and // moral failing, but at the moment it seems like the only // convenient way to extract the ABI. - ndm - let tcx = ccx.tcx; - let abi = tcx.map.get_foreign_abi(it.id); - - let scheme = type_scheme_of_foreign_item(ccx, it, abi); - write_ty_to_tcx(ccx, it.id, scheme.ty); + let def_id = ccx.tcx.map.local_def_id(it.id); + type_scheme_of_def_id(ccx, def_id); let predicates = match it.node { hir::ForeignItemFn(_, ref generics) => { @@ -1620,21 +1666,10 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } }; - let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - predicates); + let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); assert!(prev_predicates.is_none()); } -fn ty_generics_for_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &hir::Generics) - -> ty::Generics<'tcx> { - ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty(), true) -} - -fn ty_generics_for_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, generics: &hir::Generics) - -> ty::Generics<'tcx> { - ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty(), false) -} - fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, generics: &hir::Generics) -> ty::GenericPredicates<'tcx> @@ -1642,50 +1677,6 @@ fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty()) } -fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - trait_id: ast::NodeId, - substs: &'tcx Substs<'tcx>, - ast_generics: &hir::Generics) - -> ty::Generics<'tcx> -{ - debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})", - ccx.tcx.map.local_def_id(trait_id), substs); - - let mut generics = ty_generics_for_type(ccx, ast_generics); - - // Add in the self type parameter. - // - // Something of a hack: use the node id for the trait, also as - // the node id for the Self type parameter. - let param_id = trait_id; - - let parent = ccx.tcx.map.get_parent(param_id); - - let def = ty::TypeParameterDef { - space: SelfSpace, - index: 0, - name: keywords::SelfType.name(), - def_id: ccx.tcx.map.local_def_id(param_id), - default_def_id: ccx.tcx.map.local_def_id(parent), - default: None, - object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, - }; - - ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone()); - - generics.types.push(SelfSpace, def); - - return generics; -} - -fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - generics: &hir::Generics, - base_generics: &ty::Generics<'tcx>) - -> ty::Generics<'tcx> -{ - ty_generics(ccx, FnSpace, generics, base_generics, false) -} - fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, generics: &hir::Generics, base_predicates: &ty::GenericPredicates<'tcx>) @@ -1859,42 +1850,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, result } -fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - space: ParamSpace, - ast_generics: &hir::Generics, - base_generics: &ty::Generics<'tcx>, - allow_defaults: bool) - -> ty::Generics<'tcx> -{ - let tcx = ccx.tcx; - let mut result = base_generics.clone(); - - let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); - for (i, l) in early_lifetimes.iter().enumerate() { - let bounds = l.bounds.iter() - .map(|l| ast_region_to_region(tcx, l)) - .collect(); - let def = ty::RegionParameterDef { name: l.lifetime.name, - space: space, - index: i as u32, - def_id: ccx.tcx.map.local_def_id(l.lifetime.id), - bounds: bounds }; - result.regions.push(space, def); - } - - assert!(result.types.is_empty_in(space)); - - // Now create the real type parameters. - for i in 0..ast_generics.ty_params.len() { - let def = - get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults); - debug!("ty_generics: def for type param: {:?}, {:?}", def, space); - result.types.push(space, def); - } - - result -} - fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, path: &P, space: ParamSpace, @@ -1969,6 +1924,9 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); + debug!("get_or_create_type_parameter_def: def for type param: {:?}, {:?}", + def, space); + def } @@ -2122,16 +2080,14 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( +fn compute_type_of_foreign_fn_decl<'a, 'tcx>( ccx: &CrateCtxt<'a, 'tcx>, - id: DefId, + def_id: DefId, decl: &hir::FnDecl, ast_generics: &hir::Generics, abi: abi::Abi) - -> ty::TypeScheme<'tcx> + -> Ty<'tcx> { - let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty()); - let rb = BindingRscope::new(); let input_tys = decl.inputs .iter() @@ -2167,34 +2123,32 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>( } } - let substs = mk_item_substs(ccx.tcx, &ty_generics); - let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy { + let id = ccx.tcx.map.as_local_node_id(def_id).unwrap(); + let substs = mk_item_substs(&ccx.icx(ast_generics), ccx.tcx.map.span(id), def_id); + ccx.tcx.mk_fn_def(def_id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy { abi: abi, unsafety: hir::Unsafety::Unsafe, sig: ty::Binder(ty::FnSig {inputs: input_tys, output: output, variadic: decl.variadic}), - })); - - ty::TypeScheme { - generics: ty_generics, - ty: t_fn - } + })) } -pub fn mk_item_substs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - ty_generics: &ty::Generics) - -> &'tcx Substs<'tcx> -{ - let types = - ty_generics.types.map( - |def| tcx.mk_param_from_def(def)); +pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + span: Span, + def_id: DefId) + -> &'tcx Substs<'tcx> { + let tcx = astconv.tcx(); + // FIXME(eddyb) Do this request from Substs::for_item in librustc. + if let Err(ErrorReported) = astconv.get_generics(span, def_id) { + // No convenient way to recover from a cycle here. Just bail. Sorry! + tcx.sess.abort_if_errors(); + bug!("ErrorReported returned, but no errors reports?") + } - let regions = - ty_generics.regions.map( - |def| def.to_early_bound_region()); - - tcx.mk_substs(Substs::new(types, regions)) + Substs::for_item(tcx, def_id, + |def, _| def.to_early_bound_region(), + |def, _| tcx.mk_param_from_def(def)) } /// Checks that all the type parameters on an impl diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4ce6f8210c3..8a8232535c7 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -231,7 +231,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, _ => () } let main_def_id = tcx.map.local_def_id(main_id); - let substs = tcx.mk_substs(Substs::empty()); + let substs = Substs::empty(tcx); let se_ty = tcx.mk_fn_def(main_def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, @@ -284,7 +284,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, } let start_def_id = ccx.tcx.map.local_def_id(start_id); - let substs = tcx.mk_substs(Substs::empty()); + let substs = Substs::empty(tcx); let se_ty = tcx.mk_fn_def(start_def_id, substs, tcx.mk_bare_fn(ty::BareFnTy { unsafety: hir::Unsafety::Normal, diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs index 58d1ec9d02a..9aca779dd89 100644 --- a/src/librustc_typeck/rscope.rs +++ b/src/librustc_typeck/rscope.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use rustc::ty::{self, TyCtxt}; +use rustc::hir::def_id::DefId; +use rustc::ty; use rustc::ty::subst::Substs; +use astconv::AstConv; + use std::cell::Cell; use syntax_pos::Span; @@ -71,33 +73,34 @@ pub trait RegionScope { } #[derive(Copy, Clone)] -pub struct AnonTypeScope<'a> { - generics: &'a ty::Generics<'a> +pub struct AnonTypeScope { + enclosing_item: DefId } -impl<'a, 'b, 'gcx, 'tcx> AnonTypeScope<'a> { - pub fn new(generics: &'a ty::Generics<'a>) -> AnonTypeScope<'a> { +impl<'gcx: 'tcx, 'tcx> AnonTypeScope { + pub fn new(enclosing_item: DefId) -> AnonTypeScope { AnonTypeScope { - generics: generics + enclosing_item: enclosing_item } } - pub fn fresh_substs(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { + pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span) + -> &'tcx Substs<'tcx> { use collect::mk_item_substs; - mk_item_substs(tcx, self.generics) + mk_item_substs(astconv, span, self.enclosing_item) } } /// A scope wrapper which optionally allows anonymized types. #[derive(Copy, Clone)] -pub struct MaybeWithAnonTypes<'a, R> { +pub struct MaybeWithAnonTypes { base_scope: R, - anon_scope: Option> + anon_scope: Option } -impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R> { - pub fn new(base_scope: R, anon_scope: Option>) -> Self { +impl MaybeWithAnonTypes { + pub fn new(base_scope: R, anon_scope: Option) -> Self { MaybeWithAnonTypes { base_scope: base_scope, anon_scope: anon_scope @@ -105,7 +108,7 @@ impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R> { } } -impl<'a, R: RegionScope> RegionScope for MaybeWithAnonTypes<'a, R> { +impl RegionScope for MaybeWithAnonTypes { fn object_lifetime_default(&self, span: Span) -> Option { self.base_scope.object_lifetime_default(span) } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 6e6f9ce65c5..8c9b4beb79d 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -16,8 +16,7 @@ use dep_graph::DepTrackingMapConfig; use hir::def_id::DefId; use middle::resolve_lifetime as rl; -use rustc::ty::subst; -use rustc::ty::subst::ParamSpace; +use rustc::ty::subst::{self, ParamSpace, Substs}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::ItemVariances; use rustc::hir::map as hir_map; @@ -370,8 +369,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, def.did, - item_type.generics.types.get_slice(subst::TypeSpace), - item_type.generics.regions.get_slice(subst::TypeSpace), + item_type.generics.types.as_full_slice(), + item_type.generics.regions.as_full_slice(), substs, variance); } @@ -449,7 +448,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { def_id: DefId, type_param_defs: &[ty::TypeParameterDef<'tcx>], region_param_defs: &[ty::RegionParameterDef], - substs: &subst::Substs<'tcx>, + substs: &Substs<'tcx>, variance: VarianceTermPtr<'a>) { debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})", def_id, diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 8bb49410a5b..22edf219dff 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -16,6 +16,7 @@ //! inferred is then written into the `variance_map` in the tcx. use rustc::ty; +use rustc::ty::subst; use std::rc::Rc; use super::constraints::*; @@ -108,7 +109,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { let num_inferred = self.terms_cx.num_inferred(); while index < num_inferred { let item_id = inferred_infos[index].item_id; - let mut item_variances = ty::ItemVariances::empty(); + + let (mut rs, mut rt, mut rf) = (vec![], vec![], vec![]); + let (mut ts, mut tt, mut tf) = (vec![], vec![], vec![]); while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; @@ -116,13 +119,34 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { debug!("Index {} Info {} / {:?} / {:?} Variance {:?}", index, info.index, info.kind, info.space, variance); match info.kind { - TypeParam => { item_variances.types.push(info.space, variance); } - RegionParam => { item_variances.regions.push(info.space, variance); } + TypeParam => { + let types = match info.space { + subst::SelfSpace => &mut ts, + subst::TypeSpace => &mut tt, + subst::FnSpace => &mut tf + }; + assert_eq!(types.len(), info.index); + types.push(variance); + } + RegionParam => { + let regions = match info.space { + subst::SelfSpace => &mut rs, + subst::TypeSpace => &mut rt, + subst::FnSpace => &mut rf + }; + assert_eq!(regions.len(), info.index); + regions.push(variance); + } } index += 1; } + let item_variances = ty::ItemVariances { + regions: subst::VecPerParamSpace::new(rs, rt, rf), + types: subst::VecPerParamSpace::new(ts, tt, tf) + }; + debug!("item_id={} item_variances={:?}", item_id, item_variances); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cea12404298..b4be201440c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -161,7 +161,7 @@ pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tc let def = tcx.lookup_trait_def(did); let trait_items = tcx.trait_items(did).clean(cx); let predicates = tcx.lookup_predicates(did); - let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); + let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); clean::Trait { @@ -189,7 +189,7 @@ fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx let predicates = tcx.lookup_predicates(did); clean::Function { decl: decl, - generics: (&t.generics, &predicates, subst::FnSpace).clean(cx), + generics: (t.generics, &predicates, subst::FnSpace).clean(cx), unsafety: style, constness: constness, abi: abi, @@ -209,7 +209,7 @@ fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, &[..] if variant.kind == ty::VariantKind::Tuple => doctree::Tuple, _ => doctree::Plain, }, - generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -222,7 +222,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, match t.ty.sty { ty::TyEnum(edef, _) if !tcx.sess.cstore.is_typedef(did) => { return clean::EnumItem(clean::Enum { - generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), variants_stripped: false, variants: edef.variants.clean(cx), }) @@ -232,7 +232,7 @@ fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, clean::TypedefItem(clean::Typedef { type_: t.ty.clean(cx), - generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (t.generics, &predicates, subst::TypeSpace).clean(cx), }, false) } @@ -389,15 +389,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } ty::TypeTraitItem(ref assoc_ty) => { let did = assoc_ty.def_id; - let type_scheme = ty::TypeScheme { - ty: assoc_ty.ty.unwrap(), - generics: ty::Generics::empty() - }; // Not sure the choice of ParamSpace actually matters here, // because an associated type won't have generics on the LHS let typedef = clean::Typedef { - type_: type_scheme.ty.clean(cx), - generics: (&type_scheme.generics, + type_: assoc_ty.ty.unwrap().clean(cx), + generics: (&ty::Generics::empty(), &ty::GenericPredicates::empty(), subst::TypeSpace).clean(cx) }; @@ -438,7 +434,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, provided_trait_methods: provided, trait_: trait_, for_: for_, - generics: (&ty.generics, &predicates, subst::TypeSpace).clean(cx), + generics: (ty.generics, &predicates, subst::TypeSpace).clean(cx), items: trait_items, polarity: polarity.map(|p| { p.clean(cx) }), }), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ffe5b9aad2f..f8a3a0af697 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -41,7 +41,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::fold::Folder; use rustc::hir::print as pprust; -use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace}; +use rustc::ty::subst::{self, ParamSpace, Substs, VecPerParamSpace}; use rustc::ty; use rustc::middle::stability; @@ -631,7 +631,7 @@ impl Clean for hir::TyParamBound { } fn external_path_params(cx: &DocContext, trait_did: Option, - bindings: Vec, substs: &subst::Substs) -> PathParameters { + bindings: Vec, substs: &Substs) -> PathParameters { let lifetimes = substs.regions.get_slice(subst::TypeSpace) .iter() .filter_map(|v| v.clean(cx)) @@ -676,7 +676,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar // from Fn<(A, B,), C> to Fn(A, B) -> C fn external_path(cx: &DocContext, name: &str, trait_did: Option, - bindings: Vec, substs: &subst::Substs) -> Path { + bindings: Vec, substs: &Substs) -> Path { Path { global: false, segments: vec![PathSegment { @@ -692,20 +692,20 @@ impl Clean for ty::BuiltinBound { Some(tcx) => tcx, None => return RegionBound(Lifetime::statik()) }; - let empty = subst::Substs::empty(); + let empty = Substs::empty(tcx); let (did, path) = match *self { ty::BoundSend => (tcx.lang_items.send_trait().unwrap(), - external_path(cx, "Send", None, vec![], &empty)), + external_path(cx, "Send", None, vec![], empty)), ty::BoundSized => (tcx.lang_items.sized_trait().unwrap(), - external_path(cx, "Sized", None, vec![], &empty)), + external_path(cx, "Sized", None, vec![], empty)), ty::BoundCopy => (tcx.lang_items.copy_trait().unwrap(), - external_path(cx, "Copy", None, vec![], &empty)), + external_path(cx, "Copy", None, vec![], empty)), ty::BoundSync => (tcx.lang_items.sync_trait().unwrap(), - external_path(cx, "Sync", None, vec![], &empty)), + external_path(cx, "Sync", None, vec![], empty)), }; inline::record_extern_fqn(cx, did, TypeTrait); TraitBound(PolyTrait { @@ -765,7 +765,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { } } -impl<'tcx> Clean>> for subst::Substs<'tcx> { +impl<'tcx> Clean>> for Substs<'tcx> { fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); v.extend(self.regions.as_full_slice().iter().filter_map(|r| r.clean(cx)) @@ -891,7 +891,7 @@ impl<'a> Clean for ty::Predicate<'a> { impl<'a> Clean for ty::TraitPredicate<'a> { fn clean(&self, cx: &DocContext) -> WherePredicate { WherePredicate::BoundPredicate { - ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(), + ty: self.trait_ref.self_ty().clean(cx), bounds: vec![self.trait_ref.clean(cx)] } } @@ -1353,7 +1353,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { predicates: self.predicates.predicates[method_start..].to_vec() }; - let generics = (&self.generics, &method_predicates, + let generics = (self.generics, &method_predicates, subst::FnSpace).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { @@ -2923,7 +2923,7 @@ impl<'tcx> Clean for ty::AssociatedType<'tcx> { // applied to this associated type in question. let def = cx.tcx().lookup_trait_def(did); let predicates = cx.tcx().lookup_predicates(did); - let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); + let generics = (def.generics, &predicates, subst::TypeSpace).clean(cx); generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate {