diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 218681efb7dc1..d15d51aed09a1 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -9,7 +9,6 @@ // except according to those terms. use hir::def_id::DefId; -use ty::subst::ParamSpace; use util::nodemap::NodeMap; use syntax::ast; use hir; @@ -31,7 +30,7 @@ pub enum Def { AssociatedTy(DefId /* trait */, DefId), Trait(DefId), PrimTy(hir::PrimTy), - TyParam(ParamSpace, u32, DefId, ast::Name), + TyParam(DefId), Upvar(DefId, // def id of closed over local ast::NodeId, // node id of closed over local usize, // index in the freevars list of the closure @@ -122,7 +121,7 @@ impl Def { match *self { Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) | Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) | - Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) | + Def::TyParam(id) | Def::Struct(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) | Def::Local(id, _) | Def::Upvar(id, _, _, _) => { id diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index b0dec3277a996..9a6375719c1bc 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -82,7 +82,6 @@ use hir::def::Def; use hir::def_id::DefId; use infer::{self, TypeOrigin}; use middle::region; -use ty::subst; use ty::{self, TyCtxt, TypeFoldable}; use ty::{Region, ReFree}; use ty::error::TypeError; @@ -1366,10 +1365,10 @@ 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; + generics.regions.len() as u32; let lifetimes = path.segments.last().unwrap().parameters.lifetimes(); let mut insert = Vec::new(); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 24fadc549fafc..1b65b5dae0748 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}; @@ -1172,15 +1170,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_var(self.next_ty_var_id(false)) } - pub fn next_ty_var_with_default(&self, - default: Option>) -> Ty<'tcx> { - let ty_var_id = self.type_variables - .borrow_mut() - .new_var(false, default); - - self.tcx.mk_var(ty_var_id) - } - pub fn next_diverging_ty_var(&self) -> Ty<'tcx> { self.tcx.mk_var(self.next_ty_var_id(true)) } @@ -1205,89 +1194,55 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::ReVar(self.region_vars.new_region_var(origin)) } - pub fn region_vars_for_defs(&self, - span: Span, - defs: &[ty::RegionParameterDef]) - -> Vec { - defs.iter() - .map(|d| self.next_region_var(EarlyBoundRegion(span, d.name))) - .collect() - } - - // We have to take `&mut Substs` in order to provide the correct substitutions for defaults - // along the way, for this reason we don't return them. - pub fn type_vars_for_defs(&self, + /// Create a region inference variable for the given + /// region parameter definition. + pub fn region_var_for_def(&self, span: Span, - space: subst::ParamSpace, - substs: &mut Substs<'tcx>, - defs: &[ty::TypeParameterDef<'tcx>]) { - - for def in defs.iter() { - let default = def.default.map(|default| { - type_variable::Default { - ty: default.subst_spanned(self.tcx, substs, Some(span)), - origin_span: span, - def_id: def.default_def_id - } - }); - - let ty_var = self.next_ty_var_with_default(default); - substs.types.push(space, ty_var); - } - } - - /// 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 type_params = subst::VecPerParamSpace::empty(); - - let region_params = - generics.regions.map( - |d| self.next_region_var(EarlyBoundRegion(span, d.name))); + def: &ty::RegionParameterDef) + -> ty::Region { + self.next_region_var(EarlyBoundRegion(span, def.name)) + } + + /// Create a type inference variable for the given + /// type parameter definition. The substitutions are + /// for actual parameters that may be referred to by + /// the default of this type parameter, if it exists. + /// E.g. `struct Foo(...);` when + /// used in a path such as `Foo::::new()` will + /// use an inference variable for `C` with `[T, U]` + /// as the substitutions for the default, `(T, U)`. + pub fn type_var_for_def(&self, + span: Span, + def: &ty::TypeParameterDef<'tcx>, + substs: &Substs<'tcx>) + -> Ty<'tcx> { + let default = def.default.map(|default| { + type_variable::Default { + ty: default.subst_spanned(self.tcx, substs, Some(span)), + origin_span: span, + def_id: def.default_def_id + } + }); - let mut substs = subst::Substs::new(type_params, region_params); - for space in subst::ParamSpace::all().iter() { - self.type_vars_for_defs( - span, - *space, - &mut substs, - generics.types.get_slice(*space)); - } + let ty_var_id = self.type_variables + .borrow_mut() + .new_var(false, default); - self.tcx.mk_substs(substs) + self.tcx.mk_var(ty_var_id) } - /// 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>) - -> subst::Substs<'tcx> - { - - assert!(generics.types.len(subst::SelfSpace) == 1); - assert!(generics.types.len(subst::FnSpace) == 0); - assert!(generics.regions.len(subst::SelfSpace) == 0); - assert!(generics.regions.len(subst::FnSpace) == 0); - - let type_params = Vec::new(); - - let region_param_defs = generics.regions.get_slice(subst::TypeSpace); - let regions = self.region_vars_for_defs(span, region_param_defs); - - let mut substs = subst::Substs::new_trait(type_params, regions, self_ty); - - let type_parameter_defs = generics.types.get_slice(subst::TypeSpace); - self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs); - - return substs; + /// 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_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) + }) } 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 481fd332404ba..abb22783ddc84 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 2b59e603cc897..2a8594c59a837 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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}; + let def = self.tcx.expect_def(id); + // 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), - _ => (), - }); + 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[0].sty { + TyEnum(tyid, _) | TyStruct(tyid, _) => { + self.check_def_id(tyid.did) + } + _ => {} + } + } + } + _ => {} + } - let def = self.tcx.expect_def(id); match def { Def::Const(_) | Def::AssociatedConst(..) => { self.check_def_id(def.def_id()); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 9ccca9e6a08f9..8369a6c39d54d 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -24,9 +24,7 @@ use session::Session; use hir::def::{Def, DefMap}; use hir::def_id::DefId; use middle::region; -use ty::subst; use ty; -use std::fmt; use std::mem::replace; use syntax::ast; use syntax::parse::token::keywords; @@ -41,8 +39,7 @@ use hir::intravisit::{self, Visitor, FnKind}; #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub enum DefRegion { DefStaticRegion, - DefEarlyBoundRegion(/* space */ subst::ParamSpace, - /* index */ u32, + DefEarlyBoundRegion(/* index */ u32, /* lifetime decl */ ast::NodeId), DefLateBoundRegion(ty::DebruijnIndex, /* lifetime decl */ ast::NodeId), @@ -90,10 +87,11 @@ struct LifetimeContext<'a, 'tcx: 'a> { labels_in_fn: Vec<(ast::Name, Span)>, } +#[derive(PartialEq, Debug)] enum ScopeChain<'a> { - /// EarlyScope(i, ['a, 'b, ...], s) extends s with early-bound - /// lifetimes, assigning indexes 'a => i, 'b => i+1, ... etc. - EarlyScope(subst::ParamSpace, &'a [hir::LifetimeDef], Scope<'a>), + /// EarlyScope(['a, 'b, ...], s) extends s with early-bound + /// lifetimes. + EarlyScope(&'a [hir::LifetimeDef], Scope<'a>), /// LateScope(['a, 'b, ...], s) extends s with late-bound /// lifetimes introduced by the declaration binder_id. LateScope(&'a [hir::LifetimeDef], Scope<'a>), @@ -159,8 +157,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { hir::ItemImpl(_, _, ref generics, _, _, _) => { // These kinds of items have only early bound lifetime parameters. let lifetimes = &generics.lifetimes; - let early_scope = EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE); - this.with(early_scope, |old_scope, this| { + this.with(EarlyScope(lifetimes, &ROOT_SCOPE), |old_scope, this| { this.check_lifetime_defs(old_scope, lifetimes); intravisit::walk_item(this, item); }); @@ -181,11 +178,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { self.with(RootScope, |_, this| { match item.node { hir::ForeignItemFn(ref decl, ref generics) => { - this.visit_early_late(item.id, - subst::FnSpace, - decl, - generics, - |this| { + this.visit_early_late(item.id, decl, generics, |this| { intravisit::walk_foreign_item(this, item); }) } @@ -203,14 +196,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { b: &'v hir::Block, s: Span, fn_id: ast::NodeId) { match fk { FnKind::ItemFn(_, generics, _, _, _, _, _) => { - self.visit_early_late(fn_id, subst::FnSpace, decl, generics, |this| { + self.visit_early_late(fn_id,decl, generics, |this| { this.add_scope_and_walk_fn(fk, decl, b, s, fn_id) }) } FnKind::Method(_, sig, _, _) => { self.visit_early_late( fn_id, - subst::FnSpace, decl, &sig.generics, |this| this.add_scope_and_walk_fn(fk, decl, b, s, fn_id)); @@ -263,7 +255,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for LifetimeContext<'a, 'tcx> { if let hir::MethodTraitItem(ref sig, None) = trait_item.node { self.visit_early_late( - trait_item.id, subst::FnSpace, + trait_item.id, &sig.decl, &sig.generics, |this| intravisit::walk_trait_item(this, trait_item)) } else { @@ -469,7 +461,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Block) { FnScope { s, .. } => { scope = s; } RootScope => { return; } - EarlyScope(_, lifetimes, s) | + EarlyScope(lifetimes, s) | LateScope(lifetimes, s) => { for lifetime_def in lifetimes { // FIXME (#24278): non-hygienic comparison @@ -557,7 +549,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// ordering is not important there. fn visit_early_late(&mut self, fn_id: ast::NodeId, - early_space: subst::ParamSpace, decl: &hir::FnDecl, generics: &hir::Generics, walk: F) where @@ -576,7 +567,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .partition(|l| self.map.late_bound.contains_key(&l.lifetime.id)); let this = self; - this.with(EarlyScope(early_space, &early, this.scope), move |old_scope, this| { + this.with(EarlyScope(&early, this.scope), move |old_scope, this| { this.with(LateScope(&late, this.scope), move |_, this| { this.check_lifetime_defs(old_scope, &generics.lifetimes); walk(this); @@ -606,11 +597,19 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break; } - EarlyScope(space, lifetimes, s) => { + EarlyScope(lifetimes, s) => { match search_lifetimes(lifetimes, lifetime_ref) { - Some((index, lifetime_def)) => { + Some((mut index, lifetime_def)) => { + // Adjust for nested early scopes, e.g. in methods. + let mut parent = s; + while let EarlyScope(lifetimes, s) = *parent { + index += lifetimes.len() as u32; + parent = s; + } + assert_eq!(*parent, RootScope); + let decl_id = lifetime_def.id; - let def = DefEarlyBoundRegion(space, index, decl_id); + let def = DefEarlyBoundRegion(index, decl_id); self.insert_lifetime(lifetime_ref, def); return; } @@ -672,7 +671,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break; } - EarlyScope(_, lifetimes, s) | + EarlyScope(lifetimes, s) | LateScope(lifetimes, s) => { search_result = search_lifetimes(lifetimes, lifetime_ref); if search_result.is_some() { @@ -768,7 +767,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { return; } - EarlyScope(_, lifetimes, s) | + EarlyScope(lifetimes, s) | LateScope(lifetimes, s) => { if let Some((_, lifetime_def)) = search_lifetimes(lifetimes, lifetime) { signal_shadowing_problem( @@ -963,14 +962,3 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap, } } } - -impl<'a> fmt::Debug for ScopeChain<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - EarlyScope(space, defs, _) => write!(fmt, "EarlyScope({:?}, {:?})", space, defs), - LateScope(defs, _) => write!(fmt, "LateScope({:?})", defs), - FnScope { fn_id, body_id, s: _ } => write!(fmt, "FnScope({:?}, {:?})", fn_id, body_id), - RootScope => write!(fmt, "RootScope"), - } - } -} diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 2bde3d6554fee..f511d820fac58 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/coherence.rs b/src/librustc/traits/coherence.rs index b38f5f96de448..a5a415dd27c65 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -14,7 +14,6 @@ use super::{SelectionContext, Obligation, ObligationCause}; use middle::cstore::LOCAL_CRATE; use hir::def_id::DefId; -use ty::subst::TypeSpace; use ty::{self, Ty, TyCtxt}; use infer::{InferCtxt, TypeOrigin}; use syntax_pos::DUMMY_SP; @@ -160,12 +159,9 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt, // First, create an ordered iterator over all the type parameters to the trait, with the self // type appearing first. - let input_tys = Some(trait_ref.self_ty()); - let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace)); - // Find the first input type that either references a type parameter OR // some local type. - for input_ty in input_tys { + for input_ty in trait_ref.input_types() { if ty_is_local(tcx, input_ty, infer_is_local) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); @@ -231,7 +227,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.is_fundamental(), ty::TyTrait(ref data) => - tcx.has_attr(data.principal_def_id(), "fundamental"), + tcx.has_attr(data.principal.def_id(), "fundamental"), _ => false } @@ -275,7 +271,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> } ty::TyTrait(ref tt) => { - tt.principal_def_id().is_local() + tt.principal.def_id().is_local() } ty::TyError => { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index cf004767b2aac..33db0053cda13 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -31,7 +31,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::ExpectedFound; use ty::fast_reject; use ty::fold::TypeFolder; -use ty::subst::{self, Subst, TypeSpace}; +use ty::subst::Subst; use util::nodemap::{FnvHashMap, FnvHashSet}; use std::cmp; @@ -167,29 +167,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }); } - fn impl_substs(&self, - did: DefId, - obligation: PredicateObligation<'tcx>) - -> subst::Substs<'tcx> { - let tcx = self.tcx; - - let ity = tcx.lookup_item_type(did); - let (tps, rps, _) = - (ity.generics.types.get_slice(TypeSpace), - ity.generics.regions.get_slice(TypeSpace), - ity.ty); - - let rps = self.region_vars_for_defs(obligation.cause.span, rps); - let mut substs = subst::Substs::new( - subst::VecPerParamSpace::empty(), - subst::VecPerParamSpace::new(rps, Vec::new(), Vec::new())); - self.type_vars_for_defs(obligation.cause.span, - TypeSpace, - &mut substs, - tps); - substs - } - fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// returns the fuzzy category of a given type, or None /// if the type can be equated to any type. @@ -244,18 +221,19 @@ 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 impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); let impl_trait_ref = tcx .impl_trait_ref(def_id) .unwrap() - .subst(tcx, &self.impl_substs(def_id, obligation.clone())); + .subst(tcx, impl_substs); let impl_self_ty = impl_trait_ref.self_ty(); if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) { self_match_impls.push(def_id); - if trait_ref.substs.types.get_slice(TypeSpace).iter() - .zip(impl_trait_ref.substs.types.get_slice(TypeSpace)) + if trait_ref.substs.types[1..].iter() + .zip(&impl_trait_ref.substs.types[1..]) .all(|(u,v)| self.fuzzy_match_tys(u, v)) { fuzzy_match_impls.push(def_id); @@ -293,14 +271,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let def = self.tcx.lookup_trait_def(trait_ref.def_id); let trait_str = def.trait_ref.to_string(); if let Some(ref istring) = item.value_str() { - let mut generic_map = def.generics.types.iter_enumerated() - .map(|(param, i, gen)| { - (gen.name.as_str().to_string(), - trait_ref.substs.types.get(param, i) - .to_string()) - }).collect::>(); - generic_map.insert("Self".to_string(), - trait_ref.self_ty().to_string()); + let generic_map = def.generics.types.iter().map(|param| { + (param.name.as_str().to_string(), + trait_ref.substs.type_for_def(param).to_string()) + }).collect::>(); let parser = Parser::new(&istring); let mut errored = false; let err: String = parser.filter_map(|p| { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 5ba7b914d6591..837e33b3e7fc2 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -142,7 +142,7 @@ impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> { // Auto trait obligations on `impl Trait`. if tcx.trait_has_default_impl(predicate.def_id()) { let substs = predicate.skip_binder().trait_ref.substs; - if substs.types.as_slice().len() == 1 && substs.regions.is_empty() { + if substs.types.len() == 1 && substs.regions.is_empty() { if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty { return true; } @@ -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 dc0807ba38fae..b86a54f01cf49 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 4889895860129..25d2df8fdedb3 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -20,7 +20,6 @@ use super::elaborate_predicates; use hir::def_id::DefId; -use ty::subst::{self, SelfSpace, TypeSpace}; use traits; use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use std::rc::Rc; @@ -146,10 +145,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match predicate { ty::Predicate::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.0.trait_ref.substs.types.get_slice(TypeSpace) - .iter() - .cloned() - .any(|t| t.has_self_ty()) + data.0.trait_ref.input_types()[1..].iter().any(|t| t.has_self_ty()) } ty::Predicate::Projection(..) | ty::Predicate::WellFormed(..) | @@ -166,25 +162,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.into_vec(); + 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 +205,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 +222,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; } @@ -274,7 +265,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // We can't monomorphize things like `fn foo(...)`. - if !method.generics.types.is_empty_in(subst::FnSpace) { + if !method.generics.types.is_empty() { return Some(MethodViolationCode::Generic); } @@ -330,7 +321,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty.maybe_walk(|ty| { match ty.sty { ty::TyParam(ref param_ty) => { - if param_ty.space == SelfSpace { + if param_ty.is_self() { error = true; } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index aed4f43932411..ea4fc1c25ab42 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -811,7 +811,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( // If so, extract what we know from the trait and try to come up with a good answer. let trait_predicates = selcx.tcx().lookup_predicates(def_id); let bounds = trait_predicates.instantiate(selcx.tcx(), substs); - let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec()); + let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates); assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, @@ -1133,10 +1133,9 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( object_ty) } }; - let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty); - let env_predicates = projection_bounds.iter() - .map(|p| p.to_predicate()) - .collect(); + let env_predicates = data.projection_bounds.iter().map(|p| { + p.with_self_ty(selcx.tcx(), object_ty).to_predicate() + }).collect(); let env_predicate = { let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index b61cb0d3eee72..9ea738bd326eb 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -36,12 +36,13 @@ use super::util; use hir::def_id::DefId; use infer; use infer::{InferCtxt, InferOk, TypeFreshener, TypeOrigin}; -use ty::subst::{Subst, Substs, TypeSpace}; +use ty::subst::{Subst, Substs}; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; 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; @@ -1214,7 +1215,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { bounds); let matching_bound = - util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec()) + util::elaborate_predicates(self.tcx(), bounds.predicates) .filter_to_traits() .find( |bound| self.probe( @@ -1528,7 +1529,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyTrait(ref data) => { match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { - if data.bounds.builtin_bounds.contains(&bound) { + if data.builtin_bounds.contains(&bound) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate"); candidates.vec.push(BuiltinObjectCandidate); @@ -1538,7 +1539,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => {} } - data.principal_trait_ref_with_self_ty(this.tcx(), self_ty) + data.principal.with_self_ty(this.tcx(), self_ty) } ty::TyInfer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -1602,7 +1603,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return; } }; - let target = obligation.predicate.0.input_types()[0]; + let target = obligation.predicate.skip_binder().input_types()[1]; debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})", source, target); @@ -1622,7 +1623,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // We always upcast when we can because of reason // #2 (region bounds). data_a.principal.def_id() == data_a.principal.def_id() && - data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) + data_a.builtin_bounds.is_superset(&data_b.builtin_bounds) } // T -> Trait. @@ -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.to_vec() } ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => { @@ -2179,10 +2180,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(ref data) => { // OK to skip the binder, it is reintroduced below - let input_types = data.principal.skip_binder().substs.types.get_slice(TypeSpace); - let assoc_types = data.bounds.projection_bounds - .iter() - .map(|pb| pb.skip_binder().ty); + let input_types = data.principal.skip_binder().input_types(); + let assoc_types = data.projection_bounds.iter() + .map(|pb| pb.skip_binder().ty); let all_types: Vec<_> = input_types.iter().cloned() .chain(assoc_types) .collect(); @@ -2315,7 +2315,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { ty::TyTrait(ref data) => { - data.principal_trait_ref_with_self_ty(self.tcx(), self_ty) + data.principal.with_self_ty(self.tcx(), self_ty) } _ => { span_bug!(obligation.cause.span, @@ -2476,7 +2476,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // regions here. See the comment there for more details. let source = self.infcx.shallow_resolve( tcx.no_late_bound_regions(&obligation.self_ty()).unwrap()); - let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]); + let target = obligation.predicate.skip_binder().input_types()[1]; + let target = self.infcx.shallow_resolve(target); debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})", source, target); @@ -2486,13 +2487,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => { // See assemble_candidates_for_unsizing for more info. - let bounds = ty::ExistentialBounds { - region_bound: data_b.bounds.region_bound, - builtin_bounds: data_b.bounds.builtin_bounds, - projection_bounds: data_a.bounds.projection_bounds.clone(), - }; - - let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds); + let new_trait = tcx.mk_trait(ty::TraitObject { + principal: data_a.principal, + region_bound: data_b.region_bound, + builtin_bounds: data_b.builtin_bounds, + projection_bounds: data_a.projection_bounds.clone(), + }); let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = self.infcx.sub_types(false, origin, new_trait, target) @@ -2503,8 +2503,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let cause = ObligationCause::new(obligation.cause.span, obligation.cause.body_id, ObjectCastObligation(target)); - let outlives = ty::OutlivesPredicate(data_a.bounds.region_bound, - data_b.bounds.region_bound); + let outlives = ty::OutlivesPredicate(data_a.region_bound, + data_b.region_bound); nested.push(Obligation::with_depth(cause, obligation.recursion_depth + 1, ty::Binder(outlives).to_predicate())); @@ -2512,12 +2512,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T -> Trait. (_, &ty::TyTrait(ref data)) => { - let mut object_dids = Some(data.principal_def_id()).into_iter(); + let mut object_dids = Some(data.principal.def_id()).into_iter(); // FIXME(#33243) -// data.bounds.builtin_bounds.iter().flat_map(|bound| { +// data.builtin_bounds.iter().flat_map(|bound| { // tcx.lang_items.from_builtin_kind(bound).ok() // }) -// .chain(Some(data.principal_def_id())); +// .chain(Some(data.principal.def_id())); if let Some(did) = object_dids.find(|did| { !tcx.is_object_safe(*did) }) { @@ -2534,10 +2534,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; // Create the obligation for casting from T to Trait. - push(data.principal_trait_ref_with_self_ty(tcx, source).to_predicate()); + push(data.principal.with_self_ty(tcx, source).to_predicate()); // We can only make objects from sized types. - let mut builtin_bounds = data.bounds.builtin_bounds; + let mut builtin_bounds = data.builtin_bounds; builtin_bounds.insert(ty::BoundSized); // Create additional obligations for all the various builtin @@ -2553,14 +2553,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // Create obligations for the projection predicates. - for bound in data.projection_bounds_with_self_ty(tcx, source) { - push(bound.to_predicate()); + for bound in &data.projection_bounds { + push(bound.with_self_ty(tcx, source).to_predicate()); } // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: - let outlives = ty::OutlivesPredicate(source, - data.bounds.region_bound); + let outlives = ty::OutlivesPredicate(source, data.region_bound); push(ty::Binder(outlives).to_predicate()); } @@ -2586,17 +2585,15 @@ 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()); + 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); } @@ -2604,12 +2601,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.iter().enumerate().map(|(i, ty)| { + if ty_params.contains(i) { + tcx.types.err + } else { + ty + } + }).collect(); + 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); } } @@ -2620,11 +2621,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.iter().enumerate().map(|(i, ty)| { + if ty_params.contains(i) { + substs_b.types[i] + } else { + ty + } + }).collect(); + 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) @@ -2693,12 +2698,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, @@ -2892,20 +2896,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // obligation will normalize to `<$0 as Iterator>::Item = $1` and // `$1: Copy`, so we must ensure the obligations are emitted in // that order. - let predicates = tcx - .lookup_predicates(def_id) - .predicates.iter() - .flat_map(|predicate| { - let predicate = - normalize_with_depth(self, cause.clone(), recursion_depth, - &predicate.subst(tcx, substs)); - predicate.obligations.into_iter().chain( - Some(Obligation { - cause: cause.clone(), - recursion_depth: recursion_depth, - predicate: predicate.value - })) - }).collect(); + let predicates = tcx.lookup_predicates(def_id); + assert_eq!(predicates.parent, None); + let predicates = predicates.predicates.iter().flat_map(|predicate| { + let predicate = normalize_with_depth(self, cause.clone(), recursion_depth, + &predicate.subst(tcx, substs)); + predicate.obligations.into_iter().chain( + Some(Obligation { + cause: cause.clone(), + recursion_depth: recursion_depth, + predicate: predicate.value + })) + }).collect(); self.infcx().plug_leaks(skol_map, snapshot, &predicates) } } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 38cccb9753df6..9acfe2754820c 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; @@ -44,11 +44,10 @@ pub struct OverlapError { /// When we have selected one impl, but are actually using item definitions from /// a parent impl providing a default, we need a way to translate between the /// type parameters of the two impls. Here the `source_impl` is the one we've -/// selected, and `source_substs` is a substitution of its generics (and -/// possibly some relevant `FnSpace` variables as well). And `target_node` is -/// the impl/trait we're actually going to get the definition from. The resulting -/// substitution will map from `target_node`'s generics to `source_impl`'s -/// generics as instantiated by `source_subst`. +/// selected, and `source_substs` is a substitution of its generics. +/// And `target_node` is the impl/trait we're actually going to get the +/// definition from. The resulting substitution will map from `target_node`'s +/// generics to `source_impl`'s generics as instantiated by `source_subst`. /// /// For example, consider the following scenario: /// @@ -101,7 +100,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 +140,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 +184,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 a47cd23c64aa6..13193e1b2d71b 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 818eb4eb2fb1e..1954ce1993c5e 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,20 +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 tcx = infcx.tcx; - let impl_generics = 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, @@ -402,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) => { @@ -422,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) } @@ -510,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 4056fb01aa2c2..3501dd4846087 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -23,13 +23,13 @@ use middle::free_region::FreeRegionMap; use middle::region::RegionMaps; use middle::resolve_lifetime; use middle::stability; -use ty::subst::{self, Substs}; +use ty::subst::Substs; use traits; use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants}; -use ty::{AdtDef, ClosureSubsts, ExistentialBounds, Region}; +use ty::{AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; -use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy}; +use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject}; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; @@ -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), @@ -1150,12 +1160,6 @@ impl_interners!('tcx, region: mk_region(Region, keep_local) -> Region ); -fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { - bounds.is_empty() || - bounds[1..].iter().enumerate().all( - |(index, bound)| bounds[index].sort_key() <= bound.sort_key()) -} - impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Create an unsafe fn ty based on a safe fn ty. pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { @@ -1288,18 +1292,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TyFnPtr(fty)) } - pub fn mk_trait(self, - principal: ty::PolyTraitRef<'tcx>, - bounds: ExistentialBounds<'tcx>) - -> Ty<'tcx> - { - assert!(bound_list_is_sorted(&bounds.projection_bounds)); - - let inner = box TraitTy { - principal: principal, - bounds: bounds - }; - self.mk_ty(TyTrait(inner)) + pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> { + obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())); + self.mk_ty(TyTrait(box obj)) } pub fn mk_projection(self, @@ -1351,18 +1346,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_param(self, - space: subst::ParamSpace, index: u32, name: Name) -> Ty<'tcx> { - self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name })) + self.mk_ty(TyParam(ParamTy { idx: index, name: name })) } pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_param(subst::SelfSpace, 0, keywords::SelfType.name()) + self.mk_param(0, keywords::SelfType.name()) } pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { - self.mk_param(def.space, def.index, def.name) + self.mk_param(def.index, def.name) } pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 42d5788568f1c..17f9b6c25995c 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -9,7 +9,6 @@ // except according to those terms. use hir::def_id::DefId; -use ty::subst; use infer::type_variable; use ty::{self, BoundRegion, Region, Ty, TyCtxt}; @@ -243,7 +242,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::TyFnDef(..) => format!("fn item"), ty::TyFnPtr(_) => "fn pointer".to_string(), ty::TyTrait(ref inner) => { - format!("trait {}", tcx.item_path_str(inner.principal_def_id())) + format!("trait {}", tcx.item_path_str(inner.principal.def_id())) } ty::TyStruct(def, _) => { format!("struct `{}`", tcx.item_path_str(def.did)) @@ -258,7 +257,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(), ty::TyProjection(_) => "associated type".to_string(), ty::TyParam(ref p) => { - if p.space == subst::SelfSpace { + if p.is_self() { "Self".to_string() } else { "type parameter".to_string() diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 9bf2daeb5f49b..f7472d611befe 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -61,7 +61,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType), ty::TyRawPtr(_) => Some(PtrSimplifiedType), ty::TyTrait(ref trait_info) => { - Some(TraitSimplifiedType(trait_info.principal_def_id())) + Some(TraitSimplifiedType(trait_info.principal.def_id())) } ty::TyStruct(def, _) => { Some(StructSimplifiedType(def.did)) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 0997d6c1a7562..c6c37296e9e12 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::Substs; use ty::{self, Ty, TypeFlags, TypeFoldable}; pub struct FlagComputation { @@ -77,7 +77,7 @@ impl FlagComputation { &ty::TyParam(ref p) => { self.add_flags(TypeFlags::HAS_LOCAL_NAMES); - if p.space == subst::SelfSpace { + if p.is_self() { self.add_flags(TypeFlags::HAS_SELF); } else { self.add_flags(TypeFlags::HAS_PARAMS); @@ -116,17 +116,16 @@ impl FlagComputation { self.add_substs(substs); } - &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { + &ty::TyTrait(ref obj) => { let mut computation = FlagComputation::new(); - computation.add_substs(principal.0.substs); - for projection_bound in &bounds.projection_bounds { + computation.add_substs(obj.principal.skip_binder().substs); + for projection_bound in &obj.projection_bounds { let mut proj_computation = FlagComputation::new(); - proj_computation.add_projection_predicate(&projection_bound.0); + proj_computation.add_existential_projection(&projection_bound.0); self.add_bound_computation(&proj_computation); } self.add_bound_computation(&computation); - - self.add_bounds(bounds); + self.add_region(obj.region_bound); } &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { @@ -199,23 +198,19 @@ impl FlagComputation { } } - fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) { - self.add_projection_ty(&projection_predicate.projection_ty); - self.add_ty(projection_predicate.ty); + fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { + self.add_substs(projection.trait_ref.substs); + self.add_ty(projection.ty); } fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { self.add_substs(projection_ty.trait_ref.substs); } - fn add_substs(&mut self, substs: &subst::Substs) { - self.add_tys(substs.types.as_slice()); + fn add_substs(&mut self, substs: &Substs) { + self.add_tys(&substs.types); for &r in &substs.regions { self.add_region(r); } } - - fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) { - self.add_region(bounds.region_bound); - } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 3eeff6ee5792f..2e114a801d6ed 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}; @@ -140,17 +140,13 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { t.super_fold_with(self) } - fn fold_trait_ref(&mut self, t: &ty::TraitRef<'tcx>) -> ty::TraitRef<'tcx> { - t.super_fold_with(self) - } - fn fold_impl_header(&mut self, imp: &ty::ImplHeader<'tcx>) -> ty::ImplHeader<'tcx> { imp.super_fold_with(self) } 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) } @@ -177,11 +173,6 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { r.super_fold_with(self) } - fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>) - -> ty::ExistentialBounds<'tcx> { - s.super_fold_with(self) - } - fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>) -> adjustment::AutoRef<'tcx> { ar.super_fold_with(self) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8ddd8bef36a6f..1dcc623d36558 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -322,7 +322,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => Some(adt_def.did), - ty::TyTrait(ref data) => Some(data.principal_def_id()), + ty::TyTrait(ref data) => Some(data.principal.def_id()), ty::TyArray(subty, _) | ty::TySlice(subty) | diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 57b1dd66bea9d..d5686906e6a7b 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 cfc2e89f9d5a1..1f747ddfb2959 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -28,7 +28,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use traits; use ty; -use ty::subst::{Subst, Substs, VecPerParamSpace}; +use ty::subst::{Subst, Substs}; use ty::walk::TypeWalker; use util::common::MemoizationMap; use util::nodemap::NodeSet; @@ -54,11 +54,13 @@ use hir::{ItemImpl, ItemTrait, PatKind}; use hir::intravisit::Visitor; pub use self::sty::{Binder, DebruijnIndex}; -pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds}; +pub use self::sty::{BuiltinBound, BuiltinBounds}; pub use self::sty::{BareFnTy, FnSig, PolyFnSig}; -pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitTy}; +pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject}; pub use self::sty::{ClosureSubsts, TypeAndMut}; pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; +pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; +pub use self::sty::{ExistentialProjection, PolyExistentialProjection}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::Issue32330; pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid}; @@ -171,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.into_vec(), - }.subst(tcx, &impl_substs); + predicates: tcx.lookup_predicates(impl_def_id).predicates + }.subst(tcx, impl_substs); let traits::Normalized { value: mut header, obligations } = traits::normalize(selcx, traits::ObligationCause::dummy(), &header); @@ -346,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, @@ -358,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, @@ -425,8 +426,17 @@ pub struct AssociatedType<'tcx> { #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)] pub struct ItemVariances { - pub types: VecPerParamSpace, - pub regions: VecPerParamSpace, + pub types: Vec, + pub regions: Vec, +} + +impl ItemVariances { + pub fn empty() -> ItemVariances { + ItemVariances { + types: vec![], + regions: vec![], + } + } } #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] @@ -442,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 @@ -713,7 +723,6 @@ pub enum ObjectLifetimeDefault { pub struct TypeParameterDef<'tcx> { pub name: Name, pub def_id: DefId, - pub space: subst::ParamSpace, pub index: u32, pub default_def_id: DefId, // for use in error reporing about defaults pub default: Option>, @@ -724,7 +733,6 @@ pub struct TypeParameterDef<'tcx> { pub struct RegionParameterDef { pub name: Name, pub def_id: DefId, - pub space: subst::ParamSpace, pub index: u32, pub bounds: Vec, } @@ -732,7 +740,6 @@ pub struct RegionParameterDef { impl RegionParameterDef { pub fn to_early_bound_region(&self) -> ty::Region { ty::ReEarlyBound(ty::EarlyBoundRegion { - space: self.space, index: self.index, name: self.name, }) @@ -747,59 +754,53 @@ impl RegionParameterDef { /// with an item or method. Analogous to hir::Generics. #[derive(Clone, Debug)] pub struct Generics<'tcx> { - pub types: VecPerParamSpace>, - pub regions: VecPerParamSpace, -} - -impl<'tcx> Generics<'tcx> { - pub fn empty() -> Generics<'tcx> { - Generics { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty(), - } - } - - pub fn is_empty(&self) -> bool { - self.types.is_empty() && self.regions.is_empty() - } - - pub fn has_type_params(&self, space: subst::ParamSpace) -> bool { - !self.types.is_empty_in(space) - } - - pub fn has_region_params(&self, space: subst::ParamSpace) -> bool { - !self.regions.is_empty_in(space) - } + pub parent: Option, + pub parent_regions: u32, + pub parent_types: u32, + pub regions: Vec, + pub types: Vec>, + pub has_self: bool, } /// Bounds on generics. #[derive(Clone)] pub struct GenericPredicates<'tcx> { - pub predicates: VecPerParamSpace>, + pub parent: Option, + pub predicates: Vec>, } impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { - pub fn empty() -> GenericPredicates<'tcx> { - GenericPredicates { - predicates: VecPerParamSpace::empty(), - } - } - pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) -> InstantiatedPredicates<'tcx> { + let mut instantiated = InstantiatedPredicates::empty(); + self.instantiate_into(tcx, &mut instantiated, substs); + instantiated + } + pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) + -> InstantiatedPredicates<'tcx> { InstantiatedPredicates { - predicates: self.predicates.subst(tcx, substs), + predicates: self.predicates.subst(tcx, substs) + } + } + + fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + instantiated: &mut InstantiatedPredicates<'tcx>, + substs: &Substs<'tcx>) { + if let Some(def_id) = self.parent { + tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs); } + instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs))) } pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, poly_trait_ref: &ty::PolyTraitRef<'tcx>) -> InstantiatedPredicates<'tcx> { + assert_eq!(self.parent, None); InstantiatedPredicates { - predicates: self.predicates.map(|pred| { + predicates: self.predicates.iter().map(|pred| { pred.subst_supertrait(tcx, poly_trait_ref) - }) + }).collect() } } } @@ -808,7 +809,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { pub enum Predicate<'tcx> { /// Corresponds to `where Foo : Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` - /// would be the parameters in the `TypeSpace`. + /// would be the type parameters. Trait(PolyTraitPredicate<'tcx>), /// A predicate created by RFC1592 @@ -833,9 +834,9 @@ pub enum Predicate<'tcx> { /// trait must be object-safe ObjectSafe(DefId), - /// No direct syntax. May be thought of as `where T : FnFoo<...>` for some 'TypeSpace' - /// substitutions `...` and T being a closure type. Satisfied (or refuted) once we know the - /// closure's kind. + /// No direct syntax. May be thought of as `where T : FnFoo<...>` + /// for some substitutions `...` and T being a closure type. + /// Satisfied (or refuted) once we know the closure's kind. ClosureKind(DefId, ClosureKind), } @@ -971,7 +972,7 @@ impl<'tcx> TraitPredicate<'tcx> { } pub fn input_types(&self) -> &[Ty<'tcx>] { - self.trait_ref.substs.types.as_slice() + &self.trait_ref.substs.types } pub fn self_ty(&self) -> Ty<'tcx> { @@ -1113,7 +1114,7 @@ impl<'tcx> Predicate<'tcx> { pub fn walk_tys(&self) -> IntoIter> { let vec: Vec<_> = match *self { ty::Predicate::Trait(ref data) => { - data.0.trait_ref.substs.types.as_slice().to_vec() + data.0.trait_ref.input_types().to_vec() } ty::Predicate::Rfc1592(ref data) => { return data.walk_tys() @@ -1128,7 +1129,7 @@ impl<'tcx> Predicate<'tcx> { vec![] } ty::Predicate::Projection(ref data) => { - let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice(); + let trait_inputs = data.0.projection_ty.trait_ref.input_types(); trait_inputs.iter() .cloned() .chain(Some(data.0.ty)) @@ -1193,12 +1194,12 @@ impl<'tcx> Predicate<'tcx> { /// [usize:Bar]]`. #[derive(Clone)] pub struct InstantiatedPredicates<'tcx> { - pub predicates: VecPerParamSpace>, + pub predicates: Vec>, } impl<'tcx> InstantiatedPredicates<'tcx> { pub fn empty() -> InstantiatedPredicates<'tcx> { - InstantiatedPredicates { predicates: VecPerParamSpace::empty() } + InstantiatedPredicates { predicates: vec![] } } pub fn is_empty(&self) -> bool { @@ -1212,7 +1213,7 @@ impl<'tcx> TraitRef<'tcx> { } pub fn self_ty(&self) -> Ty<'tcx> { - self.substs.self_ty().unwrap() + self.substs.types[0] } pub fn input_types(&self) -> &[Ty<'tcx>] { @@ -1220,7 +1221,7 @@ impl<'tcx> TraitRef<'tcx> { // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. - self.substs.types.as_slice() + &self.substs.types } } @@ -1286,23 +1287,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)) } _ => { @@ -1320,11 +1315,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) => { @@ -1334,8 +1326,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) @@ -1345,8 +1335,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { }; tcx.construct_parameter_environment( trait_item.span, - method_generics, - method_bounds, + method_ty.def_id, extent) } _ => { @@ -1363,13 +1352,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(..) | @@ -1379,20 +1365,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)) } _ => { @@ -1413,11 +1393,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) } _ => { @@ -1450,7 +1427,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>, } @@ -1905,9 +1882,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) { @@ -2158,7 +2133,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(), } @@ -2496,27 +2471,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 } } @@ -2545,6 +2529,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( @@ -2800,18 +2791,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 @@ -2825,18 +2816,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 } } @@ -2848,7 +2841,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 @@ -2860,30 +2853,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 mut types = VecPerParamSpace::empty(); - for def in generics.types.as_slice() { - debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", - def); - types.push(def.space, self.global_tcx().mk_param_from_def(def)); - } + pub fn construct_free_substs(self, def_id: DefId, + free_id_outlive: CodeExtent) + -> &'gcx Substs<'gcx> { - // map bound 'a => free 'a - let mut regions = VecPerParamSpace::empty(); - for def in generics.regions.as_slice() { - let region = - ReFree(FreeRegion { scope: free_id_outlive, - bound_region: def.to_bound_region() }); - debug!("push_region_params {:?}", region); - regions.push(def.space, region); - } + 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) + }); - Substs { - types: types, - regions: regions, - } + debug!("construct_parameter_environment: {:?}", substs); + substs } /// See `ParameterEnvironment` struct def'n for details. @@ -2891,8 +2875,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> { @@ -2900,16 +2883,17 @@ 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.into_vec(); + let predicates = bounds.predicates; // Finally, we have to normalize the bounds in the environment, in // case they contain any associated type projections. This process @@ -2925,7 +2909,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 05a9b8111570d..abf863f953664 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,21 @@ 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(); - - 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); - } - - 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 tcx = relation.tcx(); - Ok(relation.tcx().mk_substs(substs)) -} + let types = a_subst.types.iter().enumerate().map(|(i, a_ty)| { + let b_ty = &b_subst.types[i]; + let variance = variances.map_or(ty::Invariant, |v| v.types[i]); + relation.relate_with_variance(variance, a_ty, b_ty) + }).collect()?; -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 regions = a_subst.regions.iter().enumerate().map(|(i, a_r)| { + let b_r = &b_subst.regions[i]; + let variance = variances.map_or(ty::Invariant, |v| v.regions[i]); + relation.relate_with_variance(variance, a_r, b_r) + }).collect()?; - (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> { @@ -326,24 +265,33 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { } } -impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { +impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>) - -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> + a: &ty::ExistentialProjection<'tcx>, + b: &ty::ExistentialProjection<'tcx>) + -> RelateResult<'tcx, ty::ExistentialProjection<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - let projection_ty = relation.relate(&a.projection_ty, &b.projection_ty)?; - let ty = relation.relate(&a.ty, &b.ty)?; - Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) + if a.item_name != b.item_name { + Err(TypeError::ProjectionNameMismatched( + expected_found(relation, &a.item_name, &b.item_name))) + } else { + let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; + let ty = relation.relate(&a.ty, &b.ty)?; + Ok(ty::ExistentialProjection { + trait_ref: trait_ref, + item_name: a.item_name, + ty: ty + }) + } } } -impl<'tcx> Relate<'tcx> for Vec> { +impl<'tcx> Relate<'tcx> for Vec> { fn relate<'a, 'gcx, R>(relation: &mut R, - a: &Vec>, - b: &Vec>) - -> RelateResult<'tcx, Vec>> + a: &Vec>, + b: &Vec>) + -> RelateResult<'tcx, Vec>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { // To be compatible, `a` and `b` must be for precisely the @@ -361,27 +309,6 @@ impl<'tcx> Relate<'tcx> for Vec> { } } -impl<'tcx> Relate<'tcx> for ty::ExistentialBounds<'tcx> { - fn relate<'a, 'gcx, R>(relation: &mut R, - a: &ty::ExistentialBounds<'tcx>, - b: &ty::ExistentialBounds<'tcx>) - -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a - { - let r = - relation.with_cause( - Cause::ExistentialRegionBound, - |relation| relation.relate_with_variance(ty::Contravariant, - &a.region_bound, - &b.region_bound))?; - let nb = relation.relate(&a.builtin_bounds, &b.builtin_bounds)?; - let pb = relation.relate(&a.projection_bounds, &b.projection_bounds)?; - Ok(ty::ExistentialBounds { region_bound: r, - builtin_bounds: nb, - projection_bounds: pb }) - } -} - impl<'tcx> Relate<'tcx> for ty::BuiltinBounds { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::BuiltinBounds, @@ -416,6 +343,23 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { + fn relate<'a, 'gcx, R>(relation: &mut R, + a: &ty::ExistentialTraitRef<'tcx>, + b: &ty::ExistentialTraitRef<'tcx>) + -> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>> + where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a + { + // Different traits cannot be related + if a.def_id != b.def_id { + Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) + } else { + let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; + Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) + } + } +} + impl<'tcx> Relate<'tcx> for Ty<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &Ty<'tcx>, @@ -466,7 +410,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p)) - if a_p.idx == b_p.idx && a_p.space == b_p.space => + if a_p.idx == b_p.idx => { Ok(a) } @@ -478,11 +422,23 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_enum(a_def, substs)) } - (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) => + (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) => { - let principal = relation.relate(&a_.principal, &b_.principal)?; - let bounds = relation.relate(&a_.bounds, &b_.bounds)?; - Ok(tcx.mk_trait(principal, bounds)) + let principal = relation.relate(&a_obj.principal, &b_obj.principal)?; + let r = + relation.with_cause( + Cause::ExistentialRegionBound, + |relation| relation.relate_with_variance(ty::Contravariant, + &a_obj.region_bound, + &b_obj.region_bound))?; + let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?; + let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; + Ok(tcx.mk_trait(ty::TraitObject { + principal: principal, + region_bound: r, + builtin_bounds: nb, + projection_bounds: pb + })) } (&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs)) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 83413d16ffb3f..f7c4b9938c279 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -9,8 +9,8 @@ // except according to those terms. use infer::type_variable; -use ty::subst::{self, VecPerParamSpace}; -use ty::{self, Lift, TraitRef, Ty, TyCtxt}; +use ty::subst::Substs; +use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use std::rc::Rc; @@ -80,10 +80,20 @@ impl<'tcx> Lift<'tcx> for ty::Region { } } -impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> { - type Lifted = TraitRef<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - tcx.lift(&self.substs).map(|substs| TraitRef { +impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> { + type Lifted = ty::TraitRef<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + tcx.lift(&self.substs).map(|substs| ty::TraitRef { + def_id: self.def_id, + substs: substs + }) + } +} + +impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> { + type Lifted = ty::ExistentialTraitRef<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + tcx.lift(&self.substs).map(|substs| ty::ExistentialTraitRef { def_id: self.def_id, substs: substs }) @@ -141,6 +151,19 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> { } } +impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> { + type Lifted = ty::ExistentialProjection<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| { + ty::ExistentialProjection { + trait_ref: trait_ref, + item_name: self.item_name, + ty: ty + } + }) + } +} + impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> { type Lifted = ty::Predicate<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { @@ -427,26 +450,20 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for P<[T]> { } } -impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - self.map(|elem| elem.fold_with(folder)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.iter().any(|elem| elem.visit_with(visitor)) - } -} - -impl<'tcx> TypeFoldable<'tcx> for ty::TraitTy<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TraitTy { + ty::TraitObject { principal: self.principal.fold_with(folder), - bounds: self.bounds.fold_with(folder), + region_bound: self.region_bound.fold_with(folder), + builtin_bounds: self.builtin_bounds, + projection_bounds: self.projection_bounds.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.principal.visit_with(visitor) || self.bounds.visit_with(visitor) + self.principal.visit_with(visitor) || + self.region_bound.visit_with(visitor) || + self.projection_bounds.visit_with(visitor) } } @@ -599,8 +616,17 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> { } } - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_trait_ref(self) + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.substs.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + ty::ExistentialTraitRef { + def_id: self.def_id, + substs: self.substs.fold_with(folder), + } } fn super_visit_with>(&self, visitor: &mut V) -> bool { @@ -666,13 +692,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 { @@ -741,30 +765,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds { } } -impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::ExistentialBounds { - region_bound: self.region_bound.fold_with(folder), - builtin_bounds: self.builtin_bounds, - projection_bounds: self.projection_bounds.fold_with(folder), - } - } - - fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - folder.fold_existential_bounds(self) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.region_bound.visit_with(visitor) || self.projection_bounds.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TypeParameterDef { name: self.name, def_id: self.def_id, - space: self.space, index: self.index, default: self.default.fold_with(folder), default_def_id: self.default_def_id, @@ -805,7 +810,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef { ty::RegionParameterDef { name: self.name, def_id: self.def_id, - space: self.space, index: self.index, bounds: self.bounds.fold_with(folder), } @@ -816,31 +820,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef { } } -impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::Generics { - types: self.types.fold_with(folder), - regions: self.regions.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.types.visit_with(visitor) || self.regions.visit_with(visitor) - } -} - -impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::GenericPredicates { - predicates: self.predicates.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.predicates.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { @@ -893,6 +872,20 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + ty::ExistentialProjection { + trait_ref: self.trait_ref.fold_with(folder), + item_name: self.item_name, + ty: self.ty.fold_with(folder), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor) + } +} + impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ProjectionTy { @@ -986,19 +979,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 9680632ec4dcc..8aa81cc4743c9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -13,7 +13,7 @@ use middle::cstore; use hir::def_id::DefId; use middle::region; -use ty::subst::{self, Substs}; +use ty::subst::Substs; use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TyS, TypeFoldable}; use util::common::ErrorReported; @@ -152,7 +152,7 @@ pub enum TypeVariants<'tcx> { TyFnPtr(&'tcx BareFnTy<'tcx>), /// A trait, defined with `trait`. - TyTrait(Box>), + TyTrait(Box>), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -291,57 +291,11 @@ impl<'tcx> Decodable for ClosureSubsts<'tcx> { } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct TraitTy<'tcx> { - pub principal: ty::PolyTraitRef<'tcx>, - pub bounds: ExistentialBounds<'tcx>, -} - -impl<'a, 'gcx, 'tcx> TraitTy<'tcx> { - pub fn principal_def_id(&self) -> DefId { - self.principal.0.def_id - } - - /// 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 principal_trait_ref_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()); - - ty::Binder(TraitRef { - def_id: self.principal.0.def_id, - substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), - }) - } - - pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> Vec> - { - // otherwise the escaping regions would be captured by the binders - assert!(!self_ty.has_escaping_regions()); - - self.bounds.projection_bounds.iter() - .map(|in_poly_projection_predicate| { - let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; - let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); - let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, - substs); - let projection_ty = ty::ProjectionTy { - trait_ref: trait_ref, - item_name: in_projection_ty.item_name - }; - ty::Binder(ty::ProjectionPredicate { - projection_ty: projection_ty, - ty: in_poly_projection_predicate.0.ty - }) - }) - .collect() - } +pub struct TraitObject<'tcx> { + pub principal: PolyExistentialTraitRef<'tcx>, + pub region_bound: ty::Region, + pub builtin_bounds: BuiltinBounds, + pub projection_bounds: Vec>, } /// A complete reference to a trait. These take numerous guises in syntax, @@ -350,8 +304,8 @@ impl<'a, 'gcx, 'tcx> TraitTy<'tcx> { /// T : Foo /// /// This would be represented by a trait-reference where the def-id is the -/// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the -/// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`. +/// def-id for the trait `Foo` and the substs define `T` as parameter 0, +/// and `U` as parameter 1. /// /// Trait references also appear in object types like `Foo`, but in /// that case the `Self` parameter is absent from the substitutions. @@ -392,6 +346,42 @@ impl<'tcx> PolyTraitRef<'tcx> { } } +/// An existential reference to a trait, where `Self` is erased. +/// For example, the trait object `Trait<'a, 'b, X, Y>` is: +/// +/// exists T. T: Trait<'a, 'b, X, Y> +/// +/// The substitutions don't include the erased `Self`, only trait +/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct ExistentialTraitRef<'tcx> { + pub def_id: DefId, + pub substs: &'tcx Substs<'tcx>, +} + +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 + // trait-reference, but it should eventually exclude + // associated types. + &self.substs.types + } +} + +pub type PolyExistentialTraitRef<'tcx> = Binder>; + +impl<'tcx> PolyExistentialTraitRef<'tcx> { + pub fn def_id(&self) -> DefId { + self.0.def_id + } + + pub fn input_types(&self) -> &[Ty<'tcx>] { + // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> + self.0.input_types() + } +} + /// Binder is a binder for higher-ranked lifetimes. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` /// (which would be represented by the type `PolyTraitRef == @@ -508,33 +498,34 @@ impl<'tcx> PolyFnSig<'tcx> { #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct ParamTy { - pub space: subst::ParamSpace, pub idx: u32, pub name: Name, } impl<'a, 'gcx, 'tcx> ParamTy { - pub fn new(space: subst::ParamSpace, - index: u32, - name: Name) - -> ParamTy { - ParamTy { space: space, idx: index, name: name } + pub fn new(index: u32, name: Name) -> ParamTy { + ParamTy { idx: index, name: name } } pub fn for_self() -> ParamTy { - ParamTy::new(subst::SelfSpace, 0, keywords::SelfType.name()) + ParamTy::new(0, keywords::SelfType.name()) } pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { - ParamTy::new(def.space, def.index, def.name) + ParamTy::new(def.index, def.name) } pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { - tcx.mk_param(self.space, self.idx, self.name) + tcx.mk_param(self.idx, self.name) } pub fn is_self(&self) -> bool { - self.space == subst::SelfSpace && self.idx == 0 + if self.name == keywords::SelfType.name() { + assert_eq!(self.idx, 0); + true + } else { + false + } } } @@ -686,7 +677,6 @@ pub enum Region { #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub struct EarlyBoundRegion { - pub space: subst::ParamSpace, pub index: u32, pub name: Name, } @@ -730,27 +720,40 @@ pub enum InferTy { FreshFloatTy(u32) } -/// Bounds suitable for an existentially quantified type parameter -/// such as those that appear in object types or closure types. -#[derive(PartialEq, Eq, Hash, Clone)] -pub struct ExistentialBounds<'tcx> { - pub region_bound: ty::Region, - pub builtin_bounds: BuiltinBounds, - pub projection_bounds: Vec>, +/// A `ProjectionPredicate` for an `ExistentialTraitRef`. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct ExistentialProjection<'tcx> { + pub trait_ref: ExistentialTraitRef<'tcx>, + pub item_name: Name, + pub ty: Ty<'tcx> } -impl<'tcx> ExistentialBounds<'tcx> { - pub fn new(region_bound: ty::Region, - builtin_bounds: BuiltinBounds, - projection_bounds: Vec>) - -> Self { - let mut projection_bounds = projection_bounds; - projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())); - ExistentialBounds { - region_bound: region_bound, - builtin_bounds: builtin_bounds, - projection_bounds: projection_bounds - } +pub type PolyExistentialProjection<'tcx> = Binder>; + +impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { + pub fn item_name(&self) -> Name { + self.0.item_name // safe to skip the binder to access a name + } + + pub fn sort_key(&self) -> (DefId, Name) { + (self.0.trait_ref.def_id, self.0.item_name) + } + + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + self_ty: Ty<'tcx>) + -> ty::PolyProjectionPredicate<'tcx> + { + // otherwise the escaping regions would be captured by the binders + assert!(!self_ty.has_escaping_regions()); + + let trait_ref = self.map_bound(|proj| proj.trait_ref); + self.map_bound(|proj| ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref.with_self_ty(tcx, self_ty).0, + item_name: proj.item_name + }, + ty: proj.ty + }) } } @@ -942,16 +945,16 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_bool(&self) -> bool { self.sty == TyBool } - pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool { + pub fn is_param(&self, index: u32) -> bool { match self.sty { - ty::TyParam(ref data) => data.space == space && data.idx == index, + ty::TyParam(ref data) => data.idx == index, _ => false, } } pub fn is_self(&self) -> bool { match self.sty { - TyParam(ref p) => p.space == subst::SelfSpace, + TyParam(ref p) => p.is_self(), _ => false } } @@ -1185,7 +1188,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn ty_to_def_id(&self) -> Option { match self.sty { - TyTrait(ref tt) => Some(tt.principal_def_id()), + TyTrait(ref tt) => Some(tt.principal.def_id()), TyStruct(def, _) | TyEnum(def, _) => Some(def.did), TyClosure(id, _) => Some(id), @@ -1209,21 +1212,20 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { vec![*region] } TyTrait(ref obj) => { - let mut v = vec![obj.bounds.region_bound]; - v.extend_from_slice(obj.principal.skip_binder() - .substs.regions.as_slice()); + let mut v = vec![obj.region_bound]; + v.extend_from_slice(&obj.principal.skip_binder().substs.regions); v } TyEnum(_, substs) | TyStruct(_, substs) | TyAnon(_, substs) => { - substs.regions.as_slice().to_vec() + substs.regions.to_vec() } TyClosure(_, ref substs) => { - substs.func_substs.regions.as_slice().to_vec() + substs.func_substs.regions.to_vec() } TyProjection(ref data) => { - data.trait_ref.substs.regions.as_slice().to_vec() + data.trait_ref.substs.regions.to_vec() } TyFnDef(..) | TyFnPtr(_) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 595d965ffce26..e1a19a7b7992e 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -10,132 +10,127 @@ // Type substitutions. -pub use self::ParamSpace::*; - use middle::cstore; use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder}; use serialize::{Encodable, Encoder, Decodable, Decoder}; -use std::fmt; -use std::iter::IntoIterator; -use std::slice::Iter; -use std::vec::{Vec, IntoIter}; use syntax_pos::{Span, DUMMY_SP}; /////////////////////////////////////////////////////////////////////////// -/// A substitution mapping type/region parameters to new values. We -/// identify each in-scope parameter by an *index* and a *parameter -/// space* (which indices where the parameter is defined; see -/// `ParamSpace`). +/// A substitution mapping type/region parameters to new values. #[derive(Clone, PartialEq, Eq, Hash)] pub struct Substs<'tcx> { - pub types: VecPerParamSpace>, - pub regions: VecPerParamSpace, + pub types: Vec>, + pub regions: Vec, } impl<'a, 'gcx, 'tcx> Substs<'tcx> { - pub fn new(t: VecPerParamSpace>, - r: VecPerParamSpace) - -> Substs<'tcx> - { - Substs { types: t, regions: r } - } - - pub fn new_type(t: Vec>, - r: Vec) - -> Substs<'tcx> + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, + t: Vec>, + r: Vec) + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()), - VecPerParamSpace::new(r, Vec::new(), Vec::new())) + tcx.mk_substs(Substs { types: t, regions: r }) } - pub fn new_trait(t: Vec>, + pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>, + mut t: Vec>, r: Vec, s: Ty<'tcx>) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { - Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()), - VecPerParamSpace::new(r, Vec::new(), Vec::new())) - } - - pub fn empty() -> Substs<'tcx> { - Substs { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty(), - } - } + t.insert(0, s); + Substs::new(tcx, t, r) + } + + pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> { + Substs::new(tcx, vec![], vec![]) + } + + /// Creates a Substs for generic parameter definitions, + /// by calling closures to obtain each region and type. + /// 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 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 defs = tcx.lookup_generics(def_id); + let num_regions = defs.parent_regions as usize + defs.regions.len(); + let num_types = defs.parent_types as usize + defs.types.len(); + let mut substs = Substs { + regions: Vec::with_capacity(num_regions), + types: Vec::with_capacity(num_types) + }; - pub fn is_noop(&self) -> bool { - self.regions.is_empty() && self.types.is_empty() - } + substs.fill_item(tcx, defs, &mut mk_region, &mut mk_type); - pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> { - *self.types.get(ty_param_def.space, ty_param_def.index as usize) + Substs::new(tcx, substs.types, substs.regions) } - pub fn self_ty(&self) -> Option> { - self.types.get_self().cloned() - } + fn fill_item(&mut self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + defs: &ty::Generics<'tcx>, + mk_region: &mut FR, + mk_type: &mut FT) + where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region, + FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> { + if let Some(def_id) = defs.parent { + let parent_defs = tcx.lookup_generics(def_id); + self.fill_item(tcx, parent_defs, mk_region, mk_type); + } - 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 - } + for def in &defs.regions { + let region = mk_region(def, self); + assert_eq!(def.index as usize, self.regions.len()); + self.regions.push(region); + } - pub fn erase_regions(self) -> Substs<'tcx> { - let Substs { types, regions } = self; - let regions = regions.map(|_| ty::ReErased); - Substs { types: types, regions: regions } + for def in &defs.types { + let ty = mk_type(def, self); + assert_eq!(def.index as usize, self.types.len()); + self.types.push(ty); + } } - 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 is_noop(&self) -> bool { + self.regions.is_empty() && self.types.is_empty() } - 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 type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> { + self.types[ty_param_def.index as usize] } - 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 } + pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region { + self.regions[def.index as usize] } - /// 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 }) - } + /// 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); + let regions = target_substs.regions.iter() + .chain(&self.regions[defs.regions.len()..]).cloned().collect(); + let types = target_substs.types.iter() + .chain(&self.types[defs.types.len()..]).cloned().collect(); + 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); @@ -144,384 +139,16 @@ 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) } } -/////////////////////////////////////////////////////////////////////////// -// ParamSpace - -#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, - Clone, Hash, RustcEncodable, RustcDecodable, Debug)] -pub enum ParamSpace { - TypeSpace, // Type parameters attached to a type definition, trait, or impl - SelfSpace, // Self parameter on a trait - FnSpace, // Type parameters attached to a method or fn -} - -impl ParamSpace { - pub fn all() -> [ParamSpace; 3] { - [TypeSpace, SelfSpace, FnSpace] - } - - pub fn to_uint(self) -> usize { - match self { - TypeSpace => 0, - SelfSpace => 1, - FnSpace => 2, - } - } - - pub fn from_uint(u: usize) -> ParamSpace { - match u { - 0 => TypeSpace, - 1 => SelfSpace, - 2 => FnSpace, - _ => bug!("Invalid ParamSpace: {}", u) - } - } -} - -/// Vector of things sorted by param space. Used to keep -/// the set of things declared on the type, self, or method -/// distinct. -#[derive(PartialEq, Eq, Clone, Hash, RustcEncodable, RustcDecodable)] -pub struct VecPerParamSpace { - // This was originally represented as a tuple with one Vec for - // each variant of ParamSpace, and that remains the abstraction - // that it provides to its clients. - // - // Here is how the representation corresponds to the abstraction - // i.e. the "abstraction function" AF: - // - // AF(self) = (self.content[..self.type_limit], - // self.content[self.type_limit..self.self_limit], - // self.content[self.self_limit..]) - type_limit: usize, - self_limit: usize, - content: Vec, -} - -/// The `split` function converts one `VecPerParamSpace` into this -/// `SeparateVecsPerParamSpace` structure. -pub struct SeparateVecsPerParamSpace { - pub types: Vec, - pub selfs: Vec, - pub fns: Vec, -} - -impl fmt::Debug for VecPerParamSpace { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{:?};{:?};{:?}]", - self.get_slice(TypeSpace), - self.get_slice(SelfSpace), - self.get_slice(FnSpace)) - } -} - -impl VecPerParamSpace { - fn limits(&self, space: ParamSpace) -> (usize, usize) { - match space { - TypeSpace => (0, self.type_limit), - SelfSpace => (self.type_limit, self.self_limit), - FnSpace => (self.self_limit, self.content.len()), - } - } - - pub fn empty() -> VecPerParamSpace { - VecPerParamSpace { - type_limit: 0, - self_limit: 0, - content: Vec::new() - } - } - - /// `t` is the type space. - /// `s` is the self space. - /// `f` is the fn space. - pub fn new(t: Vec, s: Vec, f: Vec) -> VecPerParamSpace { - let type_limit = t.len(); - let self_limit = type_limit + s.len(); - - let mut content = t; - content.extend(s); - content.extend(f); - - VecPerParamSpace { - type_limit: type_limit, - self_limit: self_limit, - content: content, - } - } - - fn new_internal(content: Vec, type_limit: usize, self_limit: usize) - -> VecPerParamSpace - { - VecPerParamSpace { - type_limit: type_limit, - self_limit: self_limit, - content: content, - } - } - - /// 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 { - TypeSpace => { self.type_limit += 1; self.self_limit += 1; } - SelfSpace => { self.self_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 { - TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; } - SelfSpace => { self.self_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() - } - - pub fn is_empty_in(&self, space: ParamSpace) -> bool { - self.len(space) == 0 - } - - pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] { - let (start, limit) = self.limits(space); - &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] - } - - pub fn iter<'a>(&'a self) -> Iter<'a,T> { - self.content.iter() - } - - pub fn into_iter(self) -> IntoIter { - self.content.into_iter() - } - - pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> { - EnumeratedItems::new(self) - } - - pub fn as_slice(&self) -> &[T] { - &self.content - } - - pub fn into_vec(self) -> Vec { - self.content - } - - pub fn all_vecs

(&self, mut pred: P) -> bool where - P: FnMut(&[T]) -> bool, - { - let spaces = [TypeSpace, SelfSpace, FnSpace]; - spaces.iter().all(|&space| { pred(self.get_slice(space)) }) - } - - pub fn all

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { - self.iter().all(pred) - } - - pub fn any

(&self, pred: P) -> bool where P: FnMut(&T) -> bool { - self.iter().any(pred) - } - - pub fn is_empty(&self) -> bool { - self.all_vecs(|v| v.is_empty()) - } - - pub fn map(&self, pred: P) -> VecPerParamSpace where P: FnMut(&T) -> U { - let result = self.iter().map(pred).collect(); - VecPerParamSpace::new_internal(result, - self.type_limit, - self.self_limit) - } - - pub fn map_enumerated(&self, pred: P) -> VecPerParamSpace where - P: FnMut((ParamSpace, usize, &T)) -> U, - { - let result = self.iter_enumerated().map(pred).collect(); - VecPerParamSpace::new_internal(result, - self.type_limit, - self.self_limit) - } - - pub fn split(self) -> SeparateVecsPerParamSpace { - let VecPerParamSpace { type_limit, self_limit, content } = self; - - let mut content_iter = content.into_iter(); - - SeparateVecsPerParamSpace { - types: content_iter.by_ref().take(type_limit).collect(), - selfs: content_iter.by_ref().take(self_limit - type_limit).collect(), - fns: content_iter.collect() - } - } - - 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)] -pub struct EnumeratedItems<'a,T:'a> { - vec: &'a VecPerParamSpace, - space_index: usize, - elem_index: usize -} - -impl<'a,T> EnumeratedItems<'a,T> { - fn new(v: &'a VecPerParamSpace) -> EnumeratedItems<'a,T> { - let mut result = EnumeratedItems { vec: v, space_index: 0, elem_index: 0 }; - result.adjust_space(); - result - } - - fn adjust_space(&mut self) { - let spaces = ParamSpace::all(); - while - self.space_index < spaces.len() && - self.elem_index >= self.vec.len(spaces[self.space_index]) - { - self.space_index += 1; - self.elem_index = 0; - } - } -} - -impl<'a,T> Iterator for EnumeratedItems<'a,T> { - type Item = (ParamSpace, usize, &'a T); - - fn next(&mut self) -> Option<(ParamSpace, usize, &'a T)> { - let spaces = ParamSpace::all(); - if self.space_index < spaces.len() { - let space = spaces[self.space_index]; - let index = self.elem_index; - let item = self.vec.get(space, index); - - self.elem_index += 1; - self.adjust_space(); - - Some((space, index, item)) - } else { - None - } - } - - fn size_hint(&self) -> (usize, Option) { - let size = self.vec.as_slice().len(); - (size, Some(size)) - } -} - -impl IntoIterator for VecPerParamSpace { - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - self.into_vec().into_iter() - } -} - -impl<'a,T> IntoIterator for &'a VecPerParamSpace { - type Item = &'a T; - type IntoIter = Iter<'a, T>; - - fn into_iter(self) -> Iter<'a, T> { - self.as_slice().into_iter() - } -} - /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` @@ -596,7 +223,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(data.index as usize) { Some(&r) => { self.shift_region_through_binders(r) } @@ -606,10 +233,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> { span, "Region parameter out of range \ when substituting in region {} (root type={:?}) \ - (space={:?}, index={})", + (index={})", data.name, self.root_ty, - data.space, data.index); } } @@ -652,18 +278,17 @@ 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(p.idx as usize); let ty = match opt_ty { Some(t) => *t, None => { let span = self.span.unwrap_or(DUMMY_SP); span_bug!( span, - "Type parameter `{:?}` ({:?}/{:?}/{}) out of range \ + "Type parameter `{:?}` ({:?}/{}) out of range \ when substituting (root type={:?}) substs={:?}", p, source_ty, - p.space, p.idx, self.root_ty, self.substs); @@ -733,3 +358,60 @@ 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 defs = tcx.lookup_generics(trait_id); + let regions = substs.regions[..defs.regions.len()].to_vec(); + let types = substs.types[..defs.types.len()].to_vec(); + + 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(); + + types.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(); + + types.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 a76dfc35dc1d3..61285e8f8b0a5 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 d7bb8ff2995aa..51710c13a7dea 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}; @@ -451,21 +450,21 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { // to sort them again by the name, in string form. // Hash the whole principal trait ref. - self.def_id(data.principal_def_id()); + self.def_id(data.principal.def_id()); data.principal.visit_with(self); // Hash region and builtin bounds. - data.bounds.region_bound.visit_with(self); - self.hash(data.bounds.builtin_bounds); + data.region_bound.visit_with(self); + self.hash(data.builtin_bounds); // Only projection bounds are left, sort and hash them. - let mut projection_bounds: Vec<_> = data.bounds.projection_bounds + let mut projection_bounds: Vec<_> = data.projection_bounds .iter() .map(|b| (b.item_name().as_str(), b)) .collect(); projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); for (name, bound) in projection_bounds { - self.def_id(bound.0.projection_ty.trait_ref.def_id); + self.def_id(bound.0.trait_ref.def_id); self.hash(name); bound.visit_with(self); } @@ -477,7 +476,6 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { self.hash(tys.len()); } TyParam(p) => { - self.hash(p.space); self.hash(p.idx); self.hash(p.name.as_str()); } @@ -695,12 +693,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; + let types_b = &substs_b.types; - 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/ty/walk.rs b/src/librustc/ty/walk.rs index 9c1f9d9537a4f..8a9ee45351dfc 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -79,28 +79,28 @@ fn push_subtypes<'tcx>(stack: &mut Vec>, parent_ty: Ty<'tcx>) { stack.push(mt.ty); } ty::TyProjection(ref data) => { - push_reversed(stack, data.trait_ref.substs.types.as_slice()); + push_reversed(stack, &data.trait_ref.substs.types); } - ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - push_reversed(stack, principal.substs().types.as_slice()); - push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| { + ty::TyTrait(ref obj) => { + push_reversed(stack, obj.principal.input_types()); + push_reversed(stack, &obj.projection_bounds.iter().map(|pred| { pred.0.ty }).collect::>()); } ty::TyEnum(_, ref substs) | ty::TyStruct(_, ref substs) | ty::TyAnon(_, ref substs) => { - push_reversed(stack, substs.types.as_slice()); + push_reversed(stack, &substs.types); } ty::TyClosure(_, ref substs) => { - push_reversed(stack, substs.func_substs.types.as_slice()); + push_reversed(stack, &substs.func_substs.types); push_reversed(stack, &substs.upvar_tys); } ty::TyTuple(ref ts) => { push_reversed(stack, ts); } ty::TyFnDef(_, substs, ref ft) => { - push_reversed(stack, substs.types.as_slice()); + push_reversed(stack, &substs.types); push_sig_subtypes(stack, &ft.sig); } ty::TyFnPtr(ref ft) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index bfc2e11d9fbce..54b19362b1d86 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -261,7 +261,6 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); self.out.extend( trait_ref.substs.types - .as_slice() .iter() .filter(|ty| !ty.has_escaping_regions()) .map(|ty| traits::Obligation::new(cause.clone(), @@ -406,13 +405,13 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // FIXME(#33243): remove RFC1592 self.out.push(traits::Obligation::new( cause.clone(), - ty::Predicate::ObjectSafe(data.principal_def_id()) + ty::Predicate::ObjectSafe(data.principal.def_id()) )); let component_traits = - data.bounds.builtin_bounds.iter().flat_map(|bound| { + data.builtin_bounds.iter().flat_map(|bound| { tcx.lang_items.from_builtin_kind(bound).ok() }); -// .chain(Some(data.principal_def_id())); +// .chain(Some(data.principal.def_id())); self.out.extend( component_traits.map(|did| { traits::Obligation::new( cause.clone(), @@ -476,7 +475,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { .collect() } - fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) { + fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) { // Imagine a type like this: // // trait Foo { } @@ -512,10 +511,10 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { if !data.has_escaping_regions() { let implicit_bounds = object_region_bounds(self.infcx.tcx, - &data.principal, - data.bounds.builtin_bounds); + data.principal, + data.builtin_bounds); - let explicit_bound = data.bounds.region_bound; + let explicit_bound = data.region_bound; for implicit_bound in implicit_bounds { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); @@ -534,7 +533,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// `ty::required_region_bounds`, see that for more information. pub fn object_region_bounds<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - principal: &ty::PolyTraitRef<'tcx>, + principal: ty::PolyExistentialTraitRef<'tcx>, others: ty::BuiltinBounds) -> Vec { @@ -543,13 +542,8 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>( // a skolemized type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); - // Note that we preserve the overall binding levels here. - assert!(!open_ty.has_escaping_regions()); - let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty)); - let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs))); - let mut predicates = others.to_predicates(tcx, open_ty); - predicates.extend(trait_refs.iter().map(|t| t.to_predicate())); + predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate()); tcx.required_region_bounds(open_ty, predicates) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 896ef49de6f05..02ad8fb7033ed 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}; @@ -56,78 +56,75 @@ fn fn_sig(f: &mut fmt::Formatter, } /// Namespace of the path given to parameterized to print. -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Ns { Type, Value } -fn number_of_supplied_defaults<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - substs: &subst::Substs, - space: subst::ParamSpace, - 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) +pub fn parameterized(f: &mut fmt::Formatter, + substs: &subst::Substs, + did: DefId, + ns: Ns, + projections: &[ty::ProjectionPredicate]) + -> fmt::Result { + let mut verbose = false; + let mut num_supplied_defaults = 0; + let mut has_self = false; + let mut num_regions = 0; + let mut num_types = 0; + let mut item_name = None; + let fn_trait_kind = ty::tls::with(|tcx| { + let mut generics = tcx.lookup_generics(did); + let mut path_def_id = did; + verbose = tcx.sess.verbose(); + has_self = generics.has_self; + + if let Some(def_id) = generics.parent { + // Methods. + assert_eq!(ns, Ns::Value); + generics = tcx.lookup_generics(def_id); + num_regions = generics.regions.len(); + num_types = generics.types.len(); + + if has_self { + write!(f, "<{} as ", substs.types[0])?; + } + + item_name = Some(tcx.item_name(did)); + path_def_id = def_id; + } else { + if ns == Ns::Value { + // Functions. + assert_eq!(has_self, false); + } else { + // Types and traits. + num_regions = generics.regions.len(); + num_types = generics.types.len(); + } + } + + if !verbose { + if generics.types.last().map_or(false, |def| def.default.is_some()) { + if let Some(substs) = tcx.lift(&substs) { + let tps = &substs.types[..num_types]; + for (def, actual) in generics.types.iter().zip(tps).rev() { + if def.default.subst(tcx, substs) != Some(actual) { + break; + } + num_supplied_defaults += 1; } } - None => false } - }).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)?; - } + } - 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)))) - } else { - (did, None) - }; - write!(f, "{}", tcx.item_path_str(did))?; - Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose(), item_name)) + write!(f, "{}", tcx.item_path_str(path_def_id))?; + Ok(tcx.lang_items.fn_trait_kind(path_def_id)) })?; 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[1].sty { return fn_sig(f, args, false, projection_ty); } } @@ -170,23 +167,11 @@ pub fn parameterized(f: &mut fmt::Formatter, Ok(()) }; - print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?; - - let num_supplied_defaults = if verbose { - 0 - } else { - ty::tls::with(|tcx| { - if let Some(generics) = get_generics(tcx) { - number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics) - } else { - 0 - } - }) - }; + print_regions(f, "<", &substs.regions[..num_regions])?; - let tps = substs.types.get_slice(subst::TypeSpace); + let tps = &substs.types[..num_types]; - for &ty in &tps[..tps.len() - num_supplied_defaults] { + for &ty in &tps[has_self as usize..tps.len() - num_supplied_defaults] { start_or_continue(f, "<", ", ")?; write!(f, "{}", ty)?; } @@ -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 has_self { write!(f, ">")?; } @@ -212,10 +197,10 @@ pub fn parameterized(f: &mut fmt::Formatter, write!(f, "::{}", item_name)?; } - print_regions(f, "::<", substs.regions.get_slice(subst::FnSpace))?; + print_regions(f, "::<", &substs.regions[num_regions..])?; // FIXME: consider being smart with defaults here too - for ty in substs.types.get_slice(subst::FnSpace) { + for ty in &substs.types[num_types..] { start_or_continue(f, "::<", ", ")?; write!(f, "{}", ty)?; } @@ -288,7 +273,8 @@ 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::TraitRef<'tcx>, Vec>); +struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, + Vec>); impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { @@ -306,29 +292,32 @@ 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) } } -impl<'tcx> fmt::Display for ty::TraitTy<'tcx> { +impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let bounds = &self.bounds; - // 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"); - let projections = tcx.lift(&bounds.projection_bounds[..]) - .expect("could not lift projections for printing"); - let projections = projections.into_iter().map(|p| p.0).collect(); + // 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| { + 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)); in_binder(f, tcx, &ty::Binder(""), Some(tap)) })?; // Builtin bounds. - for bound in &bounds.builtin_bounds { + for bound in &self.builtin_bounds { write!(f, " + {:?}", bound)?; } @@ -337,7 +326,7 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> { // use thread-local data of some kind? There are also // advantages to just showing the region, since it makes // people aware that it's there. - let bound = bounds.region_bound.to_string(); + let bound = self.region_bound.to_string(); if !bound.is_empty() { write!(f, " + {}", bound)?; } @@ -348,19 +337,19 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> { impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TypeParameterDef({}, {:?}, {:?}/{})", + write!(f, "TypeParameterDef({}, {:?}, {})", self.name, self.def_id, - self.space, self.index) + self.index) } } impl fmt::Debug for ty::RegionParameterDef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RegionParameterDef({}, {:?}, {:?}/{}, {:?})", + write!(f, "RegionParameterDef({}, {:?}, {}, {:?})", self.name, self.def_id, - self.space, self.index, + self.index, self.bounds) } } @@ -379,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) @@ -397,10 +386,20 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { // when printing out the debug representation, we don't need // to enumerate the `for<...>` etc because the debruijn index // tells you everything you need to know. - match self.substs.self_ty() { - None => write!(f, "{}", *self), - Some(self_ty) => write!(f, "<{:?} as {}>", self_ty, *self) - } + write!(f, "<{:?} as {}>", self.self_ty(), *self) + } +} + +impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + 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, &[]) + }) } } @@ -448,11 +447,38 @@ impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> { } } -impl<'tcx> fmt::Debug for ty::TraitTy<'tcx> { +impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TraitTy({:?},{:?})", - self.principal, - self.bounds) + let mut empty = true; + let mut maybe_continue = |f: &mut fmt::Formatter| { + if empty { + empty = false; + Ok(()) + } else { + write!(f, " + ") + } + }; + + maybe_continue(f)?; + write!(f, "{:?}", self.principal)?; + + let region_str = format!("{:?}", self.region_bound); + if !region_str.is_empty() { + maybe_continue(f)?; + write!(f, "{}", region_str)?; + } + + for bound in &self.builtin_bounds { + maybe_continue(f)?; + write!(f, "{:?}", bound)?; + } + + for projection_bound in &self.projection_bounds { + maybe_continue(f)?; + write!(f, "{:?}", projection_bound)?; + } + + Ok(()) } } @@ -509,8 +535,7 @@ impl fmt::Debug for ty::Region { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ty::ReEarlyBound(ref data) => { - write!(f, "ReEarlyBound({:?}, {}, {})", - data.space, + write!(f, "ReEarlyBound({}, {})", data.index, data.name) } @@ -668,38 +693,6 @@ impl<'tcx> fmt::Display for ty::FnSig<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut empty = true; - let mut maybe_continue = |f: &mut fmt::Formatter| { - if empty { - empty = false; - Ok(()) - } else { - write!(f, " + ") - } - }; - - let region_str = format!("{:?}", self.region_bound); - if !region_str.is_empty() { - maybe_continue(f)?; - write!(f, "{}", region_str)?; - } - - for bound in &self.builtin_bounds { - maybe_continue(f)?; - write!(f, "{:?}", bound)?; - } - - for projection_bound in &self.projection_bounds { - maybe_continue(f)?; - write!(f, "{:?}", projection_bound)?; - } - - Ok(()) - } -} - impl fmt::Display for ty::BuiltinBounds { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut bounds = self.iter(); @@ -814,8 +807,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())) + parameterized(f, self.substs, self.def_id, Ns::Type, &[]) } } @@ -868,9 +860,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) => { @@ -893,12 +883,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, &[]) } }) } @@ -910,14 +895,14 @@ 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); let mut first = true; let mut is_sized = false; write!(f, "impl")?; - for predicate in bounds.predicates.into_vec() { + for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() { @@ -1034,7 +1019,7 @@ impl fmt::Display for ty::ParamTy { impl fmt::Debug for ty::ParamTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}/{:?}.{}", self, self.space, self.idx) + write!(f, "{}/#{}", self, self.idx) } } diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index f6e9484eda1a4..111646912ade3 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -16,7 +16,7 @@ use super::{drop_flag_effects_for_location, on_all_children_bits}; use super::{DropFlagState, MoveDataParamEnv}; use super::patch::MirPatch; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::subst::{Subst, Substs, VecPerParamSpace}; +use rustc::ty::subst::{Subst, Substs}; use rustc::mir::repr::*; use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::middle::const_val::ConstVal; @@ -859,10 +859,7 @@ 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( - VecPerParamSpace::new(vec![], vec![], vec![ty]), - VecPerParamSpace::new(vec![], vec![], vec![]) - )); + let substs = Substs::new(tcx, vec![ty], 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 73b54c4374ffb..d71add3258fbd 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 7711091685d38..32d0bbbfdb6b7 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -20,8 +20,7 @@ use rustc::middle::region::{self, CodeExtent}; 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}; @@ -276,19 +275,17 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { self.infcx.tcx.mk_tup(vec![ty1, ty2]) } - pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> { + pub fn t_param(&self, index: u32) -> Ty<'tcx> { let name = format!("T{}", index); - self.infcx.tcx.mk_param(space, index, token::intern(&name[..])) + self.infcx.tcx.mk_param(index, token::intern(&name[..])) } pub fn re_early_bound(&self, - space: subst::ParamSpace, index: u32, name: &'static str) -> ty::Region { let name = token::intern(name); ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: name, }) @@ -674,12 +671,12 @@ fn subst_ty_renumber_bound() { // t_source = fn(A) let t_source = { - let t_param = env.t_param(subst::TypeSpace, 0); + let t_param = env.t_param(0); 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(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 = { @@ -709,12 +706,12 @@ fn subst_ty_renumber_some_bounds() { // t_source = (A, fn(A)) let t_source = { - let t_param = env.t_param(subst::TypeSpace, 0); + let t_param = env.t_param(0); 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(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)) // @@ -755,7 +752,7 @@ fn escaping() { assert!(t_rptr_bound2.has_escaping_regions()); // t_fn = fn(A) - let t_param = env.t_param(subst::TypeSpace, 0); + let t_param = env.t_param(0); assert!(!t_param.has_escaping_regions()); let t_fn = env.t_fn(&[t_param], env.t_nil()); assert!(!t_fn.has_escaping_regions()); @@ -771,12 +768,12 @@ fn subst_region_renumber_region() { // type t_source<'a> = fn(&'a isize) let t_source = { - let re_early = env.re_early_bound(subst::TypeSpace, 0, "'a"); + let re_early = env.re_early_bound(0, "'a"); 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(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 ed17f3533d49f..61d927239828b 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 b8e66530ea153..1ef48e6d6565f 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; @@ -413,7 +413,7 @@ impl tr for Def { Def::AssociatedTy(trait_did, did) => Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)), Def::PrimTy(p) => Def::PrimTy(p), - Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n), + Def::TyParam(did) => Def::TyParam(did.tr(dcx)), Def::Upvar(_, nid1, index, nid2) => { let nid1 = dcx.tr_id(nid1); let nid2 = dcx.tr_id(nid2); @@ -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() @@ -524,16 +524,8 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) { 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_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]); - fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - predicate: &ty::Predicate<'tcx>); - fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - ty: &ty::TraitRef<'tcx>); fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, - substs: &subst::Substs<'tcx>); - fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, - bounds: &ty::ExistentialBounds<'tcx>); - fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds); + 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>); @@ -556,39 +548,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { ty))); } - fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) { - self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty))); - } - - fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - trait_ref: &ty::TraitRef<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor, - &ecx.ty_str_ctxt(), - *trait_ref))); - } - - fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, - predicate: &ty::Predicate<'tcx>) { - self.emit_opaque(|this| { - Ok(tyencode::enc_predicate(&mut this.cursor, - &ecx.ty_str_ctxt(), - predicate)) - }); - } - - fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>, - bounds: &ty::ExistentialBounds<'tcx>) { - self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor, - &ecx.ty_str_ctxt(), - bounds))); - } - - fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) { - self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor, - &ecx.ty_str_ctxt(), - bounds))); - } - fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture) { use rustc_serialize::Encoder; @@ -610,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))); @@ -879,10 +838,8 @@ trait rbml_decoder_decoder_helpers<'tcx> { -> ty::PolyTraitRef<'tcx>; fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) -> ty::Predicate<'tcx>; - fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) - -> ty::ExistentialBounds<'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>) @@ -902,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> { @@ -927,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( @@ -988,14 +945,8 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate()) } - fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) - -> ty::ExistentialBounds<'tcx> - { - self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds()) - } - 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)) @@ -1189,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 ff072cce5db96..99a3f3b00c8b0 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -196,20 +196,14 @@ 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_predicates: usize = 0x95; +// GAP 0x96 -pub const tag_item_generics: usize = 0x95; -pub const tag_method_ty_generics: usize = 0x96; - -pub const tag_type_predicate: usize = 0x97; -pub const tag_self_predicate: usize = 0x98; -pub const tag_fn_predicate: usize = 0x99; +pub const tag_predicate: usize = 0x97; +// GAP 0x98, 0x99 pub const tag_unsafety: usize = 0x9a; diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 2cdbd1b86012d..f6d698eb969d8 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 64b614b56e12f..5488f114db32f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -35,7 +35,6 @@ use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls}; use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex}; use middle::lang_items; -use rustc::ty::subst; use rustc::ty::{ImplContainer, TraitContainer}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind}; @@ -265,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, @@ -384,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); @@ -494,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); @@ -514,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); @@ -531,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, @@ -543,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 { @@ -961,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, @@ -1394,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, @@ -1406,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 } } @@ -1538,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, }; @@ -1574,31 +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 types = subst::VecPerParamSpace::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(); - types.push(bd.space, bd); - } - - let mut regions = subst::VecPerParamSpace::empty(); - 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(); - regions.push(bd.space, bd); - } - - ty::Generics { types: types, regions: regions } + 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, @@ -1622,21 +1590,12 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, { let doc = reader::get_doc(base_doc, tag); - let mut predicates = subst::VecPerParamSpace::empty(); - for predicate_doc in reader::tagged_docs(doc, tag_type_predicate) { - predicates.push(subst::TypeSpace, - doc_predicate(cdata, predicate_doc, tcx)); - } - for predicate_doc in reader::tagged_docs(doc, tag_self_predicate) { - predicates.push(subst::SelfSpace, - doc_predicate(cdata, predicate_doc, tcx)); - } - for predicate_doc in reader::tagged_docs(doc, tag_fn_predicate) { - predicates.push(subst::FnSpace, - doc_predicate(cdata, predicate_doc, tcx)); + ty::GenericPredicates { + parent: item_parent_item(cdata, doc), + predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| { + doc_predicate(cdata, predicate_doc, tcx) + }).collect() } - - ty::GenericPredicates { predicates: predicates } } pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index cc1d07b33c7e8..320ba3c8d9dc8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -26,7 +26,6 @@ use rustc::hir::def; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use middle::dependency_format::Linkage; use rustc::dep_graph::{DepGraph, DepNode, DepTask}; -use rustc::ty::subst; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::util::IntTypeExt; @@ -176,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); } @@ -511,56 +509,29 @@ 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 { - 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 { - 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 (space, _, predicate) in predicates.predicates.iter_enumerated() { - let tag = match space { - subst::TypeSpace => tag_type_predicate, - subst::SelfSpace => tag_self_predicate, - subst::FnSpace => tag_fn_predicate - }; - - rbml_w.wr_tagged_u32(tag, - 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); + if let Some(def_id) = predicates.parent { + rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id)); + } + for predicate in &predicates.predicates { + rbml_w.wr_tagged_u32(tag_predicate, + index.add_xref(XRef::Predicate(predicate.clone()))); + } rbml_w.end_tag(); } @@ -571,8 +542,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 { @@ -653,9 +623,9 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, if let Some(impl_item) = impl_item_opt { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { encode_attributes(rbml_w, &impl_item.attrs); - let scheme = ecx.tcx.lookup_item_type(m.def_id); - let any_types = !scheme.generics.types.is_empty(); - let needs_inline = any_types || is_default_impl || + let generics = ecx.tcx.lookup_generics(m.def_id); + let types = generics.parent_types as usize + generics.types.len(); + let needs_inline = types > 0 || is_default_impl || attr::requests_inline(&impl_item.attrs); if needs_inline || sig.constness == hir::Constness::Const { encode_inlined_item(ecx, @@ -702,7 +672,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); } @@ -1141,9 +1111,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 23142ca80ef0e..6e78cbcd28e73 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 7b4919bb4773b..c76cf23639237 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::Substs; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rbml; @@ -129,24 +128,48 @@ 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() { - assert_eq!(self.next(), '['); - while self.peek() != ']' { - r.push(space, f(self)); - } - assert_eq!(self.next(), ']'); + pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> { + let mut regions = vec![]; + let mut types = vec![]; + assert_eq!(self.next(), '['); + while self.peek() != '|' { + regions.push(self.parse_region()); + } + assert_eq!(self.next(), '|'); + while self.peek() != ']' { + types.push(self.parse_ty()); } - r + assert_eq!(self.next(), ']'); + + Substs::new(self.tcx, types, regions) } - pub fn parse_substs(&mut self) -> subst::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 } + pub fn parse_generics(&mut self) -> &'tcx ty::Generics<'tcx> { + let parent = self.parse_opt(|this| this.parse_def()); + let parent_regions = self.parse_u32(); + assert_eq!(self.next(), '|'); + let parent_types = self.parse_u32(); + + let mut regions = vec![]; + let mut types = vec![]; + assert_eq!(self.next(), '['); + while self.peek() != '|' { + regions.push(self.parse_region_param_def()); + } + assert_eq!(self.next(), '|'); + while self.peek() != ']' { + types.push(self.parse_type_param_def()); + } + assert_eq!(self.next(), ']'); + + self.tcx.alloc_generics(ty::Generics { + parent: parent, + parent_regions: parent_regions, + parent_types: parent_types, + regions: regions, + types: types, + has_self: self.next() == 'S' + }) } fn parse_bound_region(&mut self) -> ty::BoundRegion { @@ -196,13 +219,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } 'B' => { assert_eq!(self.next(), '['); - let space = self.parse_param_space(); - assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let name = token::intern(&self.parse_str(']')); ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: name }) @@ -302,9 +322,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> { + ty::ExistentialTraitRef { + def_id: self.parse_def(), + substs: self.parse_substs() + } } pub fn parse_ty(&mut self) -> Ty<'tcx> { @@ -336,23 +364,41 @@ 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(), '['); - let trait_ref = ty::Binder(self.parse_trait_ref()); - let bounds = self.parse_existential_bounds(); + let trait_ref = ty::Binder(self.parse_existential_trait_ref()); + let builtin_bounds = self.parse_builtin_bounds(); + let region_bound = self.parse_region(); + let mut projection_bounds = Vec::new(); + + loop { + match self.next() { + 'P' => { + let bound = self.parse_existential_projection(); + projection_bounds.push(ty::Binder(bound)); + } + '.' => { break; } + c => { + bug!("parse_bounds: bad bounds ('{}')", c) + } + } + } assert_eq!(self.next(), ']'); - return tcx.mk_trait(trait_ref, bounds); + return tcx.mk_trait(ty::TraitObject { + principal: trait_ref, + region_bound: region_bound, + builtin_bounds: builtin_bounds, + projection_bounds: projection_bounds + }); } 'p' => { assert_eq!(self.next(), '['); let index = self.parse_u32(); assert_eq!(self.next(), '|'); - let space = self.parse_param_space(); - assert_eq!(self.next(), '|'); let name = token::intern(&self.parse_str(']')); - return tcx.mk_param(space, index, name); + return tcx.mk_param(index, name); } '~' => return tcx.mk_box(self.parse_ty()), '*' => return tcx.mk_ptr(self.parse_mt()), @@ -380,7 +426,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' => { @@ -426,7 +472,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(), '['); @@ -438,7 +484,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(), '['); @@ -451,7 +497,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; @@ -495,10 +541,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { m } - fn parse_param_space(&mut self) -> subst::ParamSpace { - subst::ParamSpace::from_uint(self.parse_uint()) - } - fn parse_abi_set(&mut self) -> abi::Abi { assert_eq!(self.next(), '['); let bytes = self.scan(|c| c == ']'); @@ -588,11 +630,17 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> { + fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> { + ty::ExistentialProjection { + trait_ref: self.parse_existential_trait_ref(), + item_name: token::intern(&self.parse_str('|')), + ty: self.parse_ty(), + } + } + + 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(); - assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let default_def_id = self.parse_def(); @@ -602,7 +650,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { ty::TypeParameterDef { name: name, def_id: def_id, - space: space, index: index, default_def_id: default_def_id, default: default, @@ -610,11 +657,9 @@ 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(); - assert_eq!(self.next(), '|'); let index = self.parse_u32(); assert_eq!(self.next(), '|'); let mut bounds = vec![]; @@ -630,7 +675,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { ty::RegionParameterDef { name: name, def_id: def_id, - space: space, index: index, bounds: bounds, } @@ -649,27 +693,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { } } - pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> { - let builtin_bounds = self.parse_builtin_bounds(); - let region_bound = self.parse_region(); - let mut projection_bounds = Vec::new(); - - loop { - match self.next() { - 'P' => { - projection_bounds.push(ty::Binder(self.parse_projection_predicate())); - } - '.' => { break; } - c => { - bug!("parse_bounds: bad bounds ('{}')", c) - } - } - } - - ty::ExistentialBounds::new( - region_bound, builtin_bounds, projection_bounds) - } - fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds { let mut builtin_bounds = ty::BuiltinBounds::empty(); loop { diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 15bafcdd3c99e..90fd8a0eb2f65 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -19,9 +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::ParamTy; +use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FnvHashMap; @@ -104,11 +102,26 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx enc_substs(w, cx, substs); write!(w, "]"); } - ty::TyTrait(box ty::TraitTy { ref principal, - ref bounds }) => { + ty::TyTrait(ref obj) => { write!(w, "x["); - enc_trait_ref(w, cx, principal.0); - enc_existential_bounds(w, cx, bounds); + enc_existential_trait_ref(w, cx, obj.principal.0); + enc_builtin_bounds(w, cx, &obj.builtin_bounds); + + enc_region(w, cx, obj.region_bound); + + // Encode projection_bounds in a stable order + let mut projection_bounds: Vec<_> = obj.projection_bounds + .iter() + .map(|b| (b.item_name().as_str(), b)) + .collect(); + projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); + + for tp in projection_bounds.iter().map(|&(_, tp)| tp) { + write!(w, "P"); + enc_existential_projection(w, cx, &tp.0); + } + + write!(w, "."); write!(w, "]"); } ty::TyTuple(ts) => { @@ -149,8 +162,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx ty::TyInfer(_) => { bug!("cannot encode inference variable types"); } - ty::TyParam(ParamTy {space, idx, name}) => { - write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name); + ty::TyParam(p) => { + write!(w, "p[{}|{}]", p.idx, p.name); } ty::TyStruct(def, substs) => { write!(w, "a[{}|", (cx.ds)(cx.tcx, def.did)); @@ -235,27 +248,42 @@ fn enc_opt(w: &mut Cursor>, t: Option, enc_f: F) where } } -fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - v: &VecPerParamSpace, - mut op: F) where - F: FnMut(&mut Cursor>, &ctxt<'a, 'tcx>, &T), -{ - for &space in &subst::ParamSpace::all() { - write!(w, "["); - for t in v.get_slice(space) { - op(w, cx, t); - } - write!(w, "]"); +pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + substs: &Substs<'tcx>) { + write!(w, "["); + for &r in &substs.regions { + enc_region(w, cx, r); + } + write!(w, "|"); + for &ty in &substs.types { + enc_ty(w, cx, ty); } + write!(w, "]"); } -pub fn enc_substs<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, - substs: &subst::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_opt(w, generics.parent, |w, def_id| { + write!(w, "{}|", (cx.ds)(cx.tcx, def_id)); + }); + write!(w, "{}|{}[", + generics.parent_regions, + generics.parent_types); + + for r in &generics.regions { + enc_region_param_def(w, cx, r) + } + write!(w, "|"); + for t in &generics.types { + enc_type_param_def(w, cx, t); + } + write!(w, "]"); + + if generics.has_self { + write!(w, "S"); + } else { + write!(w, "N"); + } } pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { @@ -266,8 +294,7 @@ pub fn enc_region(w: &mut Cursor>, cx: &ctxt, r: ty::Region) { write!(w, "]"); } ty::ReEarlyBound(ref data) => { - write!(w, "B[{}|{}|{}]", - data.space.to_uint(), + write!(w, "B[{}|{}]", data.index, data.name); } @@ -344,6 +371,12 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, enc_substs(w, cx, s.substs); } +fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, + s: ty::ExistentialTraitRef<'tcx>) { + write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id)); + enc_substs(w, cx, s.substs); +} + fn enc_unsafety(w: &mut Cursor>, p: hir::Unsafety) { match p { hir::Unsafety::Normal => write!(w, "n"), @@ -386,7 +419,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor>, cx: &ctxt<'a, 'tcx>, enc_ty(w, cx, fsig.0.output); } -pub fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { +fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinBounds) { for bound in bs { match bound { ty::BoundSend => write!(w, "S"), @@ -399,42 +432,19 @@ pub fn enc_builtin_bounds(w: &mut Cursor>, _cx: &ctxt, bs: &ty::BuiltinB write!(w, "."); } -pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor>, - cx: &ctxt<'a,'tcx>, - bs: &ty::ExistentialBounds<'tcx>) { - enc_builtin_bounds(w, cx, &bs.builtin_bounds); - - enc_region(w, cx, bs.region_bound); - - // Encode projection_bounds in a stable order - let mut projection_bounds: Vec<_> = bs.projection_bounds - .iter() - .map(|b| (b.item_name().as_str(), b)) - .collect(); - projection_bounds.sort_by_key(|&(ref name, _)| name.clone()); - - for tp in projection_bounds.iter().map(|&(_, tp)| tp) { - write!(w, "P"); - enc_projection_predicate(w, cx, &tp.0); - } - - write!(w, "."); -} - -pub 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)); +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.index, (cx.ds)(cx.tcx, v.default_def_id)); enc_opt(w, v.default, |w, t| enc_ty(w, cx, t)); enc_object_lifetime_default(w, cx, v.object_lifetime_default); } -pub 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); +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.index); for &r in &v.bounds { write!(w, "R"); enc_region(w, cx, r); @@ -489,7 +499,9 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, } ty::Predicate::Projection(ty::Binder(ref data)) => { write!(w, "p"); - enc_projection_predicate(w, cx, data); + enc_trait_ref(w, cx, data.projection_ty.trait_ref); + write!(w, "{}|", data.projection_ty.item_name); + enc_ty(w, cx, data.ty); } ty::Predicate::WellFormed(data) => { write!(w, "w"); @@ -509,10 +521,10 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor>, } } -fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor>, - cx: &ctxt<'a, 'tcx>, - data: &ty::ProjectionPredicate<'tcx>) { - enc_trait_ref(w, cx, data.projection_ty.trait_ref); - write!(w, "{}|", data.projection_ty.item_name); +fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor>, + cx: &ctxt<'a, 'tcx>, + data: &ty::ExistentialProjection<'tcx>) { + enc_existential_trait_ref(w, cx, data.trait_ref); + write!(w, "{}|", data.item_name); enc_ty(w, cx, data.ty); } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index cae9e8379897c..5e4053a82ad8a 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -89,7 +89,7 @@ should go to. use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary, ScopeId}; use rustc::middle::region::{CodeExtent, CodeExtentData}; use rustc::middle::lang_items; -use rustc::ty::subst::{Substs, Subst, VecPerParamSpace}; +use rustc::ty::subst::{Substs, Subst}; use rustc::ty::{Ty, TyCtxt}; use rustc::mir::repr::*; use syntax_pos::Span; @@ -750,10 +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( - VecPerParamSpace::new(vec![], vec![], vec![data.item_ty]), - VecPerParamSpace::new(vec![], vec![], vec![]) - )); + let substs = Substs::new(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 df1fec75939b5..972e7f5be7075 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_resolve/lib.rs b/src/librustc_resolve/lib.rs index 962509be324de..65e14eee4bc2b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -49,7 +49,6 @@ use rustc::lint; use rustc::hir::def::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::ty; -use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; @@ -557,7 +556,7 @@ impl<'a> Visitor for Resolver<'a> { fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { let type_parameters = match foreign_item.node { ForeignItemKind::Fn(_, ref generics) => { - HasTypeParameters(generics, FnSpace, ItemRibKind) + HasTypeParameters(generics, ItemRibKind) } ForeignItemKind::Static(..) => NoTypeParameters, }; @@ -625,10 +624,6 @@ enum TypeParameters<'a, 'b> { HasTypeParameters(// Type parameters. &'b Generics, - // Identifies the things that these parameters - // were declared on (type, fn, etc) - ParamSpace, - // The kind of the rib used for type parameters. RibKind<'a>), } @@ -1613,12 +1608,9 @@ impl<'a> Resolver<'a> { match item.node { ItemKind::Enum(_, ref generics) | ItemKind::Ty(_, ref generics) | - ItemKind::Struct(_, ref generics) => { - self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind), - |this| visit::walk_item(this, item)); - } + ItemKind::Struct(_, ref generics) | ItemKind::Fn(_, _, _, _, ref generics, _) => { - self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind), + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| visit::walk_item(this, item)); } @@ -1634,10 +1626,7 @@ impl<'a> Resolver<'a> { ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => { // Create a new rib for the trait-wide type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - ItemRibKind), - |this| { + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { let local_def_id = this.definitions.local_def_id(item.id); this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); @@ -1660,7 +1649,6 @@ impl<'a> Resolver<'a> { TraitItemKind::Method(ref sig, _) => { let type_parameters = HasTypeParameters(&sig.generics, - FnSpace, MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_trait_item(this, trait_item) @@ -1729,10 +1717,10 @@ impl<'a> Resolver<'a> { where F: FnOnce(&mut Resolver) { match type_parameters { - HasTypeParameters(generics, space, rib_kind) => { + HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = HashSet::new(); - for (index, type_parameter) in generics.ty_params.iter().enumerate() { + for type_parameter in &generics.ty_params { let name = type_parameter.ident.name; debug!("with_type_parameter_rib: {}", type_parameter.id); @@ -1745,7 +1733,7 @@ impl<'a> Resolver<'a> { // plain insert (no renaming) let def_id = self.definitions.local_def_id(type_parameter.id); - let def = Def::TyParam(space, index as u32, def_id, name); + let def = Def::TyParam(def_id); function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def); self.record_def(type_parameter.id, PathResolution::new(def)); } @@ -1917,10 +1905,7 @@ impl<'a> Resolver<'a> { item_id: NodeId, impl_items: &[ImplItem]) { // If applicable, create a rib for the type parameters. - self.with_type_parameter_rib(HasTypeParameters(generics, - TypeSpace, - ItemRibKind), - |this| { + self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| { // Resolve the type parameters. this.visit_generics(generics); @@ -1953,7 +1938,6 @@ impl<'a> Resolver<'a> { // specific type parameters. let type_parameters = HasTypeParameters(&sig.generics, - FnSpace, MethodRibKind(!sig.decl.has_self())); this.with_type_parameter_rib(type_parameters, |this| { visit::walk_impl_item(this, impl_item); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 16cd9186ce9bb..db535e22f194d 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)); } @@ -491,7 +490,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Def::Enum(def_id) | Def::TyAlias(def_id) | Def::Trait(def_id) | - Def::TyParam(_, _, def_id, _) => { + Def::TyParam(def_id) => { Some(Data::TypeRefData(TypeRefData { span: sub_span.unwrap(), ref_id: Some(def_id), diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs index 27a8c1f1df476..d6866b27f98a5 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 23c4258caf7bd..d48ec98a20dfb 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/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 5e2c0805c2ea3..25a1479c28948 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -252,7 +252,7 @@ impl<'a, 'tcx> Instance<'tcx> { // and should not matter anyhow. let instance_ty = scx.tcx().erase_regions(&instance_ty.ty); - let hash = get_symbol_hash(scx, &def_path, instance_ty, substs.types.as_slice()); + let hash = get_symbol_hash(scx, &def_path, instance_ty, &substs.types); let mut buffer = SymbolPathBuffer { names: Vec::with_capacity(def_path.data.len()) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c78cda75e820e..f190fbeb6feb9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -39,7 +39,7 @@ use rustc::cfg; use rustc::hir::def_id::DefId; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; use rustc::hir::pat_util::simple_name; -use rustc::ty::subst::{self, Substs}; +use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::adjustment::CustomCoerceUnsized; @@ -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)) @@ -562,14 +562,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, // change to the vtable. old_info.expect("unsized_info: missing old info for trait upcast") } - (_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => { - // Note that we preserve binding levels here: - let substs = principal.0.substs.with_self_ty(source).erase_regions(); - let substs = ccx.tcx().mk_substs(substs); - let trait_ref = ty::Binder(ty::TraitRef { - def_id: principal.def_id(), - substs: substs, - }); + (_, &ty::TyTrait(ref data)) => { + let trait_ref = data.principal.with_self_ty(ccx.tcx(), source); + let trait_ref = ccx.tcx().erase_regions(&trait_ref); consts::ptrcast(meth::get_vtable(ccx, trait_ref), Type::vtable_ptr(ccx)) } @@ -675,14 +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(subst::VecPerParamSpace::new(vec![target_ty], - vec![source_ty], - Vec::new()), - subst::VecPerParamSpace::empty()); - 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) { @@ -1418,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)); @@ -2183,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 = @@ -2480,8 +2470,8 @@ pub fn filter_reachable_ids(tcx: TyCtxt, reachable: NodeSet) -> NodeSet { hir_map::NodeImplItem(&hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => { let def_id = tcx.map.local_def_id(id); - let scheme = tcx.lookup_item_type(def_id); - scheme.generics.types.is_empty() + let generics = tcx.lookup_generics(def_id); + generics.parent_types == 0 && generics.types.is_empty() } _ => false diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index aaec2a47025a2..d50959b5ab302 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 acc302430aee6..76910304eebb0 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -195,7 +195,7 @@ use rustc::hir::map as hir_map; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem}; use rustc::traits; -use rustc::ty::subst::{self, Substs, Subst}; +use rustc::ty::subst::{Substs, Subst}; use rustc::ty::{self, TypeFoldable, TyCtxt}; use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::mir::repr as mir; @@ -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)) } @@ -1055,8 +1042,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); if let ty::TyTrait(ref trait_ty) = trait_ty.sty { - let poly_trait_ref = trait_ty.principal_trait_ref_with_self_ty(scx.tcx(), - impl_ty); + let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty); // Walk all methods of the trait, including those of its supertraits for trait_ref in traits::supertraits(scx.tcx(), poly_trait_ref) { @@ -1077,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 } @@ -1233,38 +1219,41 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id_to_string(tcx, impl_def_id)); if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { - let default_impls = tcx.provided_trait_methods(trait_ref.def_id); let callee_substs = tcx.erase_regions(&trait_ref.substs); let overridden_methods: FnvHashSet<_> = items.iter() .map(|item| item.name) .collect(); - for default_impl in default_impls { - if overridden_methods.contains(&default_impl.name) { + for method in tcx.provided_trait_methods(trait_ref.def_id) { + if overridden_methods.contains(&method.name) { continue; } - if default_impl.generics.has_type_params(subst::FnSpace) { + if !method.generics.types.is_empty() { continue; } // 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, - default_impl.name); + impl_def_id, + impl_substs, + method.name); assert!(mth.is_provided); let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); - if !normalize_and_test_predicates(tcx, predicates.into_vec()) { + if !normalize_and_test_predicates(tcx, predicates) { continue; } - if can_have_local_instance(tcx, default_impl.def_id) { + if can_have_local_instance(tcx, method.def_id) { let empty_substs = tcx.erase_regions(&mth.substs); let item = create_fn_trans_item(tcx, - default_impl.def_id, + method.def_id, callee_substs, empty_substs); output.push(item); diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 79cf77cd9d35d..b1aaea7d984c9 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 3ecba3691d279..0e9898896778c 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 65eea1bbb6337..c31dbf8943e08 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 8845f124218bc..8b3a8a2bfccfb 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 3fe8b2b66791a..f505efb1ab2f9 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; if !tps.is_empty() { output.push('<'); @@ -627,7 +627,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // But it does not describe the trait's methods. let def_id = match trait_type.sty { - ty::TyTrait(ref data) => data.principal_def_id(), + ty::TyTrait(ref data) => data.principal.def_id(), _ => { bug!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {:?}", @@ -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 d6a4ce3c43a4e..1ee000992b9c5 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, @@ -358,7 +358,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to: &mut String) -> DIArray { - let actual_types = param_substs.types.as_slice(); + let actual_types = ¶m_substs.types; if actual_types.is_empty() { return create_DIArray(DIB(cx), &[]); @@ -381,10 +381,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Again, only create type information if full debuginfo is enabled let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo { - generics.types.as_slice().iter().enumerate().map(|(i, param)| { - let actual_type = cx.tcx().normalize_associated_type(&actual_types[i]); + let names = get_type_parameter_names(cx, generics); + actual_types.iter().zip(names).map(|(ty, name)| { + let actual_type = cx.tcx().normalize_associated_type(ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); - let name = CString::new(param.name.as_str().as_bytes()).unwrap(); + let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), @@ -403,6 +404,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, return create_DIArray(DIB(cx), &template_params[..]); } + fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + generics: &ty::Generics<'tcx>) + -> Vec { + let mut names = generics.parent.map_or(vec![], |def_id| { + get_type_parameter_names(cx, cx.tcx().lookup_generics(def_id)) + }); + names.extend(generics.types.iter().map(|param| param.name)); + names + } + fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>, instance: Instance<'tcx>) -> (DIScope, Span) { diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 73b1c828663e1..2a996ca75a37e 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 6c894ddad1a94..beb589c80bfc5 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 93e5f4ba1e205..080844782f205 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 7be173d17b487..ecee470551059 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::Substs; use abi::{Abi, FnType}; use adt; use base::*; @@ -137,8 +136,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, callee::ArgExprs(arg_exprs) => { assert_eq!(arg_exprs.len(), 1); - let (in_type, out_type) = (*substs.types.get(FnSpace, 0), - *substs.types.get(FnSpace, 1)); + let (in_type, out_type) = (substs.types[0], + substs.types[1]); let llintype = type_of::type_of(ccx, in_type); let llouttype = type_of::type_of(ccx, out_type); @@ -347,12 +346,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Call(bcx, llfn, &[], call_debug_location) } (_, "size_of") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); C_uint(ccx, machine::llsize_of_alloc(ccx, lltp_ty)) } (_, "size_of_val") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_sized(tcx, tp_ty) { let (llsize, _) = glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); @@ -363,11 +362,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } (_, "min_align_of") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; C_uint(ccx, type_of::align_of(ccx, tp_ty)) } (_, "min_align_of_val") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_sized(tcx, tp_ty) { let (_, llalign) = glue::size_and_align_of_dst(&bcx.build(), tp_ty, llargs[1]); @@ -377,12 +376,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } } (_, "pref_align_of") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty)) } (_, "drop_in_place") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let ptr = if type_is_sized(tcx, tp_ty) { llargs[0] } else { @@ -396,22 +395,22 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) } (_, "type_name") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let ty_name = token::intern_and_get_ident(&tp_ty.to_string()); C_str_slice(ccx, ty_name) } (_, "type_id") => { - C_u64(ccx, ccx.tcx().type_id_hash(*substs.types.get(FnSpace, 0))) + C_u64(ccx, ccx.tcx().type_id_hash(substs.types[0])) } (_, "init_dropped") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_zero_size(ccx, tp_ty) { drop_done_fill_mem(bcx, llresult, tp_ty); } C_nil(ccx) } (_, "init") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if !type_is_zero_size(ccx, tp_ty) { // Just zero out the stack slot. (See comment on base::memzero for explanation) init_zero_mem(bcx, llresult, tp_ty); @@ -423,7 +422,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) } (_, "needs_drop") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty)) } @@ -442,7 +441,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, false, false, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[1], llargs[0], llargs[2], @@ -452,7 +451,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, true, false, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[1], llargs[0], llargs[2], @@ -461,7 +460,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "write_bytes") => { memset_intrinsic(bcx, false, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], @@ -472,7 +471,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, false, true, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], @@ -482,7 +481,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, copy_intrinsic(bcx, true, true, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], @@ -491,14 +490,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, (_, "volatile_set_memory") => { memset_intrinsic(bcx, true, - *substs.types.get(FnSpace, 0), + substs.types[0], llargs[0], llargs[1], llargs[2], call_debug_location) } (_, "volatile_load") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; let mut ptr = llargs[0]; if let Some(ty) = fn_ty.ret.cast { ptr = PointerCast(bcx, ptr, ty.ptr_to()); @@ -510,7 +509,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, to_immediate(bcx, load, tp_ty) }, (_, "volatile_store") => { - let tp_ty = *substs.types.get(FnSpace, 0); + let tp_ty = substs.types[0]; if type_is_fat_ptr(bcx.tcx(), tp_ty) { VolatileStore(bcx, llargs[1], expr::get_dataptr(bcx, llargs[0])); VolatileStore(bcx, llargs[2], expr::get_meta(bcx, llargs[0])); @@ -610,10 +609,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }, (_, "discriminant_value") => { - let val_ty = substs.types.get(FnSpace, 0); + let val_ty = substs.types[0]; match val_ty.sty { ty::TyEnum(..) => { - let repr = adt::represent_type(ccx, *val_ty); + let repr = adt::represent_type(ccx, val_ty); adt::trans_get_discr(bcx, &repr, llargs[0], Some(llret_ty), true) } @@ -664,7 +663,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, match split[1] { "cxchg" | "cxchgweak" => { - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { let weak = if split[1] == "cxchgweak" { llvm::True } else { llvm::False }; let val = AtomicCmpXchg(bcx, llargs[0], llargs[1], llargs[2], @@ -683,7 +682,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "load" => { - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { AtomicLoad(bcx, llargs[0], order) } else { @@ -696,7 +695,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } "store" => { - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { AtomicStore(bcx, llargs[1], llargs[0], order); } else { @@ -735,7 +734,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, _ => ccx.sess().fatal("unknown atomic operation") }; - let sty = &substs.types.get(FnSpace, 0).sty; + let sty = &substs.types[0].sty; if int_type_width_signed(sty, ccx).is_some() { AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order) } else { @@ -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 3d6093d4d6960..b051028ebda6b 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); @@ -289,7 +286,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // try and trans it, in that case. Issue #23435. if mth.is_provided { let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs); - if !normalize_and_test_predicates(tcx, predicates.into_vec()) { + if !normalize_and_test_predicates(tcx, predicates) { debug!("get_vtable_methods: predicates do not hold"); return None; } @@ -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 31fee560fe369..4da973bb7f946 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 e9aacaa0f954f..d1837883aaeb0 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 ade6e8abeb32a..87d0ea0fe81f3 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -486,7 +486,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[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 90058f0b8329a..580882e31dd60 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; 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) }, }; @@ -476,10 +475,10 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, output.push(']'); }, ty::TyTrait(ref trait_data) => { - push_item_name(tcx, trait_data.principal.skip_binder().def_id, output); + push_item_name(tcx, trait_data.principal.def_id(), output); push_type_params(tcx, &trait_data.principal.skip_binder().substs.types, - &trait_data.bounds.projection_bounds, + &trait_data.projection_bounds, output); }, ty::TyFnDef(_, _, &ty::BareFnTy{ unsafety, abi, ref sig } ) | @@ -561,8 +560,8 @@ fn push_item_name(tcx: TyCtxt, } fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - types: &'tcx subst::VecPerParamSpace>, - projections: &[ty::PolyProjectionPredicate<'tcx>], + types: &[Ty<'tcx>], + projections: &[ty::PolyExistentialProjection<'tcx>], output: &mut String) { if types.is_empty() && projections.is_empty() { return; @@ -577,7 +576,7 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for projection in projections { let projection = projection.skip_binder(); - let name = &projection.projection_ty.item_name.as_str(); + let name = &projection.item_name.as_str(); output.push_str(name); output.push_str("="); push_unique_type_name(tcx, projection.ty, output); diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index e6794149fcb3b..6862002ed83b2 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,18 +256,13 @@ 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 name = llvm_type_name(cx, def.did, tps); + let name = llvm_type_name(cx, def.did, &substs.types); adt::incomplete_type_of(cx, &repr, &name[..]) } ty::TyClosure(..) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. let repr = adt::represent_type(cx, t); - // Unboxed closures can have substitutions in all spaces - // inherited from their environment, so we use entire - // contents of the VecPerParamSpace to construct the llvm - // name adt::incomplete_type_of(cx, &repr, "closure") } @@ -336,8 +330,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 name = llvm_type_name(cx, def.did, tps); + let name = llvm_type_name(cx, def.did, &substs.types); adt::incomplete_type_of(cx, &repr, &name[..]) } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ed67c9fbe30be..f6984f42cab34 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -55,8 +55,7 @@ use hir::def_id::DefId; use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; -use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}; -use rustc::ty::subst::VecPerParamSpace; +use rustc::ty::subst::{Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -82,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. @@ -116,11 +119,15 @@ pub trait AstConv<'gcx, 'tcx> { fn get_free_substs(&self) -> Option<&Substs<'tcx>>; /// What type should we use when a type is omitted? - fn ty_infer(&self, - param_and_substs: Option>, - substs: Option<&mut Substs<'tcx>>, - space: Option, - span: Span) -> Ty<'tcx>; + fn ty_infer(&self, span: Span) -> Ty<'tcx>; + + /// Same as ty_infer, but with a known type parameter definition. + fn ty_infer_for_def(&self, + _def: &ty::TypeParameterDef<'tcx>, + _substs: &Substs<'tcx>, + span: Span) -> Ty<'tcx> { + self.ty_infer(span) + } /// Projecting an associated type from a (potentially) /// higher-ranked trait reference is more complicated, because of @@ -166,6 +173,11 @@ struct ConvertedBinding<'tcx> { type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec>); +/// Dummy type used for the `Self` of a `TraitRef` created for converting +/// a trait object, and which gets removed in `ExistentialTraitRef`. +/// This type must not appear anywhere in other converted types. +const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::FreshTy(0)); + pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime) -> ty::Region { let r = match tcx.named_region_map.defs.get(&lifetime.id) { @@ -195,9 +207,8 @@ pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime) issue_32330)) } - Some(&rl::DefEarlyBoundRegion(space, index, _)) => { + Some(&rl::DefEarlyBoundRegion(index, _)) => { ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: lifetime.name }) @@ -340,66 +351,87 @@ 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) - -> Substs<'tcx> + -> &'tcx Substs<'tcx> { let tcx = self.tcx(); - // ast_path_substs() is only called to convert paths that are - // known to refer to traits, types, or structs. In these cases, - // all type parameters defined for the item being referenced will - // be in the TypeSpace or SelfSpace. - // - // Note: in the case of traits, the self parameter is also - // defined, but we don't currently create a `type_param_def` for - // `Self` because it is implicit. - assert!(decl_generics.regions.all(|d| d.space == TypeSpace)); - assert!(decl_generics.types.all(|d| d.space != FnSpace)); - - let (regions, types, assoc_bindings) = match item_segment.parameters { - hir::AngleBracketedParameters(ref data) => { - self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data) - } + match item_segment.parameters { + hir::AngleBracketedParameters(_) => {} hir::ParenthesizedParameters(..) => { struct_span_err!(tcx.sess, span, E0214, "parenthesized parameters may only be used with a trait") .span_label(span, &format!("only traits may use parentheses")) .emit(); - let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - (Substs::empty(), - ty_param_defs.iter().map(|_| tcx.types.err).collect(), - vec![]) + return Substs::for_item(tcx, def_id, |_, _| { + ty::ReStatic + }, |_, _| { + tcx.types.err + }); } - }; + } + + let (substs, assoc_bindings) = + self.create_substs_for_ast_path(rscope, + span, + param_mode, + def_id, + &item_segment.parameters, + None); assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span)); - self.create_substs_for_ast_path(span, - param_mode, - decl_generics, - None, - types, - regions) + substs } - fn create_region_substs(&self, + /// Given the type/region arguments provided to some path (along with + /// an implicit Self, if this is a trait reference) returns the complete + /// set of substitutions. This may involve applying defaulted type parameters. + /// + /// Note that the type listing given here is *exactly* what the user provided. + fn create_substs_for_ast_path(&self, rscope: &RegionScope, span: Span, - decl_generics: &ty::Generics<'tcx>, - regions_provided: Vec) - -> Substs<'tcx> + param_mode: PathParamMode, + def_id: DefId, + parameters: &hir::PathParameters, + self_ty: Option>) + -> (&'tcx Substs<'tcx>, Vec>) { let tcx = self.tcx(); + debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ + parameters={:?})", + def_id, self_ty, parameters); + + let (lifetimes, num_types_provided) = match *parameters { + hir::AngleBracketedParameters(ref data) => { + if param_mode == PathParamMode::Optional && data.types.is_empty() { + (&data.lifetimes[..], None) + } else { + (&data.lifetimes[..], Some(data.types.len())) + } + } + hir::ParenthesizedParameters(_) => (&[][..], Some(1)) + }; + // 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 expected_num_region_params = decl_generics.regions.len(TypeSpace); - let supplied_num_region_params = regions_provided.len(); + 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(); + let supplied_num_region_params = lifetimes.len(); let regions = if expected_num_region_params == supplied_num_region_params { - regions_provided + lifetimes.iter().map(|l| ast_region_to_region(tcx, l)).collect() } else { let anon_regions = rscope.anon_regions(span, expected_num_region_params); @@ -415,184 +447,112 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Err(_) => (0..expected_num_region_params).map(|_| ty::ReStatic).collect() } }; - Substs::new_type(vec![], regions) - } - /// Given the type/region arguments provided to some path (along with - /// an implicit Self, if this is a trait reference) returns the complete - /// set of substitutions. This may involve applying defaulted type parameters. - /// - /// Note that the type listing given here is *exactly* what the user provided. - /// - /// The `region_substs` should be the result of `create_region_substs` - /// -- that is, a substitution with no types but the correct number of - /// regions. - fn create_substs_for_ast_path(&self, - span: Span, - param_mode: PathParamMode, - decl_generics: &ty::Generics<'tcx>, - self_ty: Option>, - types_provided: Vec>, - region_substs: Substs<'tcx>) - -> Substs<'tcx> - { - let tcx = self.tcx(); + // If a self-type was declared, one should be provided. + assert_eq!(decl_generics.has_self, self_ty.is_some()); - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \ - types_provided={:?}, region_substs={:?})", - decl_generics, self_ty, types_provided, - region_substs); - - assert_eq!(region_substs.regions.len(TypeSpace), decl_generics.regions.len(TypeSpace)); - assert!(region_substs.types.is_empty()); - - // Convert the type parameters supplied by the user. - let ty_param_defs = decl_generics.types.get_slice(TypeSpace); - let formal_ty_param_count = ty_param_defs.len(); - let required_ty_param_count = ty_param_defs.iter() - .take_while(|x| x.default.is_none()) - .count(); - - let mut type_substs = self.get_type_substs_for_defs(span, - types_provided, - param_mode, - ty_param_defs, - region_substs.clone(), - self_ty); - - let supplied_ty_param_count = type_substs.len(); - check_type_argument_count(self.tcx(), span, supplied_ty_param_count, - required_ty_param_count, formal_ty_param_count); - - if supplied_ty_param_count < required_ty_param_count { - while type_substs.len() < required_ty_param_count { - type_substs.push(tcx.types.err); - } - } else if supplied_ty_param_count > formal_ty_param_count { - type_substs.truncate(formal_ty_param_count); + // Check the number of type parameters supplied by the user. + if let Some(num_provided) = num_types_provided { + let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..]; + check_type_argument_count(tcx, span, num_provided, ty_param_defs); } - assert!(type_substs.len() >= required_ty_param_count && - type_substs.len() <= formal_ty_param_count); - - let mut substs = region_substs; - substs.types.extend(TypeSpace, type_substs.into_iter()); - match self_ty { - None => { - // If no self-type is provided, it's still possible that - // one was declared, because this could be an object type. + let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF); + let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| { + if let Some(ref default) = p.default { + if is_object && default.has_self_ty() { + // There is no suitable inference default for a type parameter + // that references self, in an object type. + return true; + } } - Some(ty) => { - // If a self-type is provided, one should have been - // "declared" (in other words, this should be a - // trait-ref). - assert!(decl_generics.types.get_self().is_some()); - substs.types.push(SelfSpace, ty); + + false + }; + + let mut output_assoc_binding = None; + let substs = Substs::for_item(tcx, def_id, |def, _| { + regions[def.index as usize] + }, |def, substs| { + let i = def.index as usize; + + // Handle Self first, so we can adjust the index to match the AST. + if let (0, Some(ty)) = (i, self_ty) { + return ty; } - } - let actual_supplied_ty_param_count = substs.types.len(TypeSpace); - for param in &ty_param_defs[actual_supplied_ty_param_count..] { - if let Some(default) = param.default { + let i = i - self_ty.is_some() as usize; + if num_types_provided.map_or(false, |n| i < n) { + // A provided type parameter. + match *parameters { + hir::AngleBracketedParameters(ref data) => { + self.ast_ty_arg_to_ty(rscope, Some(def), substs, &data.types[i]) + } + hir::ParenthesizedParameters(ref data) => { + assert_eq!(i, 0); + let (ty, assoc) = + self.convert_parenthesized_parameters(rscope, substs, data); + output_assoc_binding = Some(assoc); + ty + } + } + } else if num_types_provided.is_none() { + // No type parameters were provided, we can infer all. + let ty_var = if !default_needs_object_self(def) { + self.ty_infer_for_def(def, substs, span) + } else { + self.ty_infer(span) + }; + ty_var + } else if let Some(default) = def.default { + // No type parameter provided, but a default exists. + // If we are converting an object type, then the // `Self` parameter is unknown. However, some of the // other type parameters may reference `Self` in their // defaults. This will lead to an ICE if we are not // careful! - if self_ty.is_none() && default.has_self_ty() { + if default_needs_object_self(def) { span_err!(tcx.sess, span, E0393, "the type parameter `{}` must be explicitly specified \ in an object type because its default value `{}` references \ the type `Self`", - param.name, + def.name, default); - substs.types.push(TypeSpace, tcx.types.err); + tcx.types.err } else { // This is a default type parameter. - let default = default.subst_spanned(tcx, - &substs, - Some(span)); - substs.types.push(TypeSpace, default); + default.subst_spanned(tcx, substs, Some(span)) } } else { - span_bug!(span, "extra parameter without default"); + // We've already errored above about the mismatch. + tcx.types.err } - } - - debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", - decl_generics, self_ty, substs); + }); - substs - } - - /// Returns types_provided if it is not empty, otherwise populating the - /// type parameters with inference variables as appropriate. - fn get_type_substs_for_defs(&self, - span: Span, - types_provided: Vec>, - param_mode: PathParamMode, - ty_param_defs: &[ty::TypeParameterDef<'tcx>], - mut substs: Substs<'tcx>, - self_ty: Option>) - -> Vec> - { - fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option>) - -> Option> - { - if let Some(ref default) = p.default { - if self_ty.is_none() && default.has_self_ty() { - // There is no suitable inference default for a type parameter - // that references self with no self-type provided. - return None; - } + let assoc_bindings = match *parameters { + hir::AngleBracketedParameters(ref data) => { + data.bindings.iter().map(|b| { + ConvertedBinding { + item_name: b.name, + ty: self.ast_ty_to_ty(rscope, &b.ty), + span: b.span + } + }).collect() } + hir::ParenthesizedParameters(ref data) => { + 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 + })] + } + }; - Some(p.clone()) - } - - if param_mode == PathParamMode::Optional && types_provided.is_empty() { - ty_param_defs - .iter() - .map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs), - Some(TypeSpace), span)) - .collect() - } else { - types_provided - } - } + debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", + decl_generics, self_ty, substs); - fn convert_angle_bracketed_parameters(&self, - rscope: &RegionScope, - span: Span, - decl_generics: &ty::Generics<'tcx>, - data: &hir::AngleBracketedParameterData) - -> (Substs<'tcx>, - Vec>, - Vec>) - { - let regions: Vec<_> = - data.lifetimes.iter() - .map(|l| ast_region_to_region(self.tcx(), l)) - .collect(); - - let region_substs = - self.create_region_substs(rscope, span, decl_generics, regions); - - let types: Vec<_> = - data.types.iter() - .enumerate() - .map(|(i,t)| self.ast_ty_arg_to_ty(rscope, decl_generics, - i, ®ion_substs, t)) - .collect(); - - let assoc_bindings: Vec<_> = - data.bindings.iter() - .map(|b| ConvertedBinding { item_name: b.name, - ty: self.ast_ty_to_ty(rscope, &b.ty), - span: b.span }) - .collect(); - - (region_substs, types, assoc_bindings) + (substs, assoc_bindings) } /// Returns the appropriate lifetime to use for any output lifetimes @@ -657,29 +617,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn convert_parenthesized_parameters(&self, rscope: &RegionScope, - span: Span, - decl_generics: &ty::Generics<'tcx>, + region_substs: &Substs<'tcx>, data: &hir::ParenthesizedParameterData) - -> (Substs<'tcx>, - Vec>, - Vec>) + -> (Ty<'tcx>, ConvertedBinding<'tcx>) { - let region_substs = - self.create_region_substs(rscope, span, decl_generics, Vec::new()); - let anon_scope = rscope.anon_type_scope(); let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope); - let inputs = - data.inputs.iter() - .map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics, - 0, ®ion_substs, a_t)) - .collect::>>(); - + let inputs: Vec<_> = data.inputs.iter().map(|a_t| { + self.ast_ty_arg_to_ty(&binding_rscope, None, region_substs, a_t) + }).collect(); let input_params = vec![String::new(); inputs.len()]; let implied_output_region = self.find_implied_output_region(&inputs, input_params); - let input_ty = self.tcx().mk_tup(inputs); - let (output, output_span) = match data.output { Some(ref output_ty) => { (self.convert_ty_with_lifetime_elision(implied_output_region, @@ -698,13 +647,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: output_span }; - (region_substs, vec![input_ty], vec![output_binding]) + (self.tcx().mk_tup(inputs), output_binding) } pub fn instantiate_poly_trait_ref(&self, rscope: &RegionScope, ast_trait_ref: &hir::PolyTraitRef, - self_ty: Option>, + self_ty: Ty<'tcx>, poly_projections: &mut Vec>) -> ty::PolyTraitRef<'tcx> { @@ -729,7 +678,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn instantiate_mono_trait_ref(&self, rscope: &RegionScope, trait_ref: &hir::TraitRef, - self_ty: Option>) + self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { let trait_def_id = self.trait_def_id(trait_ref); @@ -755,32 +704,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } - fn object_path_to_poly_trait_ref(&self, - rscope: &RegionScope, - span: Span, - param_mode: PathParamMode, - trait_def_id: DefId, - trait_path_ref_id: ast::NodeId, - trait_segment: &hir::PathSegment, - mut projections: &mut Vec>) - -> ty::PolyTraitRef<'tcx> - { - self.ast_path_to_poly_trait_ref(rscope, - span, - param_mode, - trait_def_id, - None, - trait_path_ref_id, - trait_segment, - projections) - } - fn ast_path_to_poly_trait_ref(&self, rscope: &RegionScope, span: Span, param_mode: PathParamMode, trait_def_id: DefId, - self_ty: Option>, + self_ty: Ty<'tcx>, path_id: ast::NodeId, trait_segment: &hir::PathSegment, poly_projections: &mut Vec>) @@ -803,21 +732,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_segment); let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs)); - { - let converted_bindings = - assoc_bindings - .iter() - .filter_map(|binding| { - // specify type to assert that error was already reported in Err case: - let predicate: Result<_, ErrorReported> = - self.ast_type_binding_to_poly_projection_predicate(path_id, - poly_trait_ref.clone(), - self_ty, - binding); - predicate.ok() // ok to ignore Err() because ErrorReported (see above) - }); - poly_projections.extend(converted_bindings); - } + poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { + // specify type to assert that error was already reported in Err case: + let predicate: Result<_, ErrorReported> = + self.ast_type_binding_to_poly_projection_predicate(path_id, + poly_trait_ref, + binding); + predicate.ok() // ok to ignore Err() because ErrorReported (see above) + })); debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}", trait_segment, poly_projections, poly_trait_ref); @@ -829,7 +751,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: Span, param_mode: PathParamMode, trait_def_id: DefId, - self_ty: Option>, + self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment) -> ty::TraitRef<'tcx> { @@ -849,7 +771,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: Span, param_mode: PathParamMode, trait_def_id: DefId, - self_ty: Option>, + self_ty: Ty<'tcx>, trait_segment: &hir::PathSegment) -> (&'tcx Substs<'tcx>, Vec>) { @@ -865,8 +787,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }; - let (regions, types, assoc_bindings) = match trait_segment.parameters { - hir::AngleBracketedParameters(ref data) => { + match trait_segment.parameters { + hir::AngleBracketedParameters(_) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar { @@ -877,10 +799,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { type parameters is subject to change. \ Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"); } - - self.convert_angle_bracketed_parameters(rscope, span, &trait_def.generics, data) } - hir::ParenthesizedParameters(ref data) => { + hir::ParenthesizedParameters(_) => { // For now, require that parenthetical notation be used // only with `Fn()` etc. if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar { @@ -889,26 +809,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { "\ parenthetical notation is only stable when used with `Fn`-family traits"); } - - self.convert_parenthesized_parameters(rscope, span, &trait_def.generics, data) } - }; - - let substs = self.create_substs_for_ast_path(span, - param_mode, - &trait_def.generics, - self_ty, - types, - regions); + } - (self.tcx().mk_substs(substs), assoc_bindings) + self.create_substs_for_ast_path(rscope, + span, + param_mode, + trait_def_id, + &trait_segment.parameters, + Some(self_ty)) } fn ast_type_binding_to_poly_projection_predicate( &self, path_id: ast::NodeId, - mut trait_ref: ty::PolyTraitRef<'tcx>, - self_ty: Option>, + trait_ref: ty::PolyTraitRef<'tcx>, binding: &ConvertedBinding<'tcx>) -> Result, ErrorReported> { @@ -962,62 +877,39 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Simple case: X is defined in the current trait. if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { - return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+ - projection_ty: ty::ProjectionTy { // | - trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+ - item_name: binding.item_name, - }, - ty: binding.ty, + return Ok(trait_ref.map_bound(|trait_ref| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: binding.item_name, + }, + ty: binding.ty, + } })); } // Otherwise, we have to walk through the supertraits to find - // those that do. This is complicated by the fact that, for an - // object type, the `Self` type is not present in the - // substitutions (after all, it's being constructed right now), - // but the `supertraits` iterator really wants one. To handle - // this, we currently insert a dummy type and then remove it - // later. Yuck. - - let dummy_self_ty = tcx.mk_infer(ty::FreshTy(0)); - if self_ty.is_none() { // if converting for an object type - let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+ - assert!(dummy_substs.self_ty().is_none()); // | - dummy_substs.types.push(SelfSpace, dummy_self_ty); // | - trait_ref = ty::Binder(ty::TraitRef::new(trait_ref.def_id(), // <------------+ - tcx.mk_substs(dummy_substs))); - } - + // those that do. self.ensure_super_predicates(binding.span, trait_ref.def_id())?; - let mut candidates: Vec = + let candidates: Vec = traits::supertraits(tcx, trait_ref.clone()) .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name)) .collect(); - // If converting for an object type, then remove the dummy-ty from `Self` now. - // Yuckety yuck. - if self_ty.is_none() { - for candidate in &mut candidates { - let mut dummy_substs = candidate.0.substs.clone(); - assert!(dummy_substs.self_ty() == Some(dummy_self_ty)); - dummy_substs.types.pop(SelfSpace); - *candidate = ty::Binder(ty::TraitRef::new(candidate.def_id(), - tcx.mk_substs(dummy_substs))); - } - } - let candidate = self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(), &binding.item_name.as_str(), binding.span)?; - Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+ - projection_ty: ty::ProjectionTy { // | - trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+ - item_name: binding.item_name, - }, - ty: binding.ty, + Ok(candidate.map_bound(|trait_ref| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy { + trait_ref: trait_ref, + item_name: binding.item_name, + }, + ty: binding.ty, + } })) } @@ -1030,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; } @@ -1042,23 +932,24 @@ 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. if Some(did) == self.tcx().lang_items.owned_box() { - assert_eq!(substs.types.len(TypeSpace), 1); - return self.tcx().mk_box(*substs.types.get(TypeSpace, 0)); + assert_eq!(substs.types.len(), 1); + return self.tcx().mk_box(substs.types[0]); } - decl_ty.subst(self.tcx(), &substs) + decl_ty.subst(self.tcx(), substs) } - fn ast_ty_to_trait_ref(&self, - rscope: &RegionScope, - ty: &hir::Ty, - bounds: &[hir::TyParamBound]) - -> Result, ErrorReported> + fn ast_ty_to_object_trait_ref(&self, + rscope: &RegionScope, + span: Span, + ty: &hir::Ty, + bounds: &[hir::TyParamBound]) + -> Ty<'tcx> { /*! * In a type like `Foo + Send`, we want to wait to collect the @@ -1071,33 +962,32 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { * name, and reports an error otherwise. */ + let tcx = self.tcx(); match ty.node { hir::TyPath(None, ref path) => { - let resolution = self.tcx().expect_resolution(ty.id); + let resolution = tcx.expect_resolution(ty.id); match resolution.base_def { Def::Trait(trait_def_id) if resolution.depth == 0 => { - let mut projection_bounds = Vec::new(); - let trait_ref = - self.object_path_to_poly_trait_ref(rscope, - path.span, - PathParamMode::Explicit, - trait_def_id, - ty.id, - path.segments.last().unwrap(), - &mut projection_bounds); - Ok((trait_ref, projection_bounds)) + self.trait_path_to_object_type(rscope, + path.span, + PathParamMode::Explicit, + trait_def_id, + ty.id, + path.segments.last().unwrap(), + span, + partition_bounds(tcx, span, bounds)) } _ => { - struct_span_err!(self.tcx().sess, ty.span, E0172, + struct_span_err!(tcx.sess, ty.span, E0172, "expected a reference to a trait") .span_label(ty.span, &format!("expected a trait")) .emit(); - Err(ErrorReported) + tcx.types.err } } } _ => { - let mut err = struct_span_err!(self.tcx().sess, ty.span, E0178, + let mut err = struct_span_err!(tcx.sess, ty.span, E0178, "expected a path on the left-hand side \ of `+`, not `{}`", pprust::ty_to_string(ty)); @@ -1136,44 +1026,93 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } err.emit(); - Err(ErrorReported) + tcx.types.err } } } - fn trait_ref_to_object_type(&self, - rscope: &RegionScope, - span: Span, - trait_ref: ty::PolyTraitRef<'tcx>, - projection_bounds: Vec>, - bounds: &[hir::TyParamBound]) - -> Ty<'tcx> - { - let existential_bounds = self.conv_existential_bounds(rscope, - span, - trait_ref.clone(), - projection_bounds, - bounds); - - let result = self.make_object_type(span, trait_ref, existential_bounds); - debug!("trait_ref_to_object_type: result={:?}", - result); - - result + /// Transform a PolyTraitRef into a PolyExistentialTraitRef by + /// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF). + fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>) + -> ty::ExistentialTraitRef<'tcx> { + assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF); + ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } - fn make_object_type(&self, - span: Span, - principal: ty::PolyTraitRef<'tcx>, - bounds: ty::ExistentialBounds<'tcx>) - -> Ty<'tcx> { + fn trait_path_to_object_type(&self, + rscope: &RegionScope, + path_span: Span, + param_mode: PathParamMode, + trait_def_id: DefId, + trait_path_ref_id: ast::NodeId, + trait_segment: &hir::PathSegment, + span: Span, + partitioned_bounds: PartitionedBounds) + -> Ty<'tcx> { let tcx = self.tcx(); - let object = ty::TraitTy { - principal: principal, - bounds: bounds + + let mut projection_bounds = vec![]; + let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF); + let principal = self.ast_path_to_poly_trait_ref(rscope, + path_span, + param_mode, + trait_def_id, + dummy_self, + trait_path_ref_id, + trait_segment, + &mut projection_bounds); + + let PartitionedBounds { builtin_bounds, + trait_bounds, + region_bounds } = + partitioned_bounds; + + if !trait_bounds.is_empty() { + let b = &trait_bounds[0]; + let span = b.trait_ref.path.span; + struct_span_err!(self.tcx().sess, span, E0225, + "only the builtin traits can be used as closure or object bounds") + .span_label(span, &format!("non-builtin trait used as bounds")) + .emit(); + } + + // Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above. + let existential_principal = principal.map_bound(|trait_ref| { + self.trait_ref_to_existential(trait_ref) + }); + let existential_projections = projection_bounds.iter().map(|bound| { + bound.map_bound(|b| { + let p = b.projection_ty; + ty::ExistentialProjection { + trait_ref: self.trait_ref_to_existential(p.trait_ref), + item_name: p.item_name, + ty: b.ty + } + }) + }).collect(); + + let region_bound = + self.compute_object_lifetime_bound(span, + ®ion_bounds, + existential_principal, + builtin_bounds); + + let region_bound = match region_bound { + Some(r) => r, + None => { + match rscope.object_lifetime_default(span) { + Some(r) => r, + None => { + span_err!(self.tcx().sess, span, E0228, + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound"); + ty::ReStatic + } + } + } }; - let object_trait_ref = - object.principal_trait_ref_with_self_ty(tcx, tcx.types.err); + + debug!("region_bound: {:?}", region_bound); // ensure the super predicates and stop if we encountered an error if self.ensure_super_predicates(span, principal.def_id()).is_err() { @@ -1193,7 +1132,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } let mut associated_types: FnvHashSet<(DefId, ast::Name)> = - traits::supertraits(tcx, object_trait_ref) + traits::supertraits(tcx, principal) .flat_map(|tr| { let trait_def = tcx.lookup_trait_def(tr.def_id()); trait_def.associated_type_names @@ -1203,7 +1142,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }) .collect(); - for projection_bound in &object.bounds.projection_bounds { + for projection_bound in &projection_bounds { let pair = (projection_bound.0.projection_ty.trait_ref.def_id, projection_bound.0.projection_ty.item_name); associated_types.remove(&pair); @@ -1219,7 +1158,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } - tcx.mk_trait(object.principal, object.bounds) + let ty = tcx.mk_trait(ty::TraitObject { + principal: existential_principal, + region_bound: region_bound, + builtin_bounds: builtin_bounds, + projection_bounds: existential_projections + }); + debug!("trait_object_type: {:?}", ty); + ty } fn report_ambiguous_associated_type(&self, @@ -1379,8 +1325,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => { + (&ty::TyParam(_), Def::TyParam(param_did)) => { let param_node_id = tcx.map.as_local_node_id(param_did).unwrap(); + let param_name = tcx.type_parameter_def(param_node_id).name; match self.find_bound_for_assoc_item(param_node_id, param_name, assoc_name, @@ -1390,10 +1337,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } _ => { - self.report_ambiguous_associated_type(span, - &ty.to_string(), - "Trait", - &assoc_name.as_str()); + // Don't print TyErr to the user. + if !ty.references_error() { + self.report_ambiguous_associated_type(span, + &ty.to_string(), + "Trait", + &assoc_name.as_str()); + } return (tcx.types.err, Def::Err); } }; @@ -1453,7 +1403,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span, param_mode, trait_def_id, - Some(self_ty), + self_ty, trait_segment); debug!("qpath_to_ty: trait_ref={:?}", trait_ref); @@ -1468,24 +1418,20 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { /// # Parameters /// /// * `this`, `rscope`: the surrounding context - /// * `decl_generics`: the generics of the struct/enum/trait declaration being - /// referenced - /// * `index`: the index of the type parameter being instantiated from the list - /// (we assume it is in the `TypeSpace`) + /// * `def`: the type parameter being instantiated (if available) /// * `region_substs`: a partial substitution consisting of /// only the region type parameters being supplied to this type. /// * `ast_ty`: the ast representation of the type being supplied - pub fn ast_ty_arg_to_ty(&self, - rscope: &RegionScope, - decl_generics: &ty::Generics<'tcx>, - index: usize, - region_substs: &Substs<'tcx>, - ast_ty: &hir::Ty) - -> Ty<'tcx> + fn ast_ty_arg_to_ty(&self, + rscope: &RegionScope, + def: Option<&ty::TypeParameterDef<'tcx>>, + region_substs: &Substs<'tcx>, + ast_ty: &hir::Ty) + -> Ty<'tcx> { let tcx = self.tcx(); - if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) { + if let Some(def) = def { let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs); let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default); self.ast_ty_to_ty(rscope1, ast_ty) @@ -1515,23 +1461,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::Trait(trait_def_id) => { // N.B. this case overlaps somewhat with // TyObjectSum, see that fn for details - let mut projection_bounds = Vec::new(); - - let trait_ref = - self.object_path_to_poly_trait_ref(rscope, - span, - param_mode, - trait_def_id, - base_path_ref_id, - base_segments.last().unwrap(), - &mut projection_bounds); tcx.prohibit_type_params(base_segments.split_last().unwrap().1); - self.trait_ref_to_object_type(rscope, - span, - trait_ref, - projection_bounds, - &[]) + + self.trait_path_to_object_type(rscope, + span, + param_mode, + trait_def_id, + base_path_ref_id, + base_segments.last().unwrap(), + span, + partition_bounds(tcx, span, &[])) } Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => { tcx.prohibit_type_params(base_segments.split_last().unwrap().1); @@ -1541,9 +1481,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { did, base_segments.last().unwrap()) } - Def::TyParam(space, index, _, name) => { + Def::TyParam(did) => { tcx.prohibit_type_params(base_segments); - tcx.mk_param(space, index, name) + + let node_id = tcx.map.as_local_node_id(did).unwrap(); + let param = tcx.ty_param_defs.borrow().get(&node_id) + .map(ty::ParamTy::for_def); + if let Some(p) = param { + p.to_ty(tcx) + } else { + // Only while computing defaults of earlier type + // parameters can a type parameter be missing its def. + struct_span_err!(tcx.sess, span, E0128, + "type parameters with a default cannot use \ + forward declared identifiers") + .span_label(span, &format!("defaulted type parameters \ + cannot be forward declared")) + .emit(); + tcx.types.err + } } Def::SelfTy(_, Some(impl_id)) => { // Self in impl (we know the concrete type). @@ -1671,18 +1627,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty)) } hir::TyObjectSum(ref ty, ref bounds) => { - match self.ast_ty_to_trait_ref(rscope, &ty, bounds) { - Ok((trait_ref, projection_bounds)) => { - self.trait_ref_to_object_type(rscope, - ast_ty.span, - trait_ref, - projection_bounds, - bounds) - } - Err(ErrorReported) => { - self.tcx().types.err - } - } + self.ast_ty_to_object_trait_ref(rscope, ast_ty.span, ty, bounds) } hir::TyPtr(ref mt) => { tcx.mk_ptr(ty::TypeAndMut { @@ -1759,7 +1704,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.mk_fn_ptr(bare_fn_ty) } hir::TyPolyTraitRef(ref bounds) => { - self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds) + self.conv_object_ty_poly_trait_ref(rscope, ast_ty.span, bounds) } hir::TyImplTrait(ref bounds) => { use collect::{compute_bounds, SizedByDefault}; @@ -1767,7 +1712,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`. @@ -1778,7 +1723,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let predicates = bounds.predicates(tcx, ty); let predicates = tcx.lift_to_global(&predicates).unwrap(); tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { - predicates: VecPerParamSpace::new(vec![], vec![], predicates) + parent: None, + predicates: predicates }); ty @@ -1829,7 +1775,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // values in a ExprClosure, or as // the type of local variables. Both of these cases are // handled specially and will not descend into this routine. - self.ty_infer(None, None, None, ast_ty.span) + self.ty_infer(ast_ty.span) } }; @@ -1846,7 +1792,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { match a.ty.node { hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(), - hir::TyInfer => self.ty_infer(None, None, None, a.ty.span), + hir::TyInfer => self.ty_infer(a.ty.span), _ => self.ast_ty_to_ty(rscope, &a.ty), } } @@ -2068,8 +2014,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let output_ty = match decl.output { _ if is_infer && expected_ret_ty.is_some() => expected_ret_ty.unwrap(), - _ if is_infer => - self.ty_infer(None, None, None, decl.output.span()), + _ if is_infer => self.ty_infer(decl.output.span()), hir::Return(ref output) => self.ast_ty_to_ty(&rb, &output), hir::DefaultReturn(..) => bug!(), @@ -2087,28 +2032,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } } - /// Given an existential type like `Foo+'a+Bar`, this routine converts - /// the `'a` and `Bar` intos an `ExistentialBounds` struct. - /// The `main_trait_refs` argument specifies the `Foo` -- it is absent - /// for closures. Eventually this should all be normalized, I think, - /// so that there is no "main trait ref" and instead we just have a flat - /// list of bounds as the existential type. - fn conv_existential_bounds(&self, - rscope: &RegionScope, - span: Span, - principal_trait_ref: ty::PolyTraitRef<'tcx>, - projection_bounds: Vec>, - ast_bounds: &[hir::TyParamBound]) - -> ty::ExistentialBounds<'tcx> - { - let partitioned_bounds = - partition_bounds(self.tcx(), span, ast_bounds); - - self.conv_existential_bounds_from_partitioned_bounds( - rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds) - } - - fn conv_ty_poly_trait_ref(&self, + fn conv_object_ty_poly_trait_ref(&self, rscope: &RegionScope, span: Span, ast_bounds: &[hir::TyParamBound]) @@ -2116,75 +2040,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]); - let mut projection_bounds = Vec::new(); - let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { - let trait_bound = partitioned_bounds.trait_bounds.remove(0); - self.instantiate_poly_trait_ref(rscope, - trait_bound, - None, - &mut projection_bounds) + let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { + partitioned_bounds.trait_bounds.remove(0) } else { span_err!(self.tcx().sess, span, E0224, "at least one non-builtin trait is required for an object type"); return self.tcx().types.err; }; - let bounds = - self.conv_existential_bounds_from_partitioned_bounds(rscope, - span, - main_trait_bound.clone(), - projection_bounds, - partitioned_bounds); - - self.make_object_type(span, main_trait_bound, bounds) - } - - pub fn conv_existential_bounds_from_partitioned_bounds(&self, - rscope: &RegionScope, - span: Span, - principal_trait_ref: ty::PolyTraitRef<'tcx>, - projection_bounds: Vec>, // Empty for boxed closures - partitioned_bounds: PartitionedBounds) - -> ty::ExistentialBounds<'tcx> - { - let PartitionedBounds { builtin_bounds, - trait_bounds, - region_bounds } = - partitioned_bounds; - - if !trait_bounds.is_empty() { - let b = &trait_bounds[0]; - let span = b.trait_ref.path.span; - struct_span_err!(self.tcx().sess, span, E0225, - "only the builtin traits can be used as closure or object bounds") - .span_label(span, &format!("non-builtin trait used as bounds")) - .emit(); - } - - let region_bound = - self.compute_object_lifetime_bound(span, - ®ion_bounds, - principal_trait_ref, - builtin_bounds); - - let region_bound = match region_bound { - Some(r) => r, - None => { - match rscope.object_lifetime_default(span) { - Some(r) => r, - None => { - span_err!(self.tcx().sess, span, E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound"); - ty::ReStatic - } - } - } - }; - - debug!("region_bound: {:?}", region_bound); - - ty::ExistentialBounds::new(region_bound, builtin_bounds, projection_bounds) + let trait_ref = &trait_bound.trait_ref; + let trait_def_id = self.trait_def_id(trait_ref); + self.trait_path_to_object_type(rscope, + trait_ref.path.span, + PathParamMode::Explicit, + trait_def_id, + trait_ref.ref_id, + trait_ref.path.segments.last().unwrap(), + span, + partitioned_bounds) } /// Given the bounds on an object, determines what single region bound (if any) we can @@ -2195,7 +2068,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn compute_object_lifetime_bound(&self, span: Span, explicit_region_bounds: &[&hir::Lifetime], - principal_trait_ref: ty::PolyTraitRef<'tcx>, + principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>, builtin_bounds: ty::BuiltinBounds) -> Option // if None, use the default { @@ -2226,7 +2099,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = - object_region_bounds(tcx, &principal_trait_ref, builtin_bounds); + object_region_bounds(tcx, principal_trait_ref, builtin_bounds); // If there are no derived region bounds, then report back that we // can find no region bound. The caller will use the default. @@ -2279,7 +2152,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, let parameters = &segments[segments.len() - 1].parameters; if !parameters.types().is_empty() { check_type_argument_count(tcx, b.trait_ref.path.span, - parameters.types().len(), 0, 0); + parameters.types().len(), &[]); } if !parameters.lifetimes().is_empty() { report_lifetime_number_error(tcx, b.trait_ref.path.span, @@ -2310,7 +2183,9 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize, - required: usize, accepted: usize) { + ty_param_defs: &[ty::TypeParameterDef]) { + let accepted = ty_param_defs.len(); + let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count(); if supplied < required { let expected = if required < accepted { "expected at least" diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 04f22b195110f..af24a7b51176c 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 265422468fe2a..9a3cbabe55331 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/cast.rs b/src/librustc_typeck/check/cast.rs index 7a4cc09a7d506..fb78d3a37ca23 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn unsize_kind(&self, t: Ty<'tcx>) -> Option> { match t.sty { ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), - ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())), + ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())), ty::TyStruct(def, substs) => { // FIXME(arielb1): do some kind of normalization match def.struct_variant().fields.last() { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 3acb8017eec50..377ca5eaebe30 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -13,7 +13,6 @@ use super::{check_fn, Expectation, FnCtxt}; use astconv::AstConv; -use rustc::ty::subst; use rustc::ty::{self, ToPolyTraitRef, Ty}; use std::cmp; use syntax::abi::Abi; @@ -102,12 +101,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match expected_ty.sty { ty::TyTrait(ref object_type) => { - let proj_bounds = object_type.projection_bounds_with_self_ty(self.tcx, - self.tcx.types.err); - let sig = proj_bounds.iter() - .filter_map(|pb| self.deduce_sig_from_projection(pb)) - .next(); - let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal_def_id()); + let sig = object_type.projection_bounds.iter().filter_map(|pb| { + let pb = pb.with_self_ty(self.tcx, self.tcx.types.err); + self.deduce_sig_from_projection(&pb) + }).next(); + let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal.def_id()); (sig, kind) } ty::TyInfer(ty::TyVar(vid)) => { @@ -205,7 +203,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return None; } - let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0); + let arg_param_ty = trait_ref.substs().types[1]; let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty); debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e6ddc6ad69379..6bcf21563cb98 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -13,7 +13,7 @@ use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::ty; use rustc::traits::{self, Reveal}; use rustc::ty::error::ExpectedFound; -use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace}; +use rustc::ty::subst::{Subst, Substs}; use rustc::hir::map::Node; use rustc::hir::{ImplItemKind, TraitItem_}; @@ -95,8 +95,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } - let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace); - let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace); + let num_impl_m_type_params = impl_m.generics.types.len(); + let num_trait_m_type_params = trait_m.generics.types.len(); if num_impl_m_type_params != num_trait_m_type_params { span_err!(tcx.sess, impl_m_span, E0049, "method `{}` has {} type parameter{} \ @@ -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; } @@ -216,58 +214,49 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| { 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); - // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter // environment. We can't just use `impl_env.caller_bounds`, // however, because we want to replace all late-bound regions with // region variables. - let impl_bounds = - impl_m.predicates.instantiate(tcx, impl_to_skol_substs); - - debug!("compare_impl_method: impl_bounds={:?}", impl_bounds); + let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap()); + let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs); - // Obtain the predicate split predicate sets for each. - let trait_pred = trait_bounds.predicates.split(); - let impl_pred = impl_bounds.predicates.split(); + debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds); // This is the only tricky bit of the new way we check implementation methods - // We need to build a set of predicates where only the FnSpace bounds + // We need to build a set of predicates where only the method-level bounds // are from the trait and we assume all other bounds from the implementation // to be previously satisfied. // // We then register the obligations from the impl_m and check to see // if all constraints hold. - let hybrid_preds = VecPerParamSpace::new( - impl_pred.types, - impl_pred.selfs, - trait_pred.fns - ); + hybrid_preds.predicates.extend( + trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates); // Construct trait parameter environment and then shift it into the skolemized viewpoint. // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id); - let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.into_vec()); + let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates); let trait_param_env = traits::normalize_param_env_or_error(tcx, trait_param_env, normalize_cause.clone()); // FIXME(@jroesch) this seems ugly, but is a temporary change infcx.parameter_environment = trait_param_env; - debug!("compare_impl_method: trait_bounds={:?}", + debug!("compare_impl_method: caller_bounds={:?}", infcx.parameter_environment.caller_bounds); let mut selcx = traits::SelectionContext::new(&infcx); - let (impl_pred_fns, _) = + let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs); + let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var( impl_m_span, infer::HigherRankedType, - &ty::Binder(impl_pred.fns)); - for predicate in impl_pred_fns { + &ty::Binder(impl_m_own_bounds.predicates)); + for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); @@ -322,7 +311,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, @@ -390,8 +379,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, -> bool { - let trait_params = trait_generics.regions.get_slice(subst::FnSpace); - let impl_params = impl_generics.regions.get_slice(subst::FnSpace); + let trait_params = &trait_generics.regions[..]; + let impl_params = &impl_generics.regions[..]; debug!("check_region_bounds_on_impl_method: \ trait_generics={:?} \ @@ -453,16 +442,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 f3a01ef7409fa..82545d564a20c 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::{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`. @@ -179,10 +176,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( let generic_assumptions = tcx.lookup_predicates(self_type_did); let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs); - assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace)); - assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::FnSpace)); - let assumptions_in_impl_context = - assumptions_in_impl_context.predicates.get_slice(subst::TypeSpace); + let assumptions_in_impl_context = assumptions_in_impl_context.predicates; // An earlier version of this code attempted to do this checking // via the traits::fulfill machinery. However, it ran into trouble @@ -190,10 +184,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // 'a:'b and T:'b into region inference constraints. It is simpler // just to look for all the predicates directly. - assert!(dtor_predicates.predicates.is_empty_in(subst::SelfSpace)); - assert!(dtor_predicates.predicates.is_empty_in(subst::FnSpace)); - let predicates = dtor_predicates.predicates.get_slice(subst::TypeSpace); - for predicate in predicates { + assert_eq!(dtor_predicates.parent, None); + for predicate in &dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced // to take on a structure that is roughly an alpha-renaming of @@ -446,7 +438,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( ty::TyStruct(def, substs) if def.is_phantom_data() => { // PhantomData - behaves identically to T - let ity = *substs.types.get(subst::TypeSpace, 0); + let ity = substs.types[0]; iterate_over_potentially_unsafe_regions_in_type( cx, context, ity, depth+1) } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 4334f043772e3..b2873bf686578 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -13,7 +13,7 @@ use intrinsics; use rustc::infer::TypeOrigin; -use rustc::ty::subst::{self, Substs}; +use rustc::ty::subst::Substs; use rustc::ty::FnSig; use rustc::ty::{self, Ty}; use {CrateCtxt, require_same_types}; @@ -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 { @@ -49,7 +49,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, variadic: false, }), })); - let i_n_tps = i_ty.generics.types.len(subst::FnSpace); + let i_n_tps = i_ty.generics.types.len(); if i_n_tps != n_tps { struct_span_err!(tcx.sess, it.span, E0094, "intrinsic has wrong number of type \ @@ -70,7 +70,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { let name = token::intern(&format!("P{}", n)); - ccx.tcx.mk_param(subst::FnSpace, n, name) + ccx.tcx.mk_param(n, name) } let tcx = ccx.tcx; @@ -316,12 +316,12 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { let param = |n| { let name = token::intern(&format!("P{}", n)); - ccx.tcx.mk_param(subst::FnSpace, n, name) + ccx.tcx.mk_param(n, name) }; let tcx = ccx.tcx; let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id)); - let i_n_tps = i_ty.generics.types.len(subst::FnSpace); + let i_n_tps = i_ty.generics.types.len(); let name = it.name.as_str(); let (n_tps, inputs, output) = match &*name { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5fac65bbfd655..9e0b38fd9fe51 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::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>) - -> subst::Substs<'tcx> + -> &'tcx Substs<'tcx> { match pick.kind { probe::InherentImplPick => { @@ -210,7 +205,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { probe::ObjectPick => { let trait_def_id = pick.item.container().id(); - self.extract_trait_ref(self_ty, |this, object_ty, data| { + self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| { // The object data has no entry for the Self // Type. For the purposes of this method call, we // substitute the object type itself. This @@ -222,16 +217,16 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // been ruled out when we deemed the trait to be // "object safe". let original_poly_trait_ref = - data.principal_trait_ref_with_self_ty(this.tcx, object_ty); + principal.with_self_ty(this.tcx, object_ty); let upcast_poly_trait_ref = - this.upcast(original_poly_trait_ref.clone(), trait_def_id); + this.upcast(original_poly_trait_ref, trait_def_id); let upcast_trait_ref = this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref); debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}", original_poly_trait_ref, upcast_trait_ref, trait_def_id); - upcast_trait_ref.substs.clone() + upcast_trait_ref.substs }) } @@ -249,35 +244,36 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let impl_trait_ref = self.instantiate_type_scheme( self.span, - &impl_polytype.substs, + impl_polytype.substs, &self.tcx.impl_trait_ref(impl_def_id).unwrap()); - impl_trait_ref.substs.clone() + impl_trait_ref.substs } 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) => { // Where clauses can have bound regions in them. We need to instantiate // those to convert from a poly-trait-ref to a trait-ref. - self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs.clone() + self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs } } } - fn extract_trait_ref(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where - F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R, + fn extract_existential_trait_ref(&mut self, + self_ty: Ty<'tcx>, + mut closure: F) -> R + where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, + Ty<'tcx>, + ty::PolyExistentialTraitRef<'tcx>) -> R, { // If we specified that this is an object method, then the // self-type ought to be something that can be dereferenced to @@ -288,7 +284,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { self.fcx.autoderef(self.span, self_ty) .filter_map(|(ty, _)| { match ty.sty { - ty::TyTrait(ref data) => Some(closure(self, ty, &data)), + ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)), _ => None, } }) @@ -303,59 +299,49 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_substs(&mut self, pick: &probe::Pick<'tcx>, - supplied_method_types: Vec>, - substs: subst::Substs<'tcx>) - -> subst::Substs<'tcx> + mut supplied_method_types: Vec>, + 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 // variables. let num_supplied_types = supplied_method_types.len(); let method = pick.item.as_opt_method().unwrap(); - let method_types = method.generics.types.get_slice(subst::FnSpace); - let num_method_types = method_types.len(); - + let num_method_types = method.generics.types.len(); + + if num_supplied_types > 0 && num_supplied_types != num_method_types { + if num_method_types == 0 { + span_err!(self.tcx.sess, self.span, E0035, + "does not take type parameters"); + } else { + span_err!(self.tcx.sess, self.span, E0036, + "incorrect number of type parameters given for this method: \ + expected {}, found {}", + num_method_types, num_supplied_types); + } + supplied_method_types = vec![self.tcx.types.err; num_method_types]; + } // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - let method_regions = - self.region_vars_for_defs( - self.span, - pick.item.as_opt_method().unwrap() - .generics.regions.get_slice(subst::FnSpace)); - - let subst::Substs { types, regions } = substs; - let regions = regions.with_slice(subst::FnSpace, &method_regions); - let mut final_substs = subst::Substs { types: types, regions: regions }; - - if num_supplied_types == 0 { - self.type_vars_for_defs( - self.span, - subst::FnSpace, - &mut final_substs, - method_types); - } else if num_method_types == 0 { - span_err!(self.tcx.sess, self.span, E0035, - "does not take type parameters"); - self.type_vars_for_defs( - self.span, - subst::FnSpace, - &mut final_substs, - method_types); - } else if num_supplied_types != num_method_types { - span_err!(self.tcx.sess, self.span, E0036, - "incorrect number of type parameters given for this method: expected {}, found {}", - num_method_types, num_supplied_types); - final_substs.types.replace( - subst::FnSpace, - vec![self.tcx.types.err; num_method_types]); - } else { - final_substs.types.replace(subst::FnSpace, supplied_method_types); - } - - return final_substs; + Substs::for_item(self.tcx, method.def_id, |def, _| { + if let Some(&r) = substs.regions.get(def.index as usize) { + r + } else { + self.region_var_for_def(self.span, def) + } + }, |def, cur_substs| { + if let Some(&ty) = substs.types.get(def.index as usize) { + ty + } else if supplied_method_types.is_empty() { + self.type_var_for_def(self.span, def, cur_substs) + } else { + supplied_method_types[def.index as usize - substs.types.len()] + } + }) } fn unify_receivers(&mut self, @@ -382,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={:?})", @@ -393,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); @@ -411,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 e6401be5b3ef6..bcb410e1b8d01 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::Substs; use rustc::traits; use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; @@ -182,31 +182,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let trait_def = self.tcx.lookup_trait_def(trait_def_id); - let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace); - let expected_number_of_input_types = type_parameter_defs.len(); - - assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0); + if let Some(ref input_types) = opt_input_types { + assert_eq!(trait_def.generics.types.len() - 1, input_types.len()); + } assert!(trait_def.generics.regions.is_empty()); // Construct a trait-reference `self_ty : Trait` - let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty); - - match opt_input_types { - Some(input_types) => { - assert_eq!(expected_number_of_input_types, input_types.len()); - substs.types.replace(subst::ParamSpace::TypeSpace, input_types); + let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| { + self.region_var_for_def(span, def) + }, |def, substs| { + if def.index == 0 { + self_ty + } else if let Some(ref input_types) = opt_input_types { + input_types[def.index as usize - 1] + } else { + self.type_var_for_def(span, def, substs) } + }); - None => { - self.type_vars_for_defs( - span, - subst::ParamSpace::TypeSpace, - &mut substs, - type_parameter_defs); - } - } - - 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(); @@ -226,8 +220,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let tcx = self.tcx; let method_item = self.trait_item(trait_def_id, m_name).unwrap(); let method_ty = method_item.as_opt_method().unwrap(); - assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0); - assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0); + assert_eq!(method_ty.generics.types.len(), 0); + assert_eq!(method_ty.generics.regions.len(), 0); debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}", method_item, method_ty); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 99f1b13d4e4ab..c306463ec1de0 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::{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, @@ -290,8 +289,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(box ref data) => { - self.assemble_inherent_candidates_from_object(self_ty, data); - self.assemble_inherent_impl_candidates_for_type(data.principal_def_id()); + self.assemble_inherent_candidates_from_object(self_ty, data.principal); + self.assemble_inherent_impl_candidates_for_type(data.principal.def_id()); } ty::TyEnum(def, _) | ty::TyStruct(def, _) => { @@ -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. @@ -445,7 +444,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>, - data: &ty::TraitTy<'tcx>) { + principal: ty::PolyExistentialTraitRef<'tcx>) { debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty); @@ -456,7 +455,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // a substitution that replaces `Self` with the object type // itself. Hence, a `&self` method will wind up with an // argument type like `&Trait`. - let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx, self_ty); + let trait_ref = principal.with_self_ty(self.tcx, self_ty); self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| { let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref); @@ -519,14 +518,10 @@ 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.parent_types as usize, + trait_ref.substs.types.len()); + assert_eq!(m.generics.parent_regions as usize, + trait_ref.substs.regions.len()); } // Because this trait derives from a where-clause, it @@ -665,7 +660,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 +748,19 @@ 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.index == 0 { + step.self_ty + } else { + 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(), @@ -799,7 +799,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let trait_predicates = self.tcx.lookup_predicates(def_id); let bounds = trait_predicates.instantiate(self.tcx, substs); - let predicates = bounds.predicates.into_vec(); + let predicates = bounds.predicates; debug!("assemble_projection_candidates: predicates={:?}", predicates); for poly_bound in @@ -1192,7 +1192,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 +1205,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={:?})", @@ -1220,64 +1220,52 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // are given do not include type/lifetime parameters for the // method yet. So create fresh variables here for those too, // if there are any. - assert_eq!(substs.types.len(subst::FnSpace), 0); - assert_eq!(substs.regions.len(subst::FnSpace), 0); + assert_eq!(substs.types.len(), method.generics.parent_types as usize); + assert_eq!(substs.regions.len(), method.generics.parent_regions as usize); if self.mode == Mode::Path { return impl_ty; } - let mut placeholder; - let mut substs = substs; - if - !method.generics.types.is_empty_in(subst::FnSpace) || - !method.generics.regions.is_empty_in(subst::FnSpace) - { - // In general, during probe we erase regions. See - // `impl_self_ty()` for an explanation. - let method_regions = - method.generics.regions.get_slice(subst::FnSpace) - .iter() - .map(|_| ty::ReErased) - .collect(); - - placeholder = (*substs).clone().with_method(Vec::new(), method_regions); - - self.type_vars_for_defs( - self.span, - subst::FnSpace, - &mut placeholder, - method.generics.types.get_slice(subst::FnSpace)); - - substs = &placeholder; - } - // Erase any late-bound regions from the method and substitute // in the values from the substitution. let xform_self_ty = method.fty.sig.input(0); let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); - let xform_self_ty = xform_self_ty.subst(self.tcx, substs); - xform_self_ty + if method.generics.types.is_empty() && method.generics.regions.is_empty() { + xform_self_ty.subst(self.tcx, substs) + } else { + let substs = Substs::for_item(self.tcx, method.def_id, |def, _| { + if let Some(&r) = substs.regions.get(def.index as usize) { + r + } else { + // In general, during probe we erase regions. See + // `impl_self_ty()` for an explanation. + ty::ReErased + } + }, |def, cur_substs| { + if let Some(&ty) = substs.types.get(def.index as usize) { + ty + } else { + self.type_var_for_def(self.span, def, cur_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); - - let type_vars = - impl_pty.generics.types.map( - |_| self.next_ty_var()); + let impl_ty = self.tcx.lookup_item_type(impl_def_id).ty; - let region_placeholders = - impl_pty.generics.regions.map( - |_| ty::ReErased); // see erase_late_bound_regions() for an expl of why 'erased + let substs = Substs::for_item(self.tcx, impl_def_id, + |_, _| ty::ReErased, + |_, _| self.next_ty_var()); - let substs = subst::Substs::new(type_vars, region_placeholders); - (impl_pty.ty, substs) + (impl_ty, substs) } /// 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 54521782474fe..573dae46456ba 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, @@ -358,7 +356,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.did.is_local(), - ty::TyTrait(ref tr) => tr.principal_def_id().is_local(), + ty::TyTrait(ref tr) => tr.principal.def_id().is_local(), ty::TyParam(_) => true, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d985d3ccbea89..e573655b8c984 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,9 +88,8 @@ use hir::def::{Def, PathResolution}; use hir::def_id::DefId; use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; -use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace}; +use rustc::ty::subst::{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") }) { @@ -893,6 +886,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 {}", @@ -1300,6 +1294,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> { @@ -1333,7 +1333,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { .filter_map(|predicate| { match *predicate { ty::Predicate::Trait(ref data) => { - if data.0.self_ty().is_param(def.space, def.index) { + if data.0.self_ty().is_param(def.index) { Some(data.to_poly_trait_ref()) } else { None @@ -1357,27 +1357,15 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { trait_def.associated_type_names.contains(&assoc_name) } - fn ty_infer(&self, - ty_param_def: Option>, - substs: Option<&mut subst::Substs<'tcx>>, - space: Option, - span: Span) -> Ty<'tcx> { - // Grab the default doing subsitution - let default = ty_param_def.and_then(|def| { - def.default.map(|ty| type_variable::Default { - ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)), - origin_span: span, - def_id: def.default_def_id - }) - }); - - let ty_var = self.next_ty_var_with_default(default); + fn ty_infer(&self, _span: Span) -> Ty<'tcx> { + self.next_ty_var() + } - // Finally we add the type variable to the substs - match substs { - None => ty_var, - Some(substs) => { substs.types.push(space.unwrap(), ty_var); ty_var } - } + fn ty_infer_for_def(&self, + ty_param_def: &ty::TypeParameterDef<'tcx>, + substs: &Substs<'tcx>, + span: Span) -> Ty<'tcx> { + self.type_var_for_def(span, ty_param_def, substs) } fn projected_ty_from_poly_trait_ref(&self, @@ -1624,8 +1612,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { bounds: &ty::GenericPredicates<'tcx>) -> ty::InstantiatedPredicates<'tcx> { + let result = bounds.instantiate(self.tcx, substs); + let result = self.normalize_associated_types_in(span, &result.predicates); + debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", + bounds, + substs, + result); ty::InstantiatedPredicates { - predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates) + predicates: result } } @@ -1701,26 +1695,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(&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()); - let substs = self.tcx.mk_substs(substs); - 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 @@ -2784,22 +2776,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, // (potential) receiver for this impl did: DefId) -> TypeAndSubsts<'tcx> { - let tcx = self.tcx; + let ity = self.tcx.lookup_item_type(did); + debug!("impl_self_ty: ity={:?}", ity); - let ity = tcx.lookup_item_type(did); - let (tps, rps, raw_ty) = - (ity.generics.types.get_slice(subst::TypeSpace), - ity.generics.regions.get_slice(subst::TypeSpace), - ity.ty); - - debug!("impl_self_ty: tps={:?} rps={:?} raw_ty={:?}", tps, rps, raw_ty); - - let rps = self.region_vars_for_defs(span, rps); - let mut substs = subst::Substs::new( - VecPerParamSpace::empty(), - VecPerParamSpace::new(rps, Vec::new(), Vec::new())); - self.type_vars_for_defs(span, ParamSpace::TypeSpace, &mut substs, tps); - let substd_ty = self.instantiate_type_scheme(span, &substs, &raw_ty); + 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 } } @@ -3246,13 +3227,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); return None; } - Def::Variant(..) | Def::Struct(..) => { - Some(self.tcx.expect_variant_def(def)) + Def::Variant(type_did, _) | Def::Struct(type_did) => { + Some((type_did, self.tcx.expect_variant_def(def))) } - Def::TyAlias(did) | Def::AssociatedTy(_, did) => { + Def::TyAlias(did) => { if let Some(&ty::TyStruct(adt, _)) = self.tcx.opt_lookup_item_type(did) .map(|scheme| &scheme.ty.sty) { - Some(adt.struct_variant()) + Some((did, adt.struct_variant())) } else { None } @@ -3260,14 +3241,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => None }; - if let Some(variant) = variant { + if let Some((def_id, variant)) = variant { if variant.kind == ty::VariantKind::Tuple && !self.tcx.sess.features.borrow().relaxed_adts { emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic, "relaxed_adts", span, GateIssue::Language, "tuple structs and variants in struct patterns are unstable"); } - let ty = self.instantiate_type_path(def.def_id(), path, node_id); + let ty = self.instantiate_type_path(def_id, path, node_id); Some((variant, ty)) } else { struct_span_err!(self.tcx.sess, path.span, E0071, @@ -3466,10 +3447,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); @@ -4059,54 +4037,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 @@ -4180,54 +4123,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(!segments.is_empty()); let mut ufcs_associated = None; - let mut segment_spaces: Vec<_>; + let mut type_segment = None; + let mut fn_segment = None; match def { // Case 1 and 1b. Reference to a *type* or *enum variant*. - Def::SelfTy(..) | - Def::Struct(..) | - Def::Variant(..) | - Def::Enum(..) | - Def::TyAlias(..) | - Def::AssociatedTy(..) | - Def::Trait(..) | - Def::PrimTy(..) | - Def::TyParam(..) => { + Def::Struct(def_id) | + Def::Variant(_, def_id) | + Def::Enum(def_id) | + Def::TyAlias(def_id) | + Def::AssociatedTy(_, def_id) | + Def::Trait(def_id) => { // Everything but the final segment should have no // parameters at all. - segment_spaces = vec![None; segments.len() - 1]; - segment_spaces.push(Some(subst::TypeSpace)); + let mut generics = self.tcx.lookup_generics(def_id); + if let Some(def_id) = generics.parent { + // Variant and struct constructors use the + // generics of their parent type definition. + generics = self.tcx.lookup_generics(def_id); + } + type_segment = Some((segments.last().unwrap(), generics)); } // Case 2. Reference to a top-level value. - Def::Fn(..) | - Def::Const(..) | - Def::Static(..) => { - segment_spaces = vec![None; segments.len() - 1]; - segment_spaces.push(Some(subst::FnSpace)); - } - - // Case 3. Reference to a method. - Def::Method(def_id) => { - let container = self.tcx.impl_or_trait_item(def_id).container(); - match container { - ty::TraitContainer(trait_did) => { - callee::check_legal_trait_for_method_call(self.ccx, span, trait_did) - } - ty::ImplContainer(_) => {} - } - - if segments.len() >= 2 { - segment_spaces = vec![None; segments.len() - 2]; - segment_spaces.push(Some(subst::TypeSpace)); - segment_spaces.push(Some(subst::FnSpace)); - } else { - // `::method` will end up here, and so can `T::method`. - let self_ty = opt_self_ty.expect("UFCS sugared method missing Self"); - segment_spaces = vec![Some(subst::FnSpace)]; - ufcs_associated = Some((container, self_ty)); - } + Def::Fn(def_id) | + Def::Const(def_id) | + Def::Static(def_id, _) => { + fn_segment = Some((segments.last().unwrap(), + self.tcx.lookup_generics(def_id))); } + // Case 3. Reference to a method or associated const. + Def::Method(def_id) | Def::AssociatedConst(def_id) => { let container = self.tcx.impl_or_trait_item(def_id).container(); match container { @@ -4237,16 +4163,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::ImplContainer(_) => {} } + let generics = self.tcx.lookup_generics(def_id); if segments.len() >= 2 { - segment_spaces = vec![None; segments.len() - 2]; - segment_spaces.push(Some(subst::TypeSpace)); - segment_spaces.push(None); + let parent_generics = self.tcx.lookup_generics(generics.parent.unwrap()); + type_segment = Some((&segments[segments.len() - 2], parent_generics)); } else { - // `::CONST` will end up here, and so can `T::CONST`. - let self_ty = opt_self_ty.expect("UFCS sugared const missing Self"); - segment_spaces = vec![None]; + // `::assoc` will end up here, and so can `T::assoc`. + let self_ty = opt_self_ty.expect("UFCS sugared assoc missing Self"); ufcs_associated = Some((container, self_ty)); } + fn_segment = Some((segments.last().unwrap(), generics)); } // Other cases. Various nonsense that really shouldn't show up @@ -4254,52 +4180,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // elsewhere. (I hope) Def::Mod(..) | Def::ForeignMod(..) | + Def::PrimTy(..) | + Def::SelfTy(..) | + Def::TyParam(..) | Def::Local(..) | Def::Label(..) | - Def::Upvar(..) => { - segment_spaces = vec![None; segments.len()]; - } - - Def::Err => { - self.set_tainted_by_errors(); - segment_spaces = vec![None; segments.len()]; - } + Def::Upvar(..) | + Def::Err => {} } - assert_eq!(segment_spaces.len(), segments.len()); // In `>::method`, `A` and `B` are mandatory, but // `opt_self_ty` can also be Some for `Foo::method`, where Foo's // type parameters are not mandatory. let require_type_space = opt_self_ty.is_some() && ufcs_associated.is_none(); - debug!("segment_spaces={:?}", segment_spaces); - - // Next, examine the definition, and determine how many type - // parameters we expect from each space. - let type_defs = &type_scheme.generics.types; - let region_defs = &type_scheme.generics.regions; + debug!("type_segment={:?} fn_segment={:?}", type_segment, fn_segment); // Now that we have categorized what space the parameters for each // segment belong to, let's sort out the parameters that the user // provided (if any) into their appropriate spaces. We'll also report // errors if type parameters are provided in an inappropriate place. - let mut substs = Substs::empty(); - for (&opt_space, segment) in segment_spaces.iter().zip(segments) { - if let Some(space) = opt_space { - self.push_explicit_parameters_from_segment_to_substs(space, - span, - type_defs, - region_defs, - segment, - &mut substs); - } else { - self.tcx.prohibit_type_params(slice::ref_slice(segment)); - } - } - if let Some(self_ty) = opt_self_ty { - if type_defs.len(subst::SelfSpace) == 1 { - substs.types.push(subst::SelfSpace, self_ty); + let poly_segments = type_segment.is_some() as usize + + 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; } + _ => {} } // Now we have to compare the types that the user *actually* @@ -4308,20 +4223,88 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // variables. If the user provided some types, we may still need // to add defaults. If the user provided *too many* types, that's // a problem. - for &space in &[subst::SelfSpace, subst::TypeSpace, subst::FnSpace] { - self.adjust_type_parameters(span, space, type_defs, - require_type_space, &mut substs); - assert_eq!(substs.types.len(space), type_defs.len(space)); + self.check_path_parameter_count(span, !require_type_space, &mut type_segment); + self.check_path_parameter_count(span, true, &mut fn_segment); + + let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| { + let mut i = def.index as usize; + let type_regions = match (type_segment, fn_segment) { + (_, Some((_, generics))) => generics.parent_regions as usize, + (Some((_, generics)), None) => generics.regions.len(), + (None, None) => 0 + }; - self.adjust_region_parameters(span, space, region_defs, &mut substs); - assert_eq!(substs.regions.len(space), region_defs.len(space)); - } + let segment = if i < type_regions { + type_segment + } else { + i -= type_regions; + fn_segment + }; + let lifetimes = match segment.map(|(s, _)| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..], + Some(&hir::ParenthesizedParameters(_)) => bug!(), + None => &[] + }; + + if let Some(ast_lifetime) = lifetimes.get(i) { + ast_region_to_region(self.tcx, ast_lifetime) + } else { + self.region_var_for_def(span, def) + } + }, |def, substs| { + let mut i = def.index as usize; + let (type_types, has_self) = match (type_segment, fn_segment) { + (_, Some((_, generics))) => { + (generics.parent_types as usize, generics.has_self) + } + (Some((_, generics)), None) => { + (generics.types.len(), generics.has_self) + } + (None, None) => (0, false) + }; + + let can_omit = i >= type_types || !require_type_space; + let segment = if i < type_types { + // Handle Self first, so we can adjust the index to match the AST. + if has_self && i == 0 { + return opt_self_ty.unwrap_or_else(|| { + self.type_var_for_def(span, def, substs) + }); + } + i -= has_self as usize; + type_segment + } else { + i -= type_types; + fn_segment + }; + let types = match segment.map(|(s, _)| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => &data.types[..], + Some(&hir::ParenthesizedParameters(_)) => bug!(), + None => &[] + }; + + let omitted = can_omit && types.is_empty(); + if let Some(ast_ty) = types.get(i) { + // A provided type parameter. + self.to_ty(ast_ty) + } else if let (false, Some(default)) = (omitted, def.default) { + // No type parameter provided, but a default exists. + default.subst_spanned(self.tcx, substs, Some(span)) + } else { + // No type parameters were provided, we can infer all. + // This can also be reached in some error cases: + // We prefer to use inference variables instead of + // TyError to let type inference recover somewhat. + self.type_var_for_def(span, def, substs) + } + }); // 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_regions_escaping_depth(0)); - assert!(!type_scheme.has_escaping_regions()); + let scheme = self.tcx.lookup_item_type(def.def_id()); + let type_predicates = self.tcx.lookup_predicates(def.def_id()); + assert!(!substs.has_escaping_regions()); + assert!(!scheme.ty.has_escaping_regions()); // Add all the obligations that are required, substituting and // normalized appropriately. @@ -4332,7 +4315,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 { @@ -4341,10 +4324,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // type parameters, which we can infer by unifying the provided `Self` // with the substituted impl type. let impl_scheme = self.tcx.lookup_item_type(impl_def_id); - assert_eq!(substs.types.len(subst::TypeSpace), - impl_scheme.generics.types.len(subst::TypeSpace)); - assert_eq!(substs.regions.len(subst::TypeSpace), - impl_scheme.generics.regions.len(subst::TypeSpace)); let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty); match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) { @@ -4371,243 +4350,83 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty_substituted } - /// Finds the parameters that the user provided and adds them to `substs`. If too many - /// parameters are provided, then reports an error and clears the output vector. - /// - /// We clear the output vector because that will cause the `adjust_XXX_parameters()` later to - /// use inference variables. This seems less likely to lead to derived errors. - /// - /// Note that we *do not* check for *too few* parameters here. Due to the presence of defaults - /// etc that is more complicated. I wanted however to do the reporting of *too many* parameters - /// here because we can easily use the precise span of the N+1'th parameter. - fn push_explicit_parameters_from_segment_to_substs(&self, - space: subst::ParamSpace, - span: Span, - type_defs: &VecPerParamSpace>, - region_defs: &VecPerParamSpace, - segment: &hir::PathSegment, - substs: &mut Substs<'tcx>) - { - match segment.parameters { - hir::AngleBracketedParameters(ref data) => { - self.push_explicit_angle_bracketed_parameters_from_segment_to_substs( - space, type_defs, region_defs, data, substs); + /// Report errors if the provided parameters are too few or too many. + fn check_path_parameter_count(&self, + span: Span, + can_omit: bool, + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>) { + let (lifetimes, types, bindings) = match segment.map(|(s, _)| &s.parameters) { + Some(&hir::AngleBracketedParameters(ref data)) => { + (&data.lifetimes[..], &data.types[..], &data.bindings[..]) } - - hir::ParenthesizedParameters(ref data) => { - span_err!(self.tcx.sess, span, E0238, - "parenthesized parameters may only be used with a trait"); - self.push_explicit_parenthesized_parameters_from_segment_to_substs( - space, span, type_defs, data, substs); + Some(&hir::ParenthesizedParameters(_)) => { + span_bug!(span, "parenthesized parameters cannot appear in ExprPath"); } - } - } + None => (&[][..], &[][..], &[][..]) + }; - fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(&self, - space: subst::ParamSpace, - type_defs: &VecPerParamSpace>, - region_defs: &VecPerParamSpace, - data: &hir::AngleBracketedParameterData, - substs: &mut Substs<'tcx>) - { - { - let type_count = type_defs.len(space); - assert_eq!(substs.types.len(space), 0); - for (i, typ) in data.types.iter().enumerate() { - let t = self.to_ty(&typ); - if i < type_count { - substs.types.push(space, t); - } else if i == type_count { - struct_span_err!(self.tcx.sess, typ.span, E0087, - "too many type parameters provided: \ - expected at most {} parameter{}, \ - found {} parameter{}", - type_count, - if type_count == 1 {""} else {"s"}, - data.types.len(), - if data.types.len() == 1 {""} else {"s"}) - .span_label(typ.span , &format!("expected {} parameter{}", - type_count, - if type_count == 1 {""} else {"s"})).emit(); - substs.types.truncate(space, 0); - break; - } - } - } + let count = |n| { + format!("{} parameter{}", n, if n == 1 { "" } else { "s" }) + }; - if !data.bindings.is_empty() { - span_err!(self.tcx.sess, data.bindings[0].span, E0182, - "unexpected binding of associated item in expression path \ - (only allowed in type paths)"); + // Check provided lifetime parameters. + let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); + if lifetimes.len() > lifetime_defs.len() { + let span = lifetimes[lifetime_defs.len()].span; + span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())); + } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { + span_err!(self.tcx.sess, span, E0090, + "too few lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())); } - { - let region_count = region_defs.len(space); - assert_eq!(substs.regions.len(space), 0); - for (i, lifetime) in data.lifetimes.iter().enumerate() { - let r = ast_region_to_region(self.tcx, lifetime); - if i < region_count { - substs.regions.push(space, r); - } else if i == region_count { - span_err!(self.tcx.sess, lifetime.span, E0088, - "too many lifetime parameters provided: \ - expected {} parameter{}, found {} parameter{}", - region_count, - if region_count == 1 {""} else {"s"}, - data.lifetimes.len(), - if data.lifetimes.len() == 1 {""} else {"s"}); - substs.regions.truncate(space, 0); - break; - } + // Check provided type parameters. + let type_defs = segment.map_or(&[][..], |(_, generics)| { + if generics.parent.is_none() { + &generics.types[generics.has_self as usize..] + } else { + &generics.types } - } - } - - /// As with - /// `push_explicit_angle_bracketed_parameters_from_segment_to_substs`, - /// but intended for `Foo(A,B) -> C` form. This expands to - /// roughly the same thing as `Foo<(A,B),C>`. One important - /// difference has to do with the treatment of anonymous - /// regions, which are translated into bound regions (NYI). - fn push_explicit_parenthesized_parameters_from_segment_to_substs(&self, - space: subst::ParamSpace, - span: Span, - type_defs: &VecPerParamSpace>, - data: &hir::ParenthesizedParameterData, - substs: &mut Substs<'tcx>) - { - let type_count = type_defs.len(space); - if type_count < 2 { - span_err!(self.tcx.sess, span, E0167, - "parenthesized form always supplies 2 type parameters, \ - but only {} parameter(s) were expected", - type_count); - } - - let input_tys: Vec = - data.inputs.iter().map(|ty| self.to_ty(&ty)).collect(); - - let tuple_ty = self.tcx.mk_tup(input_tys); - - if type_count >= 1 { - substs.types.push(space, tuple_ty); - } - - let output_ty: Option = - data.output.as_ref().map(|ty| self.to_ty(&ty)); - - let output_ty = - output_ty.unwrap_or(self.tcx.mk_nil()); - - if type_count >= 2 { - substs.types.push(space, output_ty); - } - } - - fn adjust_type_parameters(&self, - span: Span, - space: ParamSpace, - defs: &VecPerParamSpace>, - require_type_space: bool, - substs: &mut Substs<'tcx>) - { - let provided_len = substs.types.len(space); - let desired = defs.get_slice(space); - let required_len = desired.iter() - .take_while(|d| d.default.is_none()) - .count(); - - debug!("adjust_type_parameters(space={:?}, \ - provided_len={}, \ - desired_len={}, \ - required_len={})", - space, - provided_len, - desired.len(), - required_len); - - // Enforced by `push_explicit_parameters_from_segment_to_substs()`. - assert!(provided_len <= desired.len()); - - // Nothing specified at all: supply inference variables for - // everything. - if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) { - substs.types.replace(space, Vec::new()); - self.type_vars_for_defs(span, space, substs, &desired[..]); - return; - } - - // Too few parameters specified: report an error and use Err - // for everything. - if provided_len < required_len { + }); + let required_len = type_defs.iter() + .take_while(|d| d.default.is_none()) + .count(); + if types.len() > type_defs.len() { + let span = types[type_defs.len()].span; + struct_span_err!(self.tcx.sess, span, E0087, + "too many type parameters provided: \ + expected at most {}, found {}", + count(type_defs.len()), + count(types.len())) + .span_label(span, &format!("expected {}", + count(type_defs.len()))).emit(); + + // To prevent derived errors to accumulate due to extra + // type parameters, we force instantiate_value_path to + // use inference variables instead of the provided types. + *segment = None; + } else if !(can_omit && types.len() == 0) && types.len() < required_len { let qualifier = - if desired.len() != required_len { "at least " } else { "" }; + if type_defs.len() != required_len { "at least " } else { "" }; span_err!(self.tcx.sess, span, E0089, - "too few type parameters provided: expected {}{} parameter{}, \ - found {} parameter{}", - qualifier, required_len, - if required_len == 1 {""} else {"s"}, - provided_len, - if provided_len == 1 {""} else {"s"}); - substs.types.replace(space, vec![self.tcx.types.err; desired.len()]); - return; - } - - // Otherwise, add in any optional parameters that the user - // omitted. The case of *too many* parameters is handled - // already by - // push_explicit_parameters_from_segment_to_substs(). Note - // that the *default* type are expressed in terms of all prior - // parameters, so we have to substitute as we go with the - // partial substitution that we have built up. - for i in provided_len..desired.len() { - let default = desired[i].default.unwrap(); - let default = default.subst_spanned(self.tcx, substs, Some(span)); - substs.types.push(space, default); + "too few type parameters provided: \ + expected {}{}, found {}", + qualifier, + count(required_len), + count(types.len())); } - assert_eq!(substs.types.len(space), desired.len()); - - debug!("Final substs: {:?}", substs); - } - - fn adjust_region_parameters(&self, - span: Span, - space: ParamSpace, - defs: &VecPerParamSpace, - substs: &mut Substs) - { - let provided_len = substs.regions.len(space); - let desired = defs.get_slice(space); - // Enforced by `push_explicit_parameters_from_segment_to_substs()`. - assert!(provided_len <= desired.len()); - - // If nothing was provided, just use inference variables. - if provided_len == 0 { - substs.regions.replace( - space, - self.region_vars_for_defs(span, desired)); - return; - } - - // If just the right number were provided, everybody is happy. - if provided_len == desired.len() { - return; + if !bindings.is_empty() { + span_err!(self.tcx.sess, bindings[0].span, E0182, + "unexpected binding of associated item in expression path \ + (only allowed in type paths)"); } - - // Otherwise, too few were provided. Report an error and then - // use inference variables. - span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: expected {} parameter{}, \ - found {} parameter{}", - desired.len(), - if desired.len() == 1 {""} else {"s"}, - provided_len, - if provided_len == 1 {""} else {"s"}); - - substs.regions.replace( - space, - self.region_vars_for_defs(span, desired)); } fn structurally_resolve_type_or_else(&self, sp: Span, ty: Ty<'tcx>, f: F) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 22ffcfbaae111..859d5ff0543d0 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -824,11 +824,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } /*From:*/ (_, - /*To: */ &ty::TyTrait(box ty::TraitTy { ref bounds, .. })) => { + /*To: */ &ty::TyTrait(ref obj)) => { // When T is existentially quantified as a trait // `Foo+'to`, it must outlive the region bound `'to`. self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), - from_ty, bounds.region_bound); + from_ty, obj.region_bound); } /*From:*/ (&ty::TyBox(from_referent_ty), @@ -1571,10 +1571,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // the problem is to add `T: 'r`, which isn't true. So, if there are no // inference variables, we use a verify constraint instead of adding // edges, which winds up enforcing the same condition. - let needs_infer = { - projection_ty.trait_ref.substs.types.iter().any(|t| t.needs_infer()) || - projection_ty.trait_ref.substs.regions.iter().any(|r| r.needs_infer()) - }; + let needs_infer = projection_ty.trait_ref.needs_infer(); if env_bounds.is_empty() && needs_infer { debug!("projection_must_outlive: no declared bounds"); @@ -1757,6 +1754,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // // we can thus deduce that `>::SomeType : 'a`. let trait_predicates = self.tcx.lookup_predicates(projection_ty.trait_ref.def_id); + assert_eq!(trait_predicates.parent, None); let predicates = trait_predicates.predicates.as_slice().to_vec(); traits::elaborate_predicates(self.tcx, predicates) .filter_map(|predicate| { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4bb9f4fd332f2..7ed4b2bcb1918 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -14,13 +14,11 @@ use CrateCtxt; use hir::def_id::DefId; use middle::region::{CodeExtent}; use rustc::infer::TypeOrigin; -use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; use std::collections::HashSet; use syntax::ast; -use syntax::parse::token::keywords; use syntax_pos::Span; use errors::DiagnosticBuilder; @@ -455,13 +453,14 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let item_def_id = self.tcx().map.local_def_id(item.id); let ty_predicates = self.tcx().lookup_predicates(item_def_id); + assert_eq!(ty_predicates.parent, None); let variances = self.tcx().item_variances(item_def_id); let mut constrained_parameters: HashSet<_> = variances.types - .iter_enumerated() - .filter(|&(_, _, &variance)| variance != ty::Bivariant) - .map(|(space, index, _)| self.param_ty(ast_generics, space, index)) + .iter().enumerate() + .filter(|&(_, &variance)| variance != ty::Bivariant) + .map(|(index, _)| self.param_ty(ast_generics, index)) .map(|p| Parameter::Type(p)) .collect(); @@ -469,53 +468,30 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { None, &mut constrained_parameters); - for (space, index, _) in variances.types.iter_enumerated() { - let param_ty = self.param_ty(ast_generics, space, index); + for (index, _) in variances.types.iter().enumerate() { + let param_ty = self.param_ty(ast_generics, index); if constrained_parameters.contains(&Parameter::Type(param_ty)) { continue; } - let span = self.ty_param_span(ast_generics, item, space, index); + let span = ast_generics.ty_params[index].span; self.report_bivariance(span, param_ty.name); } - for (space, index, &variance) in variances.regions.iter_enumerated() { + for (index, &variance) in variances.regions.iter().enumerate() { if variance != ty::Bivariant { continue; } - assert_eq!(space, TypeSpace); let span = ast_generics.lifetimes[index].lifetime.span; let name = ast_generics.lifetimes[index].lifetime.name; self.report_bivariance(span, name); } } - fn param_ty(&self, - ast_generics: &hir::Generics, - space: ParamSpace, - index: usize) - -> ty::ParamTy - { - let name = match space { - TypeSpace => ast_generics.ty_params[index].name, - SelfSpace => keywords::SelfType.name(), - FnSpace => bug!("Fn space occupied?"), - }; - - ty::ParamTy { space: space, idx: index as u32, name: name } - } - - fn ty_param_span(&self, - ast_generics: &hir::Generics, - item: &hir::Item, - space: ParamSpace, - index: usize) - -> Span - { - match space { - TypeSpace => ast_generics.ty_params[index].span, - SelfSpace => item.span, - FnSpace => span_bug!(item.span, "Fn space occupied?"), + fn param_ty(&self, ast_generics: &hir::Generics, index: usize) -> ty::ParamTy { + ty::ParamTy { + idx: index as u32, + name: ast_generics.ty_params[index].name } } @@ -542,10 +518,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) { - let impl_params = generics.types.get_slice(subst::TypeSpace).iter() - .map(|tp| tp.name).collect::>(); + let parent = tcx.lookup_generics(generics.parent.unwrap()); + let impl_params: HashSet<_> = parent.types.iter().map(|tp| tp.name).collect(); - for method_param in generics.types.get_slice(subst::FnSpace) { + for method_param in &generics.types { if impl_params.contains(&method_param.name) { error_194(tcx, span, method_param.name); } @@ -621,7 +597,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait impl: take implied bounds from all types that // appear in the trait reference. let trait_ref = self.instantiate_type_scheme(span, free_substs, trait_ref); - trait_ref.substs.types.as_slice().to_vec() + trait_ref.substs.types.to_vec() } None => { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 5f8861f309948..cfc1292c34b78 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,19 @@ 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 (i, r) in free_substs.regions.iter().enumerate() { + match *r { + ty::ReFree(ty::FreeRegion { + bound_region: ty::BoundRegion::BrNamed(def_id, name, _), .. + }) => { + let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion { + 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 +296,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 +343,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/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 9b26e95f7fa55..4a1e401f9820f 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -17,7 +17,7 @@ use hir::def_id::DefId; use middle::lang_items::UnsizeTraitLangItem; -use rustc::ty::subst::{self, Subst}; +use rustc::ty::subst::Subst; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::traits::{self, Reveal}; use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId}; @@ -75,7 +75,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } TyTrait(ref t) => { - Some(t.principal_def_id()) + Some(t.principal.def_id()) } TyBox(_) => { @@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let source = tcx.lookup_item_type(impl_did).ty; let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap(); - let target = *trait_ref.substs.types.get(subst::TypeSpace, 0); + let target = trait_ref.substs.types[1]; debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index e426f0cb643b7..97aed4d5e82f9 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -80,7 +80,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { self.check_def_id(item, def.did); } ty::TyTrait(ref data) => { - self.check_def_id(item, data.principal_def_id()); + self.check_def_id(item, data.principal.def_id()); } ty::TyBox(..) => { match self.tcx.lang_items.require_owned_box() { diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 46a9ef8d5babb..f60fb9583a661 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -168,14 +168,14 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if !self.tcx.is_object_safe(data.principal_def_id()) { + if !self.tcx.is_object_safe(data.principal.def_id()) { // This is an error, but it will be // reported by wfcheck. Ignore it // here. This is tested by // `coherence-impl-trait-for-trait-object-safe.rs`. } else { let mut supertrait_def_ids = - traits::supertrait_def_ids(self.tcx, data.principal_def_id()); + traits::supertrait_def_ids(self.tcx, data.principal.def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { span_err!(self.tcx.sess, item.span, E0371, "the object type `{}` automatically \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d38065f4f1238..ed406b9379e35 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, VecPerParamSpace}; +use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::{VariantKind}; @@ -85,7 +85,6 @@ use std::rc::Rc; use syntax::{abi, ast, attr}; use syntax::parse::token::keywords; -use syntax::ptr::P; use syntax_pos::Span; use rustc::hir::{self, intravisit, map as hir_map, print as pprust}; @@ -120,6 +119,7 @@ struct ItemCtxt<'a,'tcx:'a> { #[derive(Copy, Clone, PartialEq, Eq)] pub enum AstConvRequest { + GetGenerics(DefId), GetItemTypeScheme(DefId), GetTraitDef(DefId), EnsureSuperPredicates(DefId), @@ -187,6 +187,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 +210,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 +233,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 +306,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> { @@ -362,11 +373,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { None } - fn ty_infer(&self, - _ty_param_def: Option>, - _substs: Option<&mut Substs<'tcx>>, - _space: Option, - span: Span) -> Ty<'tcx> { + fn ty_infer(&self, span: Span) -> Ty<'tcx> { struct_span_err!( self.tcx().sess, span, @@ -452,35 +459,38 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for () { impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { fn get_type_parameter_bounds(&self, astconv: &AstConv<'tcx, 'tcx>, - _span: Span, + span: Span, node_id: ast::NodeId) -> Vec> { let def = astconv.tcx().type_parameter_def(node_id); - self.predicates - .iter() - .filter(|predicate| { - match **predicate { - ty::Predicate::Trait(ref data) => { - data.skip_binder().self_ty().is_param(def.space, def.index) - } - ty::Predicate::TypeOutlives(ref data) => { - data.skip_binder().0.is_param(def.space, def.index) - } - ty::Predicate::Rfc1592(..) | - ty::Predicate::Equate(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::WellFormed(..) | - ty::Predicate::ObjectSafe(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::Projection(..) => { - false - } + let mut results = self.parent.map_or(vec![], |def_id| { + let parent = astconv.tcx().lookup_predicates(def_id); + parent.get_type_parameter_bounds(astconv, span, node_id) + }); + + results.extend(self.predicates.iter().filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref data) => { + data.skip_binder().self_ty().is_param(def.index) } - }) - .cloned() - .collect() + ty::Predicate::TypeOutlives(ref data) => { + data.skip_binder().0.is_param(def.index) + } + ty::Predicate::Rfc1592(..) | + ty::Predicate::Equate(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::WellFormed(..) | + ty::Predicate::ObjectSafe(..) | + ty::Predicate::ClosureKind(..) | + ty::Predicate::Projection(..) => { + false + } + } + }).cloned()); + + results } } @@ -538,7 +548,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let path_res = tcx.expect_resolution(ast_ty.id); match path_res.base_def { Def::SelfTy(Some(def_id), None) | - Def::TyParam(_, _, def_id, _) if path_res.depth == 0 => { + Def::TyParam(def_id) if path_res.depth == 0 => { def_id == tcx.map.local_def_id(param_id) } _ => false @@ -548,7 +558,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, @@ -557,25 +566,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); + ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false); 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, @@ -586,16 +592,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); @@ -605,7 +609,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>) @@ -617,7 +621,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), @@ -633,8 +637,12 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty: ty::Ty<'tcx>, has_value: bool) { + let predicates = ty::GenericPredicates { + parent: Some(container.id()), + predicates: vec![] + }; ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id), - ty::GenericPredicates::empty()); + predicates); write_ty_to_tcx(ccx, id, ty); @@ -713,8 +721,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, @@ -726,7 +735,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { AstConv::instantiate_mono_trait_ref(&ccx.icx(&()), &ExplicitRscope, ast_trait_ref, - None); + tcx.mk_self_type()); tcx.record_trait_has_default_impl(trait_ref.def_id); @@ -741,8 +750,9 @@ 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 mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); + let ty_generics = generics_of_def_id(ccx, def_id); + let mut ty_predicates = + ty_generic_predicates(ccx, generics, None, vec![], false); debug!("convert: impl_bounds={:?}", ty_predicates); @@ -750,13 +760,13 @@ 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), &ExplicitRscope, ast_trait_ref, - Some(selfty)) + selfty) }); tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref); @@ -791,11 +801,13 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { } if let hir::ImplItemKind::Const(ref ty, _) = impl_item.node { + let const_def_id = ccx.tcx.map.local_def_id(impl_item.id); + let ty_generics = generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&ty_predicates) .to_ty(&ExplicitRscope, &ty); - tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id), + tcx.register_item_type(const_def_id, TypeScheme { - generics: ty_generics.clone(), + generics: ty_generics, ty: ty, }); // Trait-associated constants are always public. @@ -833,7 +845,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,11 +868,13 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the associated constants. for trait_item in trait_items { if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node { + let const_def_id = ccx.tcx.map.local_def_id(trait_item.id); + let ty_generics = generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&trait_predicates) .to_ty(&ExplicitRscope, ty); - tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id), + tcx.register_item_type(const_def_id, TypeScheme { - generics: trait_def.generics.clone(), + generics: ty_generics, ty: ty, }); convert_associated_const(ccx, @@ -902,7 +916,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { sig, hir::Defaultness::Default, tcx.mk_self_type(), - &trait_def.generics, &trait_predicates); } @@ -921,11 +934,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) @@ -937,15 +950,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); }, } } @@ -956,6 +968,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); + generics_of_def_id(ccx, def_id); let ctor_ty = match variant.kind { VariantKind::Unit | VariantKind::Struct => scheme.ty, VariantKind::Tuple => { @@ -964,8 +978,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, @@ -978,12 +992,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>, @@ -1185,9 +1195,8 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // generic types: let trait_def = trait_def_of_item(ccx, item); let self_predicate = ty::GenericPredicates { - predicates: VecPerParamSpace::new(vec![], - vec![trait_def.trait_ref.to_predicate()], - vec![]) + parent: None, + predicates: vec![trait_def.trait_ref.to_predicate()] }; let scope = &(generics, &self_predicate); @@ -1209,7 +1218,8 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2).collect(); let superpredicates = ty::GenericPredicates { - predicates: VecPerParamSpace::new(superbounds, vec![], vec![]) + parent: None, + predicates: superbounds }; debug!("superpredicates for trait {:?} = {:?}", tcx.map.local_def_id(item.id), @@ -1243,7 +1253,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"), }; @@ -1259,9 +1271,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 { @@ -1270,51 +1281,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, @@ -1363,23 +1337,23 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) // but to get the full set of predicates on a trait we need to add // in the supertrait bounds and anything declared on the // associated types. - let mut base_predicates = super_predicates; + let mut base_predicates = super_predicates.predicates; // Add in a predicate that `Self:Trait` (where `Trait` is the // current trait). This is needed for builtin bounds. let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate(); - base_predicates.predicates.push(SelfSpace, self_predicate); + base_predicates.push(self_predicate); // add in the explicit where-clauses let mut trait_predicates = - ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates); + ty_generic_predicates(ccx, generics, None, base_predicates, true); let assoc_predicates = predicates_for_associated_types(ccx, generics, &trait_predicates, trait_def.trait_ref, items); - trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter()); + trait_predicates.predicates.extend(assoc_predicates); let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates); assert!(prev_predicates.is_none()); @@ -1416,192 +1390,262 @@ 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 node = tcx.map.get(node_id); + let parent_def_id = match node { + NodeImplItem(_) | + NodeTraitItem(_) | + NodeVariant(_) | + NodeStructCtor(_) => { + let parent_id = tcx.map.get_parent(node_id); + Some(tcx.map.local_def_id(parent_id)) } - Some(hir_map::NodeForeignItem(foreign_item)) => { - let abi = ccx.tcx.map.get_foreign_abi(node_id); - type_scheme_of_foreign_item(ccx, &foreign_item, abi) + _ => None + }; + + let mut opt_self = None; + let mut allow_defaults = false; + + let no_generics = hir::Generics::empty(); + let ast_generics = match node { + NodeTraitItem(item) => { + match item.node { + MethodTraitItem(ref sig, _) => &sig.generics, + _ => &no_generics + } } - x => { - bug!("unexpected sort of node in get_item_type_scheme(): {:?}", - x); + + NodeImplItem(item) => { + match item.node { + ImplItemKind::Method(ref sig, _) => &sig.generics, + _ => &no_generics + } } + + NodeItem(item) => { + match item.node { + ItemFn(_, _, _, _, ref generics, _) | + ItemImpl(_, _, ref generics, _, _, _) => generics, + + ItemTy(_, ref generics) | + ItemEnum(_, ref generics) | + ItemStruct(_, ref generics) => { + allow_defaults = true; + 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 { + 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; + generics + } + + _ => &no_generics + } + } + + NodeForeignItem(item) => { + match item.node { + ForeignItemStatic(..) => &no_generics, + ForeignItemFn(_, ref generics) => generics + } + } + + _ => &no_generics + }; + + let has_self = opt_self.is_some(); + let mut parent_has_self = false; + let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| { + let generics = generics_of_def_id(ccx, def_id); + assert_eq!(generics.parent, None); + assert_eq!(generics.parent_regions, 0); + assert_eq!(generics.parent_types, 0); + assert_eq!(has_self, false); + parent_has_self = generics.has_self; + (generics.regions.len() as u32, generics.types.len() as u32) + }); + + 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, + index: parent_regions + 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, p)| { + let i = parent_types + has_self as u32 + i as u32; + get_or_create_type_parameter_def(ccx, ast_generics, i, p, allow_defaults) + }); + let types: Vec<_> = opt_self.into_iter().chain(types).collect(); + + // Debugging aid. + if tcx.has_attr(def_id, "rustc_object_lifetime_default") { + let object_lifetime_default_reprs: String = + types.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); } - } else { - ccx.tcx.lookup_item_type(def_id) - } + + tcx.alloc_generics(ty::Generics { + parent: parent_def_id, + parent_regions: parent_regions as u32, + parent_types: parent_types as u32, + regions: regions, + types: types, + has_self: has_self || parent_has_self + }) + }) } -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 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); + + 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 type_of_def_id(): {:?}", x); + } + }; + + write_ty_to_tcx(ccx, node_id, ty); + ty }) } -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 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 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; + -> ty::GenericPredicates<'tcx> { + let def_id = ccx.tcx.map.local_def_id(it.id); - let tag = type_scheme_of_item(ccx, it); - let scheme = TypeScheme { generics: tag.generics, ty: tag.ty }; - let predicates = match it.node { - hir::ItemStatic(..) | hir::ItemConst(..) => { - ty::GenericPredicates::empty() - } - 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::ItemStruct(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } - hir::ItemDefaultImpl(..) | - hir::ItemTrait(..) | - hir::ItemExternCrate(..) | - hir::ItemUse(..) | - hir::ItemImpl(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) => { - span_bug!( - it.span, - "compute_type_scheme_of_item: unexpected item type: {:?}", - it.node); - } + let no_generics = hir::Generics::empty(); + let generics = match it.node { + hir::ItemFn(_, _, _, _, ref generics, _) | + hir::ItemTy(_, ref generics) | + hir::ItemEnum(_, ref generics) | + hir::ItemStruct(_, ref generics) => generics, + _ => &no_generics }; - let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - predicates.clone()); + let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); + 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.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>, @@ -1611,95 +1655,20 @@ 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) => { - ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty()) - } - hir::ForeignItemStatic(..) => { - ty::GenericPredicates::empty() - } + let no_generics = hir::Generics::empty(); + let generics = match it.node { + hir::ForeignItemFn(_, ref generics) => generics, + hir::ForeignItemStatic(..) => &no_generics }; - let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - predicates); + let predicates = ty_generic_predicates(ccx, generics, None, vec![], false); + 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> -{ - 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>) - -> ty::GenericPredicates<'tcx> -{ - ty_generic_predicates(ccx, FnSpace, generics, base_predicates) -} - // Add the Sized bound, unless the type parameter is marked as `?Sized`. fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, bounds: &mut ty::BuiltinBounds, @@ -1765,27 +1734,46 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>( } fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - space: ParamSpace, ast_generics: &hir::Generics, - base_predicates: &ty::GenericPredicates<'tcx>) + parent: Option, + super_predicates: Vec>, + has_self: bool) -> ty::GenericPredicates<'tcx> { let tcx = ccx.tcx; - let mut result = base_predicates.clone(); + let (parent_regions, parent_types) = parent.map_or((0, 0), |def_id| { + let generics = generics_of_def_id(ccx, def_id); + assert_eq!(generics.parent, None); + assert_eq!(generics.parent_regions, 0); + assert_eq!(generics.parent_types, 0); + (generics.regions.len() as u32, generics.types.len() as u32) + }); + let ref base_predicates = match parent { + Some(def_id) => { + assert_eq!(super_predicates, vec![]); + tcx.lookup_predicates(def_id) + } + None => { + ty::GenericPredicates { + parent: None, + predicates: super_predicates.clone() + } + } + }; + let mut predicates = super_predicates; // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for (index, param) in ast_generics.ty_params.iter().enumerate() { - let index = index as u32; - let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx); + let index = parent_types + has_self as u32 + index as u32; + let param_ty = ty::ParamTy::new(index, param.name).to_ty(ccx.tcx); let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)), param_ty, ¶m.bounds, SizedByDefault::Yes, None, param.span); - let predicates = bounds.predicates(ccx.tcx, param_ty); - result.predicates.extend(space, predicates.into_iter()); + predicates.extend(bounds.predicates(ccx.tcx, param_ty)); } // Collect the region predicates that were declared inline as @@ -1793,17 +1781,16 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, // have to be careful to only iterate over early-bound regions. let early_lifetimes = early_bound_lifetimes_from_generics(ccx, ast_generics); for (index, param) in early_lifetimes.iter().enumerate() { - let index = index as u32; + let index = parent_regions + index as u32; let region = ty::ReEarlyBound(ty::EarlyBoundRegion { - space: space, index: index, name: param.lifetime.name }); for bound in ¶m.bounds { let bound_region = ast_region_to_region(ccx.tcx, bound); let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); - result.predicates.push(space, outlives.to_predicate()); + predicates.push(outlives.to_predicate()); } } @@ -1822,22 +1809,24 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, let mut projections = Vec::new(); let trait_ref = - conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)), - ty, - poly_trait_ref, - &mut projections); + AstConv::instantiate_poly_trait_ref(&ccx.icx(&(base_predicates, + ast_generics)), + &ExplicitRscope, + poly_trait_ref, + ty, + &mut projections); - result.predicates.push(space, trait_ref.to_predicate()); + predicates.push(trait_ref.to_predicate()); for projection in &projections { - result.predicates.push(space, projection.to_predicate()); + predicates.push(projection.to_predicate()); } } &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { let region = ast_region_to_region(tcx, lifetime); let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); - result.predicates.push(space, ty::Predicate::TypeOutlives(pred)) + predicates.push(ty::Predicate::TypeOutlives(pred)) } } } @@ -1848,7 +1837,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ®ion_pred.bounds { let r2 = ast_region_to_region(tcx, bound); let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); - result.predicates.push(space, ty::Predicate::RegionOutlives(pred)) + predicates.push(ty::Predicate::RegionOutlives(pred)) } } @@ -1861,89 +1850,27 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } - return 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); + ty::GenericPredicates { + parent: parent, + predicates: predicates } - - 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, - index: u32) - -> Ty<'tcx> -{ - let ty = AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path); - - for leaf_ty in ty.walk() { - if let ty::TyParam(p) = leaf_ty.sty { - if p.space == space && p.idx >= index { - struct_span_err!(ccx.tcx.sess, path.span, E0128, - "type parameters with a default cannot use \ - forward declared identifiers") - .span_label(path.span, &format!("defaulted type parameters \ - cannot be forward declared")) - .emit(); - - return ccx.tcx.types.err - } - } - } - - ty } fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ast_generics: &hir::Generics, - space: ParamSpace, index: u32, + param: &hir::TyParam, allow_defaults: bool) -> ty::TypeParameterDef<'tcx> { - let param = &ast_generics.ty_params[index as usize]; - let tcx = ccx.tcx; match tcx.ty_param_defs.borrow().get(¶m.id) { Some(d) => { return d.clone(); } None => { } } - let default = param.default.as_ref().map( - |def| convert_default_type_parameter(ccx, def, space, index) - ); + let default = + param.default.as_ref().map(|def| ccx.icx(&()).to_ty(&ExplicitRscope, def)); let object_lifetime_default = compute_object_lifetime_default(ccx, param.id, @@ -1963,7 +1890,6 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } let def = ty::TypeParameterDef { - space: space, index: index, name: param.name, def_id: ccx.tcx.map.local_def_id(param.id), @@ -1972,8 +1898,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, object_lifetime_default: object_lifetime_default, }; + if def.name == keywords::SelfType.name() { + span_bug!(param.span, "`Self` should not be the name of a regular parameter"); + } + tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone()); + debug!("get_or_create_type_parameter_def: def for type param: {:?}", def); + def } @@ -2076,7 +2008,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| { astconv.instantiate_poly_trait_ref(&rscope, bound, - Some(param_ty), + param_ty, &mut projection_bounds) }).collect(); @@ -2107,7 +2039,10 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, match *bound { hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => { let mut projections = Vec::new(); - let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections); + let pred = astconv.instantiate_poly_trait_ref(&ExplicitRscope, + tr, + param_ty, + &mut projections); projections.into_iter() .map(|p| p.to_predicate()) .chain(Some(pred.to_predicate())) @@ -2124,29 +2059,14 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, - param_ty: Ty<'tcx>, - trait_ref: &hir::PolyTraitRef, - projections: &mut Vec>) - -> ty::PolyTraitRef<'tcx> -{ - AstConv::instantiate_poly_trait_ref(astconv, - &ExplicitRscope, - trait_ref, - Some(param_ty), - projections) -} - -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() @@ -2182,48 +2102,43 @@ 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)); - - let regions = - ty_generics.regions.map( - |def| def.to_early_bound_region()); +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?") + } - 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 fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - ast_generics: &hir::Generics, + generics: &hir::Generics, impl_predicates: &mut ty::GenericPredicates<'tcx>, impl_def_id: DefId) { let impl_scheme = ccx.tcx.lookup_item_type(impl_def_id); let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id); - assert!(impl_predicates.predicates.is_empty_in(FnSpace)); - assert!(impl_predicates.predicates.is_empty_in(SelfSpace)); - // The trait reference is an input, so find all type parameters // reachable from there, to start (if this is an inherent impl, // then just examine the self type). @@ -2233,16 +2148,15 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, input_parameters.extend(ctp::parameters_for(trait_ref, false)); } - ctp::setup_constraining_predicates(impl_predicates.predicates.get_mut_slice(TypeSpace), + ctp::setup_constraining_predicates(&mut impl_predicates.predicates, impl_trait_ref, &mut input_parameters); - for (index, ty_param) in ast_generics.ty_params.iter().enumerate() { - let param_ty = ty::ParamTy { space: TypeSpace, - idx: index as u32, - name: ty_param.name }; + let ty_generics = generics_of_def_id(ccx, impl_def_id); + for (ty_param, param) in ty_generics.types.iter().zip(&generics.ty_params) { + let param_ty = ty::ParamTy::for_def(ty_param); if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) { - report_unused_parameter(ccx, ty_param.span, "type", ¶m_ty.to_string()); + report_unused_parameter(ccx, param.span, "type", ¶m_ty.to_string()); } } } @@ -2279,9 +2193,10 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .collect(); for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() { - let region = ty::EarlyBoundRegion { space: TypeSpace, - index: index as u32, - name: lifetime_def.lifetime.name }; + let region = ty::EarlyBoundRegion { + index: index as u32, + name: lifetime_def.lifetime.name + }; if lifetimes_in_associated_types.contains(®ion) && // (*) !input_parameters.contains(&ctp::Parameter::Region(region)) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 337b87ce994ad..fe1cb3d6badcd 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4018,7 +4018,7 @@ register_diagnostics! { // E0141, // E0159, // use of trait `{}` as struct constructor // E0163, // merged into E0071 - E0167, +// E0167, // E0168, // E0173, // manual implementations of unboxed closure traits are experimental // E0174, @@ -4053,7 +4053,7 @@ register_diagnostics! { // E0235, // structure constructor specifies a structure of type but // E0236, // no lang item for range syntax // E0237, // no lang item for range syntax - E0238, // parenthesized parameters may only be used with a trait +// E0238, // parenthesized parameters may only be used with a trait // E0239, // `next` method of `Iterator` trait has unexpected type // E0240, // E0241, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 11743ade2d469..8a8232535c775 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -132,7 +132,7 @@ pub mod coherence; pub mod variance; pub struct TypeAndSubsts<'tcx> { - pub substs: Substs<'tcx>, + pub substs: &'tcx Substs<'tcx>, pub ty: Ty<'tcx>, } @@ -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 58d1ec9d02a95..9aca779dd89c4 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 a4faee8f633ed..536fa629fd611 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::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::maps::ItemVariances; use rustc::hir::map as hir_map; @@ -145,7 +144,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let tcx = self.terms_cx.tcx; assert!(is_lifetime(&tcx.map, param_id)); match tcx.named_region_map.defs.get(¶m_id) { - Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id)) + Some(&rl::DefEarlyBoundRegion(_, lifetime_decl_id)) => lifetime_decl_id, Some(_) => bug!("should not encounter non early-bound cases"), @@ -211,7 +210,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { param_def_id: DefId, item_def_id: DefId, kind: ParamKind, - space: ParamSpace, index: usize) -> VarianceTermPtr<'a> { assert_eq!(param_def_id.krate, item_def_id.krate); @@ -227,8 +225,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // variance already inferred, just look it up. let variances = self.tcx().item_variances(item_def_id); let variance = match kind { - TypeParam => *variances.types.get(space, index), - RegionParam => *variances.regions.get(space, index), + TypeParam => variances.types[index], + RegionParam => variances.regions[index], }; self.constant_term(variance) } @@ -302,8 +300,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, trait_ref.def_id, - trait_def.generics.types.as_slice(), - trait_def.generics.regions.as_slice(), + &trait_def.generics.types, + &trait_def.generics.regions, trait_ref.substs, variance); } @@ -360,18 +358,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // README.md for a discussion on dep-graph management. self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did)); - // All type parameters on enums and structs should be - // in the TypeSpace. - assert!(item_type.generics.types.is_empty_in(subst::SelfSpace)); - assert!(item_type.generics.types.is_empty_in(subst::FnSpace)); - assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace)); - assert!(item_type.generics.regions.is_empty_in(subst::FnSpace)); - 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, + &item_type.generics.regions, substs, variance); } @@ -388,33 +379,30 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_substs( generics, trait_ref.def_id, - trait_def.generics.types.as_slice(), - trait_def.generics.regions.as_slice(), + &trait_def.generics.types, + &trait_def.generics.regions, trait_ref.substs, variance); } ty::TyTrait(ref data) => { - let poly_trait_ref = - data.principal_trait_ref_with_self_ty(self.tcx(), - self.tcx().types.err); - // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); - self.add_constraints_from_region(generics, data.bounds.region_bound, contra); + self.add_constraints_from_region(generics, data.region_bound, contra); - // Ignore the SelfSpace, it is erased. + let poly_trait_ref = + data.principal.with_self_ty(self.tcx(), self.tcx().types.err); self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); - let projections = data.projection_bounds_with_self_ty(self.tcx(), - self.tcx().types.err); - for projection in &projections { + for projection in &data.projection_bounds { self.add_constraints_from_ty(generics, projection.0.ty, self.invariant); } } ty::TyParam(ref data) => { - let def_id = generics.types.get(data.space, data.idx as usize).def_id; + assert_eq!(generics.parent, None); + assert!((data.idx as usize) < generics.types.len()); + let def_id = generics.types[data.idx as usize].def_id; let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); match self.terms_cx.inferred_map.get(&node_id) { Some(&index) => { @@ -452,7 +440,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, @@ -461,10 +449,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { for p in type_param_defs { let variance_decl = - self.declared_variance(p.def_id, def_id, TypeParam, - p.space, p.index as usize); + self.declared_variance(p.def_id, def_id, TypeParam, p.index as usize); let variance_i = self.xform(variance, variance_decl); - let substs_ty = *substs.types.get(p.space, p.index as usize); + let substs_ty = substs.type_for_def(p); debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}", variance_decl, variance_i); self.add_constraints_from_ty(generics, substs_ty, variance_i); @@ -472,10 +459,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { for p in region_param_defs { let variance_decl = - self.declared_variance(p.def_id, def_id, - RegionParam, p.space, p.index as usize); + self.declared_variance(p.def_id, def_id, RegionParam, p.index as usize); let variance_i = self.xform(variance, variance_decl); - let substs_r = *substs.regions.get(p.space, p.index as usize); + let substs_r = substs.region_for_def(p); self.add_constraints_from_region(generics, substs_r, variance_i); } } @@ -501,8 +487,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>) { match region { ty::ReEarlyBound(ref data) => { - let def_id = - generics.regions.get(data.space, data.index as usize).def_id; + assert_eq!(generics.parent, None); + assert!((data.index as usize) < generics.regions.len()); + let def_id = generics.regions[data.index as usize].def_id; let node_id = self.tcx().map.as_local_node_id(def_id).unwrap(); if self.is_to_be_inferred(node_id) { let index = self.inferred_index(node_id); diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 0763cfd7e2e60..d3b63119bcb32 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -15,7 +15,6 @@ //! optimal solution to the constraints. The final variance for each //! inferred is then written into the `variance_map` in the tcx. -use rustc::ty::subst::VecPerParamSpace; use rustc::ty; use std::rc::Rc; @@ -109,26 +108,28 @@ 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 types = VecPerParamSpace::empty(); - let mut regions = VecPerParamSpace::empty(); + + let mut item_variances = ty::ItemVariances::empty(); while index < num_inferred && inferred_infos[index].item_id == item_id { let info = &inferred_infos[index]; let variance = solutions[index]; - debug!("Index {} Info {} / {:?} / {:?} Variance {:?}", - index, info.index, info.kind, info.space, variance); + debug!("Index {} Info {} / {:?} Variance {:?}", + index, info.index, info.kind, variance); match info.kind { - TypeParam => { types.push(info.space, variance); } - RegionParam => { regions.push(info.space, variance); } + TypeParam => { + assert_eq!(item_variances.types.len(), info.index); + item_variances.types.push(variance); + } + RegionParam => { + assert_eq!(item_variances.regions.len(), info.index); + item_variances.regions.push(variance); + } } index += 1; } - let item_variances = ty::ItemVariances { - types: types, - regions: regions - }; debug!("item_id={} item_variances={:?}", item_id, item_variances); diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index d9e7e8cbf7df4..d30cbc8f117cf 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -21,7 +21,6 @@ use arena::TypedArena; use dep_graph::DepTrackingMapConfig; -use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace}; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::ItemVariances; use std::fmt; @@ -86,7 +85,6 @@ pub enum ParamKind { pub struct InferredInfo<'a> { pub item_id: ast::NodeId, pub kind: ParamKind, - pub space: ParamSpace, pub index: usize, pub param_id: ast::NodeId, pub term: VarianceTermPtr<'a>, @@ -112,10 +110,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>( // cache and share the variance struct used for items with // no type/region parameters - empty_variances: Rc::new(ty::ItemVariances { - types: VecPerParamSpace::empty(), - regions: VecPerParamSpace::empty() - }) + empty_variances: Rc::new(ty::ItemVariances::empty()) }; // See README.md for a discussion on dep-graph management. @@ -167,17 +162,17 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { let inferreds_on_entry = self.num_inferred(); - if has_self { - self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id); - } - for (i, p) in generics.lifetimes.iter().enumerate() { let id = p.lifetime.id; - self.add_inferred(item_id, RegionParam, TypeSpace, i, id); + self.add_inferred(item_id, RegionParam, i, id); } + if has_self { + self.add_inferred(item_id, TypeParam, 0, item_id); + } for (i, p) in generics.ty_params.iter().enumerate() { - self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id); + let i = has_self as usize + i; + self.add_inferred(item_id, TypeParam, i, p.id); } // If this item has no type or lifetime parameters, @@ -200,15 +195,13 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { fn add_inferred(&mut self, item_id: ast::NodeId, kind: ParamKind, - space: ParamSpace, index: usize, param_id: ast::NodeId) { let inf_index = InferredIndex(self.inferred_infos.len()); let term = self.arena.alloc(InferredTerm(inf_index)); - let initial_variance = self.pick_initial_variance(item_id, space, index); + let initial_variance = self.pick_initial_variance(item_id, index); self.inferred_infos.push(InferredInfo { item_id: item_id, kind: kind, - space: space, index: index, param_id: param_id, term: term, @@ -219,33 +212,23 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> { debug!("add_inferred(item_path={}, \ item_id={}, \ kind={:?}, \ - space={:?}, \ index={}, \ param_id={}, \ inf_index={:?}, \ initial_variance={:?})", self.tcx.item_path_str(self.tcx.map.local_def_id(item_id)), - item_id, kind, space, index, param_id, inf_index, + item_id, kind, index, param_id, inf_index, initial_variance); } fn pick_initial_variance(&self, item_id: ast::NodeId, - space: ParamSpace, index: usize) -> ty::Variance { - match space { - SelfSpace | FnSpace => { - ty::Bivariant - } - - TypeSpace => { - match self.lang_items.iter().find(|&&(n, _)| n == item_id) { - Some(&(_, ref variances)) => variances[index], - None => ty::Bivariant - } - } + match self.lang_items.iter().find(|&&(n, _)| n == item_id) { + Some(&(_, ref variances)) => variances[index], + None => ty::Bivariant } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3d6925041cf5b..013433336a1d5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -21,7 +21,6 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::print as pprust; use rustc::ty::{self, TyCtxt}; -use rustc::ty::subst; use rustc_const_eval::lookup_const_by_id; @@ -161,7 +160,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).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); clean::Trait { @@ -189,7 +188,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).clean(cx), unsafety: style, constness: constness, abi: abi, @@ -209,7 +208,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).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -222,7 +221,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).clean(cx), variants_stripped: false, variants: edef.variants.clean(cx), }) @@ -232,7 +231,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).clean(cx), }, false) } @@ -389,14 +388,14 @@ 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() + let typedef = clean::Typedef { + type_: assoc_ty.ty.unwrap().clean(cx), + generics: clean::Generics { + lifetimes: vec![], + type_params: vec![], + where_predicates: vec![] + } }; - // Not sure the choice of ParamSpace actually matters here, - // because an associated type won't have generics on the LHS - let typedef = (type_scheme, ty::GenericPredicates::empty(), - subst::ParamSpace::TypeSpace).clean(cx); Some(clean::Item { name: Some(assoc_ty.name.clean(cx)), inner: clean::TypedefItem(typedef, true), @@ -434,7 +433,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).clean(cx), items: trait_items, polarity: polarity.map(|p| { p.clean(cx) }), }), @@ -512,11 +511,32 @@ fn build_static<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, /// its associated types as well. We specifically move these clauses to the /// associated types instead when displaying, so when we're genering the /// generics for the trait itself we need to be sure to remove them. +/// We also need to remove the implied "recursive" Self: Trait bound. /// /// The inverse of this filtering logic can be found in the `Clean` /// implementation for `AssociatedType` fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { + for pred in &mut g.where_predicates { + match *pred { + clean::WherePredicate::BoundPredicate { + ty: clean::Generic(ref s), + ref mut bounds + } if *s == "Self" => { + bounds.retain(|bound| { + match *bound { + clean::TyParamBound::TraitBound(clean::PolyTrait { + trait_: clean::ResolvedPath { did, .. }, + .. + }, _) => did != trait_did, + _ => true + } + }); + } + _ => {} + } + } + g.where_predicates.retain(|pred| { match *pred { clean::WherePredicate::BoundPredicate { @@ -524,8 +544,8 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) self_type: box clean::Generic(ref s), trait_: box clean::ResolvedPath { did, .. }, name: ref _name, - }, .. - } => *s != "Self" || did != trait_did, + }, ref bounds + } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(), _ => true, } }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 99d2732c4bb06..75d21399f05e6 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::Substs; use rustc::ty; use rustc::middle::stability; @@ -82,12 +82,6 @@ impl, U> Clean> for [T] { } } -impl, U> Clean> for VecPerParamSpace { - fn clean(&self, cx: &DocContext) -> VecPerParamSpace { - self.map(|x| x.clean(cx)) - } -} - impl, U> Clean for P { fn clean(&self, cx: &DocContext) -> U { (**self).clean(cx) @@ -630,33 +624,10 @@ impl Clean for hir::TyParamBound { } } -impl<'tcx> Clean<(Vec, Vec)> for ty::ExistentialBounds<'tcx> { - fn clean(&self, cx: &DocContext) -> (Vec, Vec) { - let mut tp_bounds = vec![]; - self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b))); - for bb in &self.builtin_bounds { - tp_bounds.push(bb.clean(cx)); - } - - let mut bindings = vec![]; - for &ty::Binder(ref pb) in &self.projection_bounds { - bindings.push(TypeBinding { - name: pb.projection_ty.item_name.clean(cx), - ty: pb.ty.clean(cx) - }); - } - - (tp_bounds, bindings) - } -} - -fn external_path_params(cx: &DocContext, trait_did: Option, - bindings: Vec, substs: &subst::Substs) -> PathParameters { - let lifetimes = substs.regions.get_slice(subst::TypeSpace) - .iter() - .filter_map(|v| v.clean(cx)) - .collect(); - let types = substs.types.get_slice(subst::TypeSpace).to_vec(); +fn external_path_params(cx: &DocContext, trait_did: Option, has_self: bool, + bindings: Vec, substs: &Substs) -> PathParameters { + let lifetimes = substs.regions.iter().filter_map(|v| v.clean(cx)).collect(); + let types = substs.types[has_self as usize..].to_vec(); match (trait_did, cx.tcx_opt()) { // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C @@ -695,13 +666,13 @@ 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 { +fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self: bool, + bindings: Vec, substs: &Substs) -> Path { Path { global: false, segments: vec![PathSegment { name: name.to_string(), - params: external_path_params(cx, trait_did, bindings, substs) + params: external_path_params(cx, trait_did, has_self, bindings, substs) }], } } @@ -712,20 +683,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, false, vec![], empty)), ty::BoundSized => (tcx.lang_items.sized_trait().unwrap(), - external_path(cx, "Sized", None, vec![], &empty)), + external_path(cx, "Sized", None, false, vec![], empty)), ty::BoundCopy => (tcx.lang_items.copy_trait().unwrap(), - external_path(cx, "Copy", None, vec![], &empty)), + external_path(cx, "Copy", None, false, vec![], empty)), ty::BoundSync => (tcx.lang_items.sync_trait().unwrap(), - external_path(cx, "Sync", None, vec![], &empty)), + external_path(cx, "Sync", None, false, vec![], empty)), }; inline::record_extern_fqn(cx, did, TypeTrait); TraitBound(PolyTrait { @@ -748,14 +719,14 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { }; inline::record_extern_fqn(cx, self.def_id, TypeTrait); let path = external_path(cx, &tcx.item_name(self.def_id).as_str(), - Some(self.def_id), vec![], self.substs); + Some(self.def_id), true, vec![], self.substs); - debug!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n", - self.substs.types.get_slice(ParamSpace::TypeSpace)); + debug!("ty::TraitRef\n substs.types: {:?}\n", + &self.input_types()[1..]); // collect any late bound regions let mut late_bounds = vec![]; - for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace) { + for &ty_s in &self.input_types()[1..] { if let ty::TyTuple(ts) = ty_s.sty { for &ty_s in ts { if let ty::TyRef(ref reg, _) = ty_s.sty { @@ -785,10 +756,11 @@ 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.iter().filter_map(|r| r.clean(cx)).map(RegionBound)); + v.extend(self.regions.iter().filter_map(|r| r.clean(cx)) + .map(RegionBound)); v.extend(self.types.iter().map(|t| TraitBound(PolyTrait { trait_: t.clean(cx), lifetimes: vec![] @@ -910,7 +882,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)] } } @@ -991,27 +963,30 @@ impl Clean for hir::Generics { } impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, - &'a ty::GenericPredicates<'tcx>, - subst::ParamSpace) { + &'a ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext) -> Generics { use self::WherePredicate as WP; - let (gens, preds, space) = *self; + let (gens, preds) = *self; // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| { - tp.clean(cx) + let stripped_typarams = gens.types.iter().filter_map(|tp| { + if tp.name == keywords::SelfType.name() { + assert_eq!(tp.index, 0); + None + } else { + Some(tp.clean(cx)) + } }).collect::>(); - let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| { + let stripped_lifetimes = gens.regions.iter().map(|rp| { let mut srp = rp.clone(); srp.bounds = Vec::new(); srp.clean(cx) }).collect::>(); - let mut where_predicates = preds.predicates.get_slice(space) - .to_vec().clean(cx); + let mut where_predicates = preds.predicates.to_vec().clean(cx); // Type parameters and have a Sized bound by default unless removed with // ?Sized. Scan through the predicates and mark any type parameter with @@ -1363,8 +1338,7 @@ impl Clean for hir::ImplItem { impl<'tcx> Clean for ty::Method<'tcx> { fn clean(&self, cx: &DocContext) -> Item { - let generics = (&self.generics, &self.predicates, - subst::FnSpace).clean(cx); + let generics = (self.generics, &self.predicates).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { ty::ExplicitSelfCategory::ByValue => { @@ -1653,7 +1627,7 @@ impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> { fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime { let def = self.tcx.named_region_map.defs.get(<.id).cloned(); match def { - Some(DefEarlyBoundRegion(_, _, node_id)) | + Some(DefEarlyBoundRegion(_, node_id)) | Some(DefLateBoundRegion(_, node_id)) | Some(DefFreeRegion(_, node_id)) => { if let Some(lt) = self.lt_substs.get(&node_id).cloned() { @@ -1830,7 +1804,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { }; inline::record_extern_fqn(cx, did, kind); let path = external_path(cx, &cx.tcx().item_name(did).as_str(), - None, vec![], substs); + None, false, vec![], substs); ResolvedPath { path: path, typarams: None, @@ -1838,12 +1812,26 @@ impl<'tcx> Clean for ty::Ty<'tcx> { is_generic: false, } } - ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { - let did = principal.def_id(); + ty::TyTrait(ref obj) => { + let did = obj.principal.def_id(); inline::record_extern_fqn(cx, did, TypeTrait); - let (typarams, bindings) = bounds.clean(cx); + + let mut typarams = vec![]; + obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); + for bb in &obj.builtin_bounds { + typarams.push(bb.clean(cx)); + } + + let mut bindings = vec![]; + for &ty::Binder(ref pb) in &obj.projection_bounds { + bindings.push(TypeBinding { + name: pb.item_name.clean(cx), + ty: pb.ty.clean(cx) + }); + } + let path = external_path(cx, &cx.tcx().item_name(did).as_str(), - Some(did), bindings, principal.substs()); + Some(did), false, bindings, obj.principal.0.substs); ResolvedPath { path: path, typarams: Some(typarams), @@ -1863,8 +1851,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { let item_predicates = cx.tcx().lookup_predicates(def_id); let substs = cx.tcx().lift(&substs).unwrap(); let bounds = item_predicates.instantiate(cx.tcx(), substs); - let predicates = bounds.predicates.into_vec(); - ImplTrait(predicates.into_iter().filter_map(|predicate| { + ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| { predicate.to_opt_poly_trait_ref().clean(cx) }).collect()) } @@ -2920,7 +2907,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).clean(cx); generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate { @@ -2967,17 +2954,6 @@ impl<'tcx> Clean for ty::AssociatedType<'tcx> { } } -impl<'a> Clean for (ty::TypeScheme<'a>, ty::GenericPredicates<'a>, - ParamSpace) { - fn clean(&self, cx: &DocContext) -> Typedef { - let (ref ty_scheme, ref predicates, ps) = *self; - Typedef { - type_: ty_scheme.ty.clean(cx), - generics: (&ty_scheme.generics, predicates, ps).clean(cx) - } - } -} - fn lang_struct(cx: &DocContext, did: Option, t: ty::Ty, name: &str, fallback: fn(Box) -> Type) -> Type { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index c0faa04323e47..7ae177439064f 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -30,11 +30,11 @@ use std::mem; use std::collections::BTreeMap; use rustc::hir::def_id::DefId; -use rustc::ty::subst; +use rustc::ty; use clean::PathParameters as PP; use clean::WherePredicate as WP; -use clean::{self, Clean}; +use clean; use core::DocContext; pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { @@ -153,27 +153,16 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId, if child == trait_ { return true } - let def = cx.tcx().lookup_trait_def(child); - let predicates = cx.tcx().lookup_predicates(child); - let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx); - generics.where_predicates.iter().filter_map(|pred| { - match *pred { - clean::WherePredicate::BoundPredicate { - ty: clean::Generic(ref s), - ref bounds - } if *s == "Self" => Some(bounds), - _ => None, - } - }).flat_map(|bounds| bounds).any(|bound| { - let poly_trait = match *bound { - clean::TraitBound(ref t, _) => t, - _ => return false, - }; - match poly_trait.trait_ { - clean::ResolvedPath { did, .. } => { - trait_is_same_or_supertrait(cx, did, trait_) + let predicates = cx.tcx().lookup_super_predicates(child).predicates; + predicates.iter().filter_map(|pred| { + if let ty::Predicate::Trait(ref pred) = *pred { + if pred.0.trait_ref.self_ty().is_self() { + Some(pred.def_id()) + } else { + None } - _ => false, + } else { + None } - }) + }).any(|did| trait_is_same_or_supertrait(cx, did, trait_)) } diff --git a/src/test/codegen-units/item-collection/trait-method-default-impl.rs b/src/test/codegen-units/item-collection/trait-method-default-impl.rs index 2b3b83cb7ec63..47892781902ea 100644 --- a/src/test/codegen-units/item-collection/trait-method-default-impl.rs +++ b/src/test/codegen-units/item-collection/trait-method-default-impl.rs @@ -37,7 +37,7 @@ impl SomeGenericTrait for i32 { // For the non-generic foo(), we should generate a codegen-item even if it // is not called anywhere - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0] } // Non-generic impl of generic trait @@ -54,16 +54,16 @@ fn main() { //~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0] let _ = 2i8.bar("&str"); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0i32.bar(0u64, 'c'); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0i32.bar(0u64, "&str"); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0u32.bar(0i8, &['c']); - //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] + //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0] 0u32.bar(0i16, ()); } diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays.rs b/src/test/compile-fail/associated-const-type-parameter-arrays.rs index 3d3b795b2291a..ddf16a2278e5b 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays.rs @@ -25,7 +25,8 @@ impl Foo for Def { } pub fn test() { - let _array: [u32; ::Y]; //~ error: the parameter type + let _array: [u32; ::Y]; + //~^ ERROR the trait bound `A: Foo` is not satisfied } fn main() { diff --git a/src/test/compile-fail/issue-26548.rs b/src/test/compile-fail/issue-26548.rs index b6d5e5458ff08..2591d7bcbaef4 100644 --- a/src/test/compile-fail/issue-26548.rs +++ b/src/test/compile-fail/issue-26548.rs @@ -8,15 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: overflow representing the type `S` +// error-pattern: overflow representing the type -#![feature(rustc_attrs)] trait Mirror { type It: ?Sized; } impl Mirror for T { type It = Self; } struct S(Option<::It>); -#[rustc_no_mir] // FIXME #27840 MIR tries to represent `std::option::Option` first. fn main() { let _s = S(None); } diff --git a/src/test/compile-fail/issue-26812.rs b/src/test/compile-fail/issue-26812.rs index 060a66846d36f..1dd008810788b 100644 --- a/src/test/compile-fail/issue-26812.rs +++ b/src/test/compile-fail/issue-26812.rs @@ -10,5 +10,7 @@ #![feature(default_type_parameter_fallback)] -fn avg(_: T) {} //~ ERROR associated type `Item` not found for `T` +fn avg(_: T) {} +//~^ ERROR type parameters with a default cannot use forward declared identifiers + fn main() {} diff --git a/src/test/compile-fail/variance-associated-types.rs b/src/test/compile-fail/variance-associated-types.rs index 0ed0861d34af1..5539a26d2a170 100644 --- a/src/test/compile-fail/variance-associated-types.rs +++ b/src/test/compile-fail/variance-associated-types.rs @@ -20,12 +20,12 @@ trait Trait<'a> { } #[rustc_variance] -struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[];[]], regions=[[-];[];[]]) +struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[+], regions=[-]) field: (T, &'a ()) } #[rustc_variance] -struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[];[]], regions=[[o];[];[]]) +struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[o], regions=[o]) field: >::Type } diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs index 2b7b05970d90f..2f422bfd38cc7 100644 --- a/src/test/compile-fail/variance-object-types.rs +++ b/src/test/compile-fail/variance-object-types.rs @@ -18,7 +18,7 @@ use std::cell::Cell; // For better or worse, associated types are invariant, and hence we // get an invariant result for `'a`. #[rustc_variance] -struct Foo<'a> { //~ ERROR regions=[[o];[];[]] +struct Foo<'a> { //~ ERROR regions=[o] x: Box &'a i32 + 'static> } diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs index dfa5dc1444151..99416057b2540 100644 --- a/src/test/compile-fail/variance-region-bounds.rs +++ b/src/test/compile-fail/variance-region-bounds.rs @@ -13,11 +13,11 @@ #![feature(rustc_attrs)] #[rustc_variance] -trait Foo: 'static { //~ ERROR types=[[];[o];[]] +trait Foo: 'static { //~ ERROR types=[o] } #[rustc_variance] -trait Bar { //~ ERROR types=[[o];[o];[]] +trait Bar { //~ ERROR types=[o, o] fn do_it(&self) where T: 'static; } diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index bb452eecbfc8b..78591063de8ab 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -16,7 +16,7 @@ // Regions that just appear in normal spots are contravariant: #[rustc_variance] -struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]] +struct Test2<'a, 'b, 'c> { //~ ERROR regions=[-, -, -] x: &'a isize, y: &'b [isize], c: &'c str @@ -25,7 +25,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]] // Those same annotations in function arguments become covariant: #[rustc_variance] -struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]] +struct Test3<'a, 'b, 'c> { //~ ERROR regions=[+, +, +] x: extern "Rust" fn(&'a isize), y: extern "Rust" fn(&'b [isize]), c: extern "Rust" fn(&'c str), @@ -34,7 +34,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]] // Mutability induces invariance: #[rustc_variance] -struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] +struct Test4<'a, 'b:'a> { //~ ERROR regions=[-, o] x: &'a mut &'b isize, } @@ -42,7 +42,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] // contravariant context: #[rustc_variance] -struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[];[]] +struct Test5<'a, 'b:'a> { //~ ERROR regions=[+, o] x: extern "Rust" fn(&'a mut &'b isize), } @@ -52,14 +52,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[];[]] // argument list occurs in an invariant context. #[rustc_variance] -struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]] +struct Test6<'a, 'b:'a> { //~ ERROR regions=[-, o] x: &'a mut extern "Rust" fn(&'b isize), } // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR regions=[[*];[];[]] +struct Test7<'a> { //~ ERROR regions=[*] //~^ ERROR parameter `'a` is never used x: isize } @@ -67,7 +67,7 @@ struct Test7<'a> { //~ ERROR regions=[[*];[];[]] // Try enums too. #[rustc_variance] -enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]] +enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[+, -, o] Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), Test8C(&'b mut &'c str), diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index 9beb90d0b2483..d8af30da163bf 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -15,7 +15,7 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] +enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[+, -, o, *] //~^ ERROR parameter `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]] +struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[*, o, -, +] //~^ ERROR parameter `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]] +struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[o, o, *] //~^ ERROR parameter `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]] +struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[o, -, *] //~^ ERROR parameter `'c` is never used f: Base<'a, 'b, 'a, 'c> } #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here) -struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]] +struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[+, -, o] f: Base<'a, 'b, 'c, 'a> } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index b6f197987bab1..150a1aa56fe72 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -15,48 +15,48 @@ // influence variance. #[rustc_variance] -trait Getter { //~ ERROR types=[[o];[o];[]] +trait Getter { //~ ERROR types=[o, o] fn get(&self) -> T; } #[rustc_variance] -trait Setter { //~ ERROR types=[[o];[o];[]] +trait Setter { //~ ERROR types=[o, o] fn get(&self, T); } #[rustc_variance] -struct TestStruct> { //~ ERROR types=[[+, +];[];[]] +struct TestStruct> { //~ ERROR types=[+, +] t: T, u: U } #[rustc_variance] -enum TestEnum> {//~ ERROR types=[[*, +];[];[]] +enum TestEnum> {//~ ERROR types=[*, +] //~^ ERROR parameter `U` is never used Foo(T) } #[rustc_variance] -trait TestTrait> { //~ ERROR types=[[o, o];[o];[]] +trait TestTrait> { //~ ERROR types=[o, o, o] fn getter(&self, u: U) -> T; } #[rustc_variance] -trait TestTrait2 : Getter { //~ ERROR types=[[o];[o];[]] +trait TestTrait2 : Getter { //~ ERROR types=[o, o] } #[rustc_variance] -trait TestTrait3 { //~ ERROR types=[[o];[o];[]] +trait TestTrait3 { //~ ERROR types=[o, o] fn getter>(&self); } #[rustc_variance] -struct TestContraStruct> { //~ ERROR types=[[*, +];[];[]] +struct TestContraStruct> { //~ ERROR types=[*, +] //~^ ERROR parameter `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR types=[[*, +];[];[]] +struct TestBox+Setter> { //~ ERROR types=[*, +] //~^ ERROR parameter `U` is never used t: T } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index f0ca1edd56387..4244b0e1d8b8b 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -21,7 +21,7 @@ use std::mem; trait T { fn foo(&self); } #[rustc_variance] -struct TOption<'a> { //~ ERROR regions=[[-];[];[]] +struct TOption<'a> { //~ ERROR regions=[-] v: Option>, } diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs index a02f20656e7b5..c47710d6d376d 100644 --- a/src/test/compile-fail/variance-types-bounds.rs +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -14,46 +14,46 @@ #![feature(rustc_attrs)] #[rustc_variance] -struct TestImm { //~ ERROR types=[[+, +];[];[]] +struct TestImm { //~ ERROR types=[+, +] x: A, y: B, } #[rustc_variance] -struct TestMut { //~ ERROR types=[[+, o];[];[]] +struct TestMut { //~ ERROR types=[+, o] x: A, y: &'static mut B, } #[rustc_variance] -struct TestIndirect { //~ ERROR types=[[+, o];[];[]] +struct TestIndirect { //~ ERROR types=[+, o] m: TestMut } #[rustc_variance] -struct TestIndirect2 { //~ ERROR types=[[o, o];[];[]] +struct TestIndirect2 { //~ ERROR types=[o, o] n: TestMut, m: TestMut } #[rustc_variance] -trait Getter { //~ ERROR types=[[o];[o];[]] +trait Getter { //~ ERROR types=[o, o] fn get(&self) -> A; } #[rustc_variance] -trait Setter { //~ ERROR types=[[o];[o];[]] +trait Setter { //~ ERROR types=[o, o] fn set(&mut self, a: A); } #[rustc_variance] -trait GetterSetter { //~ ERROR types=[[o];[o];[]] +trait GetterSetter { //~ ERROR types=[o, o] fn get(&self) -> A; fn set(&mut self, a: A); } #[rustc_variance] -trait GetterInTypeBound { //~ ERROR types=[[o];[o];[]] +trait GetterInTypeBound { //~ ERROR types=[o, o] // Here, the use of `A` in the method bound *does* affect // variance. Think of it as if the method requested a dictionary // for `T:Getter`. Since this dictionary is an input, it is @@ -63,12 +63,12 @@ trait GetterInTypeBound { //~ ERROR types=[[o];[o];[]] } #[rustc_variance] -trait SetterInTypeBound { //~ ERROR types=[[o];[o];[]] +trait SetterInTypeBound { //~ ERROR types=[o, o] fn do_it>(&self); } #[rustc_variance] -struct TestObject { //~ ERROR types=[[o, o];[];[]] +struct TestObject { //~ ERROR types=[o, o] n: Box+Send>, m: Box+Send>, } diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs index 2fd8bf20c7997..d5164412358fc 100644 --- a/src/test/compile-fail/variance-types.rs +++ b/src/test/compile-fail/variance-types.rs @@ -17,32 +17,32 @@ use std::cell::Cell; // not considered bivariant. #[rustc_variance] -struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[];[]], regions=[[-];[];[]] +struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[o, o], regions=[-] t: &'a mut (A,B) } #[rustc_variance] -struct InvariantCell { //~ ERROR types=[[o];[];[]] +struct InvariantCell { //~ ERROR types=[o] t: Cell } #[rustc_variance] -struct InvariantIndirect { //~ ERROR types=[[o];[];[]] +struct InvariantIndirect { //~ ERROR types=[o] t: InvariantCell } #[rustc_variance] -struct Covariant { //~ ERROR types=[[+];[];[]] +struct Covariant { //~ ERROR types=[+] t: A, u: fn() -> A } #[rustc_variance] -struct Contravariant { //~ ERROR types=[[-];[];[]] +struct Contravariant { //~ ERROR types=[-] t: fn(A) } #[rustc_variance] -enum Enum { //~ ERROR types=[[+, -, o];[];[]] +enum Enum { //~ ERROR types=[+, -, o] Foo(Covariant), Bar(Contravariant), Zed(Covariant,Contravariant) diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index b116d9c3c41cf..f93447b642a20 100644 --- a/src/test/mir-opt/storage_ranges.rs +++ b/src/test/mir-opt/storage_ranges.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + fn main() { let a = 0; { @@ -25,7 +27,7 @@ fn main() { // StorageLive(tmp1); // scope 1 at storage_ranges.rs:14:18: 14:25 // StorageLive(tmp2); // scope 1 at storage_ranges.rs:14:23: 14:24 // tmp2 = var0; // scope 1 at storage_ranges.rs:14:23: 14:24 -// tmp1 = std::prelude::v1::Some(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25 +// tmp1 = std::option::Option::Some(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25 // var1 = &tmp1; // scope 1 at storage_ranges.rs:14:17: 14:25 // StorageDead(tmp2); // scope 1 at storage_ranges.rs:14:23: 14:24 // tmp0 = (); // scope 2 at storage_ranges.rs:13:5: 15:6