]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #35605 - eddyb:substs, r=nikomatsakis
authorbors <bors@rust-lang.org>
Wed, 17 Aug 2016 05:52:55 +0000 (22:52 -0700)
committerGitHub <noreply@github.com>
Wed, 17 Aug 2016 05:52:55 +0000 (22:52 -0700)
Remove the ParamSpace separation from formal and actual generics in rustc.

This is the first step towards enabling the typesystem implemented by `rustc` to be extended
(with generic modules, HKT associated types, generics over constants, etc.).

The current implementation splits all formal (`ty::Generics`) and actual (`Substs`) lifetime and type parameters (and even `where` clauses) into 3 "parameter spaces":
* `TypeSpace` for `enum`, `struct`, `trait` and `impl`
* `SelfSpace` for `Self` in a `trait`
* `FnSpace` for functions and methods

For example, in `<X as Trait<A, B>>::method::<T, U>`, the `Substs` are `[[A, B], [X], [T, U]]`.
The representation uses a single `Vec` with 2 indices where it's split into the 3 "parameter spaces".
Such a simplistic approach doesn't scale beyond the Rust 1.0 typesystem, and its existence was mainly motivated by keeping code manipulating generic parameters correct, across all possible situations.

Summary of changes:
* `ty::Generics` are uniformly stored and can be queried with `tcx.lookup_generics(def_id)`
 * the `typeck::collect` changes for this resulted in a function to lazily compute the `ty::Generics` for a local node, given only its `DefId` - this can be further generalized to other kinds of type information
* `ty::Generics` and `ty::GenericPredicates` now contain only their own parameters (or `where` clauses, respectively), and refer to their "parent", forming a linked list
 * right now most items have one level of nesting, only associated items and variants having two
 * in the future, if `<X as mod1<A>::mod2<B>::mod3::Trait<C>>::Assoc<Y>` is supported, it would be represented by item with the path `mod1::mod2::mod3::Trait::Assoc`, and 4 levels of generics: `mod1` with `[A]`, `mod2` with `[B]`, `Trait` with `[X, C]` and `Assoc` with `[Y]`
* `Substs` gets two new APIs for working with arbitrary items:
 * `Substs::for_item(def_id, mk_region, mk_type)` will construct `Substs` expected by the definition `def_id`, calling `mk_region` for lifetime parameters and `mk_type` for type parameters, and it's guaranteed to *always* return `Substs` compatible with `def_id`
 * `substs.rebase_onto(from_base_def_id, to_base_substs)` can be used if `substs` is for an item nested within `from_base_def_id` (e.g. an associated item), to replace the "outer parameters" with `to_base_substs` - for example, you can translate a method's `Substs` between a `trait` and an `impl` (in both directions) if you have the `DefId` of one and `Substs` for the other
* trait objects, without a `Self` in their `Substs`, use *solely* `ExistentialTraitRef` now, letting `TraitRef` assume it *always* has a `Self` present
* both `TraitRef` and `ExistentialTraitRef` get methods which do operations on their `Substs` which are valid only for traits (or trait objects, respectively)
* `Substs` loses its "parameter spaces" distinction, with effectively no code creating `Substs` in an ad-hoc manner, or inspecting them, without knowing what shape they have already

Future plans:
* combine both lifetimes and types in a single `Vec<Kind<'tcx>>` where `Kind` would be a tagged pointer that can be `Ty<'tcx>`, `&'tcx ty::Region` or, in the future, potentially-polymorphic constants
 * this would require some performance investigation, if it implies a lot of dynamic checks
* introduce an abstraction for `(T, Substs)`, where the `Substs` are even more hidden away from code
manipulating it; a precedent for this is `Instance` in trans, which has `T = DefId`; @nikomatsakis also referred to this, as "lazy substitution", when `T = Ty`
* rewrite type pretty-printing to fully take advantage of this to inject actual in the exact places of formal generic parameters in any paths
* extend the set of type-level information (e.g. beyond `ty::Generics`) that can be lazily queried during `typeck` and introduce a way to do those queries from code that can't refer to `typeck` directly
 * this is almost unrelated but is necessary for DAG-shaped recursion between constant evaluation and type-level information, i.e. for implementing generics over constants

r? @nikomatsakis
cc @rust-lang/compiler

cc @nrc Could get any perf numbers ahead of merging this?

115 files changed:
src/librustc/hir/def.rs
src/librustc/infer/error_reporting.rs
src/librustc/infer/mod.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/mir/repr.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/util.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/trait_def.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_const_eval/eval.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/common.rs
src/librustc_metadata/csearch.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/tls_context.rs
src/librustc_metadata/tydecode.rs
src/librustc_metadata/tyencode.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/_match.rs
src/librustc_trans/adt.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/base.rs
src/librustc_trans/callee.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/consts.rs
src/librustc_trans/context.rs
src/librustc_trans/controlflow.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/expr.rs
src/librustc_trans/glue.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/meth.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans/partitioning.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/rscope.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/solve.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/simplify.rs
src/test/codegen-units/item-collection/trait-method-default-impl.rs
src/test/compile-fail/associated-const-type-parameter-arrays.rs
src/test/compile-fail/issue-26548.rs
src/test/compile-fail/issue-26812.rs
src/test/compile-fail/variance-associated-types.rs
src/test/compile-fail/variance-object-types.rs
src/test/compile-fail/variance-region-bounds.rs
src/test/compile-fail/variance-regions-direct.rs
src/test/compile-fail/variance-regions-indirect.rs
src/test/compile-fail/variance-trait-bounds.rs
src/test/compile-fail/variance-trait-object-bound.rs
src/test/compile-fail/variance-types-bounds.rs
src/test/compile-fail/variance-types.rs
src/test/mir-opt/storage_ranges.rs

index 218681efb7dc167d033b1da220acc94b901bd215..d15d51aed09a1049febb903ef1952ee73b56660e 100644 (file)
@@ -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 @@ pub fn def_id(&self) -> DefId {
         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
index b0dec3277a9967686ddaf937e825947a26267000..9a6375719c1bcd406138ce002a37e941c8bdc178 100644 (file)
@@ -82,7 +82,6 @@
 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 @@ fn rebuild_arg_ty_or_output(&self,
                 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();
index 24fadc549fafc221e748cdaff099c9781863b5d4..1b65b5dae074850ad2d74951d9102f73849f4921 100644 (file)
@@ -25,9 +25,7 @@
 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 @@ pub fn next_ty_var(&self) -> Ty<'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(false))
     }
 
-    pub fn next_ty_var_with_default(&self,
-                                    default: Option<type_variable::Default<'tcx>>) -> 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 @@ pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region {
         ty::ReVar(self.region_vars.new_region_var(origin))
     }
 
-    pub fn region_vars_for_defs(&self,
-                                span: Span,
-                                defs: &[ty::RegionParameterDef])
-                                -> Vec<ty::Region> {
-        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<A, B, C = (A, B)>(...);` when
+    /// used in a path such as `Foo::<T, U>::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 {
index 481fd332404bab68217d019d66da3b1b584e27fd..abb22783ddc84a72badc40212a5c69e24f8dd16d 100644 (file)
@@ -154,7 +154,7 @@ fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     fn item_variances(&self, def: DefId) -> ty::ItemVariances;
     fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
     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<DefId>>;
     fn item_name(&self, def: DefId) -> ast::Name;
     fn opt_item_name(&self, def: DefId) -> Option<ast::Name>;
@@ -162,6 +162,8 @@ fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                            -> 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<ast::Attribute>;
     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 @@ fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
 
     // trait/impl-item info
-    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                         -> Option<DefId>;
+    fn trait_of_item(&self, def_id: DefId) -> Option<DefId>;
     fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<ty::ImplOrTraitItem<'tcx>>;
 
@@ -334,7 +335,7 @@ fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     fn item_variances(&self, def: DefId) -> ty::ItemVariances { bug!("item_variances") }
     fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { 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<DefId>> {
         bug!("visible_parent_map")
     }
@@ -344,6 +345,8 @@ fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                            -> 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<ast::Attribute> { 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 @@ fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
 
     // trait/impl-item info
-    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                         -> Option<DefId> { bug!("trait_of_item") }
+    fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { bug!("trait_of_item") }
     fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }
 
@@ -583,7 +585,7 @@ pub unsafe fn unsafe_with_encoding_context<F, R>(f: F) -> R
     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;
     }
 
index 2b59e603cc897f7b33f80846304942b0eda1106c..2a8594c59a83764c727862b7f3ff38684154d7e4 100644 (file)
@@ -88,15 +88,24 @@ fn insert_def_id(&mut self, def_id: DefId) {
     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());
index 9ccca9e6a08f9009dff8075ca506837197e229d1..8369a6c39d54d658a825aaa2eb4842e5c9aa06f2 100644 (file)
@@ -24,9 +24,7 @@
 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 @@
 #[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 @@ fn visit_item(&mut self, item: &hir::Item) {
                 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 @@ fn visit_foreign_item(&mut self, item: &hir::ForeignItem) {
         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 @@ fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl,
                 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 @@ fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
 
         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 check_if_label_shadows_lifetime<'a>(sess: &'a Session,
                 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 @@ fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
     /// ordering is not important there.
     fn visit_early_late<F>(&mut self,
                            fn_id: ast::NodeId,
-                           early_space: subst::ParamSpace,
                            decl: &hir::FnDecl,
                            generics: &hir::Generics,
                            walk: F) where
@@ -576,7 +567,7 @@ fn visit_early_late<F>(&mut self,
                     .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 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
                     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 @@ fn resolve_free_lifetime_ref(&mut self,
                     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 @@ fn check_lifetime_def_for_shadowing(&self,
                     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 visit_ty(&mut self, ty: &hir::Ty) {
         }
     }
 }
-
-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"),
-        }
-    }
-}
index 2bde3d6554feef4400767c15037e19aa4e2955b6..f511d820fac5878f5f05ee51e79b4b0efb491d36 100644 (file)
@@ -1073,10 +1073,7 @@ fn fmt_tuple(fmt: &mut Formatter, lvs: &[Operand]) -> fmt::Result {
                         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 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
         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 ")?;
index b38f5f96de4484c385f18c22b6ef4b4e420fc290..a5a415dd27c650a1debb9ea50b0bd4e47facc89d 100644 (file)
@@ -14,7 +14,6 @@
 
 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 => {
index cf004767b2aaca0e11fc6d68664561c46ed3a8e4..33db0053cda13547a9b33dd3a71cac10f6f958ad 100644 (file)
@@ -31,7 +31,7 @@
 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 @@ fn report_projection_error(&self,
         });
     }
 
-    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 @@ fn impl_similar_to(&self,
 
         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 @@ fn on_unimplemented_note(&self,
                 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::<FnvHashMap<String, String>>();
-                    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::<FnvHashMap<String, String>>();
                     let parser = Parser::new(&istring);
                     let mut errored = false;
                     let err: String = parser.filter_map(|p| {
index 5ba7b914d6591ba57c6cf42452c853165e477dcd..837e33b3e7fc2798e2c27af83265ef52845afa17 100644 (file)
@@ -142,7 +142,7 @@ pub fn must_defer(tcx: TyCtxt<'a, 'gcx, '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 @@ pub fn try_select(&self, tcx: TyCtxt<'a, 'gcx, '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(),
index dc0807ba38faea39962ab3f576f55087a11f9223..b86a54f01cf499adde3b251c2a5dd967f646ad21 100644 (file)
@@ -17,7 +17,7 @@
 
 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<N>
 }
 
index 4889895860129144dc323c6ce52ebde00b364c89..25d2df8fdedb39a0a260703315e9fee84cc4bcc1 100644 (file)
@@ -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 @@ fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
                 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 @@ fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
     }
 
     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 @@ fn object_safety_violation_for_method(self,
     {
         // 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 @@ pub fn is_vtable_safe_method(self,
                                  -> 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 @@ fn virtual_call_violation_for_method(self,
         }
 
         // We can't monomorphize things like `fn foo<A>(...)`.
-        if !method.generics.types.is_empty_in(subst::FnSpace) {
+        if !method.generics.types.is_empty() {
             return Some(MethodViolationCode::Generic);
         }
 
@@ -330,7 +321,7 @@ fn contains_illegal_self_type_reference(self,
         ty.maybe_walk(|ty| {
             match ty.sty {
                 ty::TyParam(ref param_ty) => {
-                    if param_ty.space == SelfSpace {
+                    if param_ty.is_self() {
                         error = true;
                     }
 
index aed4f4393241191d1f2d655f2ba594a709d67b10..ea4fc1c25ab42483a4ff73c6844bf8d1479609b5 100644 (file)
@@ -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);
 
index b61cb0d3eee7217c17243564bee61a911ae706d9..9ea738bd326eb7f18bf75d468433e935cc2c3989 100644 (file)
 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 @@ fn match_projection_obligation_against_definition_bounds(
                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 @@ fn assemble_candidates_from_object_ty(&mut self,
                 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 @@ fn assemble_candidates_from_object_ty(&mut self,
                         _ => {}
                     }
 
-                    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 @@ fn assemble_candidates_for_unsizing(&mut self,
                 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 @@ fn assemble_candidates_for_unsizing(&mut self,
                 // 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 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
 
             // for `PhantomData<T>`, 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 @@ fn confirm_default_impl_object_candidate(&mut self,
         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 @@ fn confirm_object_candidate(&mut self,
         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 @@ fn confirm_builtin_unsize_candidate(&mut self,
         // 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
             // 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
 
             // 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 };
 
                 // 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 }
 
                 // 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 } 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 // 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 @@ fn confirm_builtin_unsize_candidate(&mut self,
 
                 // 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 @@ fn match_impl(&mut self,
             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 @@ fn impl_or_trait_obligations(&mut self,
         // 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)
     }
 }
index 38cccb9753df60ba69e80e83586a84656c06a534..9acfe2754820c9bea7f6988149bd1821d0261f61 100644 (file)
@@ -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,
index a47cd23c64aa6f7145868c142a50f6af542b8a8f..13193e1b2d71be0ace5fb78560cce06f5563a110 100644 (file)
@@ -122,19 +122,18 @@ fn insert(&mut self,
                     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))
index 818eb4eb2fb1e3cf1d30ce81d91d8f98852d67d5..1954ce1993c5e0d71eeb5e604ed6606c68c9f204 100644 (file)
@@ -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<A,B> 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 @@ pub fn trait_ref_for_builtin_bound(self,
             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 @@ pub fn predicate_for_trait_def(self,
     {
         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 @@ pub fn closure_trait_ref_and_return_type(self,
             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))
     }
index 4056fb01aa2c26fe73c4061f0d7b0b4fa18bd6c9..3501dd484608786b7a7a3403eae02852a0e9ca18 100644 (file)
 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<Layout>,
 
     // references
+    generics: TypedArena<ty::Generics<'tcx>>,
     trait_defs: TypedArena<ty::TraitDef<'tcx>>,
     adt_defs: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
 }
@@ -78,6 +79,7 @@ pub fn new() -> 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<DepTrackingMap<maps::AdtDefs<'tcx>>>,
 
     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
-    /// associated predicates.
+    /// associated generics and predicates.
+    pub generics: RefCell<DepTrackingMap<maps::Generics<'tcx>>>,
     pub predicates: RefCell<DepTrackingMap<maps::Predicates<'tcx>>>,
 
     /// Maps from the def-id of a trait to the list of
@@ -583,13 +586,19 @@ pub fn node_type_insert(self, id: NodeId, ty: Ty<'gcx>) {
         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 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             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 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
     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 @@ pub fn mk_fn_ptr(self, fty: &'tcx BareFnTy<'tcx>) -> Ty<'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 @@ pub fn mk_infer(self, it: InferTy) -> Ty<'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> {
index 42d5788568f1c246ac72ae746c74452ffe0d1f2d..17f9b6c25995c48bc1d6f4e72677dd8068debcd2 100644 (file)
@@ -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 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             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 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             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()
index 9bf2daeb5f49bfa38be179145515d2193c08e92d..f7472d611befe30732f07bbca9ea9986732ee436 100644 (file)
@@ -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))
index 0997d6c1a7562e6b2055847f3c767e2e1ba35216..c6c37296e9e1242f82ace140e67d388dd8992e9d 100644 (file)
@@ -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 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
 
             &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 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 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 @@ fn add_region(&mut self, r: ty::Region) {
         }
     }
 
-    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);
-    }
 }
index 3eeff6ee5792fe716d07d61691d10e750a2692ee..2e114a801d6ed4a86de846ab4c286ef6bd93e416 100644 (file)
@@ -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 @@ fn fold_mt(&mut self, t: &ty::TypeAndMut<'tcx>) -> ty::TypeAndMut<'tcx> {
         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 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
         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)
index 8ddd8bef36a6f7f006b9e3f95e5008f3348a439f..1dcc623d3655868cf931b3538b6bfb6ca2faa524 100644 (file)
@@ -322,7 +322,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
         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) |
index 57b1dd66bea9d353185e7ab3f2f43304e589cf30..d5686906e6a7b7c467d99894b4f80a85aa6d5ab0 100644 (file)
@@ -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 @@ fn to_dep_node(key: &$key) -> DepNode<DefId> { DepNode::$node_name(*key) }
 }
 
 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<Vec<ty::ImplOrTraitItemId>> }
index cfc2e89f9d5a126e10e22681c00076fb29710007..1f747ddfb295971c13e4a57de31e1fd1ce93ad31 100644 (file)
@@ -28,7 +28,7 @@
 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;
 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 @@ pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'gcx, '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 @@ pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
 #[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<Variance>,
-    pub regions: VecPerParamSpace<Variance>,
+    pub types: Vec<Variance>,
+    pub regions: Vec<Variance>,
+}
+
+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<Ty<'tcx>>,
@@ -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<ty::Region>,
 }
@@ -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 @@ pub fn to_bound_region(&self) -> ty::BoundRegion {
 /// with an item or method. Analogous to hir::Generics.
 #[derive(Clone, Debug)]
 pub struct Generics<'tcx> {
-    pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
-    pub regions: VecPerParamSpace<RegionParameterDef>,
-}
-
-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<DefId>,
+    pub parent_regions: u32,
+    pub parent_types: u32,
+    pub regions: Vec<RegionParameterDef>,
+    pub types: Vec<TypeParameterDef<'tcx>>,
+    pub has_self: bool,
 }
 
 /// Bounds on generics.
 #[derive(Clone)]
 pub struct GenericPredicates<'tcx> {
-    pub predicates: VecPerParamSpace<Predicate<'tcx>>,
+    pub parent: Option<DefId>,
+    pub predicates: Vec<Predicate<'tcx>>,
 }
 
 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 @@ pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
 pub enum Predicate<'tcx> {
     /// Corresponds to `where Foo : Bar<A,B,C>`. `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 @@ fn dep_node(&self) -> DepNode<DefId> {
     }
 
     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<Ty<'tcx>> {
         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 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'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 @@ pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
 /// [usize:Bar<isize>]]`.
 #[derive(Clone)]
 pub struct InstantiatedPredicates<'tcx> {
-    pub predicates: VecPerParamSpace<Predicate<'tcx>>,
+    pub predicates: Vec<Predicate<'tcx>>,
 }
 
 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 @@ pub fn new(def_id: DefId, substs: &'tcx Substs<'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 @@ pub fn input_types(&self) -> &[Ty<'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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         // 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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         // 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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                         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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                                 };
                                 tcx.construct_parameter_environment(
                                     trait_item.span,
-                                    method_generics,
-                                    method_bounds,
+                                    method_ty.def_id,
                                     extent)
                             }
                             _ => {
@@ -1363,13 +1352,10 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
             }
             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 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
 /// `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 @@ fn sized_constraint_for_ty(
                 };
                 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 @@ pub fn node_id_to_type_opt(self, id: NodeId) -> Option<Ty<'gcx>> {
     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 @@ pub fn item_name(self, id: DefId) -> ast::Name {
     }
 
     // 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<TypeScheme<'gcx>> {
-        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 @@ pub fn lookup_adt_def(self, did: DefId) -> AdtDef<'gcx> {
         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 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
         }
     }
 
-    /// 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<DefId> {
         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 @@ pub fn trait_of_item(self, def_id: DefId) -> Option<DefId> {
     /// the same).
     /// Otherwise, return `None`.
     pub fn trait_item_of_item(self, def_id: DefId) -> Option<ImplOrTraitItemId> {
-        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 @@ pub fn empty_parameter_environment(self) -> ParameterEnvironment<'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 @@ pub fn empty_parameter_environment(self) -> ParameterEnvironment<'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 @@ pub fn construct_free_substs(self, generics: &Generics<'gcx>,
     /// 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 @@ pub fn construct_parameter_environment(self,
         // 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 @@ pub fn construct_parameter_environment(self,
         //
 
         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,
index 05a9b8111570dd5830287269b8f957b914493379..abf863f953664258de01fbcbf4f0ba40b8603922 100644 (file)
@@ -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<Ty<'tcx>>>
-    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<ty::Region>>
-    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 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
     }
 }
 
-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<ty::PolyProjectionPredicate<'tcx>> {
+impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> {
     fn relate<'a, 'gcx, R>(relation: &mut R,
-                           a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
-                           b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
-                           -> RelateResult<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
+                           a: &Vec<ty::PolyExistentialProjection<'tcx>>,
+                           b: &Vec<ty::PolyExistentialProjection<'tcx>>)
+                           -> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>>
         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 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
     }
 }
 
-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 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
     }
 }
 
+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))
index 83413d16ffb3ff448b02c8ec138ac04ec6b06524..f7c4b9938c2794da4c37b619277b6346dd2dee9a 100644 (file)
@@ -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 @@ fn lift_to_tcx(&self, _: TyCtxt) -> Option<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<TraitRef<'tcx>> {
-        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<Self::Lifted> {
+        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<Self::Lifted> {
+        tcx.lift(&self.substs).map(|substs| ty::ExistentialTraitRef {
             def_id: self.def_id,
             substs: substs
         })
@@ -141,6 +151,19 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
     }
 }
 
+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<Self::Lifted> {
+        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<Self::Lifted> {
@@ -427,26 +450,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
-    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<V: TypeVisitor<'tcx>>(&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<V: TypeVisitor<'tcx>>(&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 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
         }
     }
 
-    fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        folder.fold_trait_ref(self)
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&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<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
@@ -666,13 +692,11 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
     }
 }
 
-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<V: TypeVisitor<'tcx>>(&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 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
         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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-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<V: TypeVisitor<'tcx>>(&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<V: TypeVisitor<'tcx>>(&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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
+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<V: TypeVisitor<'tcx>>(&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 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-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<V: TypeVisitor<'tcx>>(&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<T> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         ty::error::ExpectedFound {
index 9680632ec4dcc59cb901cc3822e025f511660940..8aa81cc4743c9a639c598863af8fd956f5986215 100644 (file)
@@ -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<TraitTy<'tcx>>),
+    TyTrait(Box<TraitObject<'tcx>>),
 
     /// The anonymous type of a closure. Used to represent the type of
     /// `|a| a`.
@@ -291,57 +291,11 @@ fn decode<D: Decoder>(d: &mut D) -> Result<ClosureSubsts<'tcx>, D::Error> {
 }
 
 #[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<ty::PolyProjectionPredicate<'tcx>>
-    {
-        // 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<PolyExistentialProjection<'tcx>>,
 }
 
 /// A complete reference to a trait. These take numerous guises in syntax,
@@ -350,8 +304,8 @@ pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
 ///     T : Foo<U>
 ///
 /// 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<U>`, but in
 /// that case the `Self` parameter is absent from the substitutions.
@@ -392,6 +346,42 @@ pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'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<ExistentialTraitRef<'tcx>>;
+
+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 @@ pub fn variadic(&self) -> bool {
 
 #[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<ty::PolyProjectionPredicate<'tcx>>,
+/// 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<ty::PolyProjectionPredicate<'tcx>>)
-               -> 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<ExistentialProjection<'tcx>>;
+
+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 @@ pub fn is_phantom_data(&self) -> bool {
 
     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 @@ pub fn is_fn(&self) -> bool {
 
     pub fn ty_to_def_id(&self) -> Option<DefId> {
         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 @@ pub fn regions(&self) -> Vec<ty::Region> {
                 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(_) |
index 595d965ffce262eede9050e22016b4c24b4ecb7e..e1a19a7b7992ece6edcae09a1b47a11f422cbaea 100644 (file)
 
 // 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<Ty<'tcx>>,
-    pub regions: VecPerParamSpace<ty::Region>,
+    pub types: Vec<Ty<'tcx>>,
+    pub regions: Vec<ty::Region>,
 }
 
 impl<'a, 'gcx, 'tcx> Substs<'tcx> {
-    pub fn new(t: VecPerParamSpace<Ty<'tcx>>,
-               r: VecPerParamSpace<ty::Region>)
-               -> Substs<'tcx>
-    {
-        Substs { types: t, regions: r }
-    }
-
-    pub fn new_type(t: Vec<Ty<'tcx>>,
-                    r: Vec<ty::Region>)
-                    -> Substs<'tcx>
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+               t: Vec<Ty<'tcx>>,
+               r: Vec<ty::Region>)
+               -> &'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<Ty<'tcx>>,
+    pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                     mut t: Vec<Ty<'tcx>>,
                      r: Vec<ty::Region>,
                      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<FR, FT>(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<Ty<'tcx>> {
-        self.types.get_self().cloned()
-    }
+    fn fill_item<FR, FT>(&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<Ty<'tcx>>,
-                       m_regions: Vec<ty::Region>)
-                       -> 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<S: Encoder>(&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 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<'tcx> Decodable for Substs<'tcx> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Substs<'tcx>, 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: Decoder>(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<T> {
-    // This was originally represented as a tuple with one Vec<T> 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<T>,
-}
-
-/// The `split` function converts one `VecPerParamSpace` into this
-/// `SeparateVecsPerParamSpace` structure.
-pub struct SeparateVecsPerParamSpace<T> {
-    pub types: Vec<T>,
-    pub selfs: Vec<T>,
-    pub fns: Vec<T>,
-}
-
-impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "[{:?};{:?};{:?}]",
-               self.get_slice(TypeSpace),
-               self.get_slice(SelfSpace),
-               self.get_slice(FnSpace))
-    }
-}
-
-impl<T> VecPerParamSpace<T> {
-    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<T> {
-        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<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
-        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<T>, type_limit: usize, self_limit: usize)
-                    -> VecPerParamSpace<T>
-    {
-        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<I:Iterator<Item=T>>(&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<T> {
-        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<T>) {
-        // 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<T> {
-        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<T> {
-        self.content
-    }
-
-    pub fn all_vecs<P>(&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<P>(&self, pred: P) -> bool where P: FnMut(&T) -> bool {
-        self.iter().all(pred)
-    }
-
-    pub fn any<P>(&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<U, P>(&self, pred: P) -> VecPerParamSpace<U> 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<U, P>(&self, pred: P) -> VecPerParamSpace<U> 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<T> {
-        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<T>
-        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<T>,
-    space_index: usize,
-    elem_index: usize
-}
-
-impl<'a,T> EnumeratedItems<'a,T> {
-    fn new(v: &'a VecPerParamSpace<T>) -> 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<usize>) {
-        let size = self.vec.as_slice().len();
-        (size, Some(size))
-    }
-}
-
-impl<T> IntoIterator for VecPerParamSpace<T> {
-    type Item = T;
-    type IntoIter = IntoIter<T>;
-
-    fn into_iter(self) -> IntoIter<T> {
-        self.into_vec().into_iter()
-    }
-}
-
-impl<'a,T> IntoIterator for &'a VecPerParamSpace<T> {
-    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 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
         // 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 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
                             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 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'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 @@ fn shift_region_through_binders(&self, region: ty::Region) -> ty::Region {
         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)
+            }
+        })
+    }
+}
index a76dfc35dc1d3897ed10589c949d19ea20a57fa5..61285e8f8b0a597ef378b284e9410f644ccdc80f 100644 (file)
@@ -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<Name>)
                -> TraitDef<'tcx> {
index d7bb8ff2995aa17e359a97d15bc2879d7e795140..51710c13a7deacb9f389d0735be5376747d6784f 100644 (file)
@@ -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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 // 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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
                 self.hash(tys.len());
             }
             TyParam(p) => {
-                self.hash(p.space);
                 self.hash(p.idx);
                 self.hash(p.name.as_str());
             }
@@ -695,12 +693,10 @@ fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
                         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
index 9c1f9d9537a4f2e7e8e2e3715312b0b36df08818..8a9ee45351dfc26c73813eb2835e8e368570f9a9 100644 (file)
@@ -79,28 +79,28 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, 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::<Vec<_>>());
         }
         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) => {
index bfc2e11d9fbcef7a56c49859ff3494f6be64fea8..54b19362b1d86e43afd1b1c36b5a089f95b374c2 100644 (file)
@@ -261,7 +261,6 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'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 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     // 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 @@ fn nominal_obligations(&mut self,
                   .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 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'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 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'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<ty::Region>
 {
@@ -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)
 }
index 896ef49de6f05240d1bc2749effa35e262ddd9d9..02ad8fb7033ed2d50d9900bf2fe2d42864cd9748 100644 (file)
@@ -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<GG>(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<ty::Generics<'tcx>>
-{
-    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<GG>(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<GG>(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<GG>(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<ty::ProjectionPredicate<'tcx>>);
+struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>,
+                                 Vec<ty::ProjectionPredicate<'tcx>>);
 
 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 }
 
                 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                           !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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     // 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 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 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)
     }
 }
 
index f6e9484eda1a4ca54d363454e2531319a8f83e7c..111646912ade30998060c70694305ce1dcbe5b8f 100644 (file)
@@ -16,7 +16,7 @@
 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 @@ fn unelaborated_free_block<'a>(
         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 {
index 73b54c4374ffb65dce75dcf20a6a0bbe29545af5..d71add3258fbd888d917e991b2a80f60a1101127 100644 (file)
@@ -22,8 +22,9 @@
 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 variant_expr<'a>(variants: &'a [hir::Variant], id: ast::NodeId)
 /// 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<ty::Ty<'tcx>>)> {
     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<ty::Ty<'tcx>>)>
 {
-    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(),
index 7711091685d3848d4cd43ed0d3c8dd94951c5cf7..32d0bbbfdb6b7d8e179542345e71af35580856e2 100644 (file)
@@ -20,8 +20,7 @@
 use rustc::middle::region::CodeExtentData;
 use rustc::middle::resolve_lifetime;
 use rustc::middle::stability;
-use rustc::ty::subst;
-use rustc::ty::subst::Subst;
+use rustc::ty::subst::{Subst, Substs};
 use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
@@ -276,19 +275,17 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'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)
         //
index ed17f3533d49f785750ff73ea7bac3b9aa63f098..61d927239828b2124894debb7581181f9834cff7 100644 (file)
@@ -465,16 +465,14 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
                     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 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // 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 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             // 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.
index b8e66530ea1533c0e6299bc9b551a731efe30e0e..1ef48e6d6565fcc1c43f0570f5d3ba75bc1cefe4 100644 (file)
@@ -34,7 +34,7 @@
 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 @@ fn tr(&self, dcx: &DecodeContext) -> 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 @@ fn read_method_callee<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                     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 @@ fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
                                                     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 @@ fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapt
     }
 
     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 @@ fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, '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 @@ fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>>;
     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 @@ fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
 
     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 @@ fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
         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);
index ff072cce5db9667ccd5cb998ee0cdcb6384cdd78..99a3f3b00c8b0f4ca4824c8c457595a9a629b2d5 100644 (file)
@@ -196,20 +196,14 @@ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
 // 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;
 
index 2cdbd1b86012dd293734b01eb74ee1c4ce092048..f6d698eb969d80baa919273315ecda8a27289077 100644 (file)
@@ -86,7 +86,7 @@ fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> {
     }
 
     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 @@ fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
         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<ast::Attribute>
     {
         self.dep_graph.read(DepNode::MetaData(def_id));
@@ -231,11 +239,10 @@ fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
         decoder::get_parent_impl(&*cdata, impl_def.index)
     }
 
-    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option<DefId>
-    {
+    fn trait_of_item(&self, def_id: DefId) -> Option<DefId> {
         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)
index 64b614b56e12fdffe444b86545fb03c77226adaa..5488f114db32ff610576f227ed063a70bdda421a 100644 (file)
@@ -35,7 +35,6 @@
 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 @@ fn get_struct_variant<'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 @@ fn get_struct_variant<'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<attr::Stability> {
@@ -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<F>(cdata: Cmd,
     }
 }
 
-pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd,
-                                   id: DefIndex,
-                                   tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                                   -> Option<DefId> {
+pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option<DefId> {
     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 {
index cc1d07b33c7e830b6840e2d4b79045210db44f99..320ba3c8d9dc863c9344c800cc6228cf6a247097 100644 (file)
@@ -26,7 +26,6 @@
 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);
index 23142ca80ef0ecc695c088650263b15c5d2eb26c..6e78cbcd28e731e663b698a6fc16d2068b041113 100644 (file)
@@ -74,7 +74,7 @@ fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'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)
         };
index 7b4919bb4773be39e41447b8a37b47e299e8a0d4..c76cf2363923741b12a2db7c2e1421fe2fe61c78 100644 (file)
@@ -20,8 +20,7 @@
 
 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 @@ fn parse_size(&mut self) -> Option<usize> {
         }
     }
 
-    fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> 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 @@ pub fn parse_region(&mut self) -> ty::Region {
             }
             '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 @@ fn parse_str(&mut self, term: char) -> String {
     }
 
     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 @@ pub fn parse_ty(&mut self) -> Ty<'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 @@ pub fn parse_ty(&mut self) -> Ty<'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 @@ pub fn parse_ty(&mut self) -> Ty<'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 @@ pub fn parse_ty(&mut self) -> Ty<'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 @@ pub fn parse_ty(&mut self) -> Ty<'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 @@ fn parse_u32(&mut self) -> u32 {
         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 @@ fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'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 @@ pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'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 @@ pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'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 @@ pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
         ty::RegionParameterDef {
             name: name,
             def_id: def_id,
-            space: space,
             index: index,
             bounds: bounds,
         }
@@ -649,27 +693,6 @@ fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
         }
     }
 
-    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 {
index 15bafcdd3c99e9e5d61378be03509da0d264a640..90fd8a0eb2f654f2fa69e25c3b10ab5b426eb831 100644 (file)
@@ -19,9 +19,7 @@
 
 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<Vec<u8>>, 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<Vec<u8>>, 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<T, F>(w: &mut Cursor<Vec<u8>>, t: Option<T>, enc_f: F) where
     }
 }
 
-fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut Cursor<Vec<u8>>,
-                                           cx: &ctxt<'a, 'tcx>,
-                                           v: &VecPerParamSpace<T>,
-                                           mut op: F) where
-    F: FnMut(&mut Cursor<Vec<u8>>, &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<Vec<u8>>, 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<Vec<u8>>, 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<Vec<u8>>, 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<Vec<u8>>, cx: &ctxt, r: ty::Region) {
@@ -266,8 +294,7 @@ pub fn enc_region(w: &mut Cursor<Vec<u8>>, 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<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
     enc_substs(w, cx, s.substs);
 }
 
+fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, 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<Vec<u8>>, p: hir::Unsafety) {
     match p {
         hir::Unsafety::Normal => write!(w, "n"),
@@ -386,7 +419,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
     enc_ty(w, cx, fsig.0.output);
 }
 
-pub fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
+fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _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<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinB
     write!(w, ".");
 }
 
-pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor<Vec<u8>>,
-                                       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<Vec<u8>>, 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<Vec<u8>>, 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<Vec<u8>>, 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<Vec<u8>>, 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<Vec<u8>>,
         }
         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<Vec<u8>>,
     }
 }
 
-fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
-                                      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<Vec<u8>>,
+                                        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);
 }
index cae9e8379897c5311e44a183d1049bf3bf595d37..5e4053a82ad8a3ce22a7c6b093733073d08864e5 100644 (file)
@@ -89,7 +89,7 @@
 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,
index df1fec75939b5097e8d62ec45e6d481007e92253..972e7f5be7075ed339a7cba7754e5f5bfb42d692 100644 (file)
@@ -147,16 +147,16 @@ pub fn trait_method(&mut self,
                         params: Vec<Ty<'tcx>>)
                         -> (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,
                         });
                     }
                 }
index 962509be324de363aa44c8e3bce6f87c3033b804..65e14eee4bc2bc0fc0ec5e039c0cd920096355db 100644 (file)
@@ -49,7 +49,6 @@
 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 @@ fn visit_variant(&mut self,
     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 @@ fn resolve_item(&mut self, item: &Item) {
         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 @@ fn resolve_item(&mut self, item: &Item) {
 
             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 @@ fn resolve_item(&mut self, item: &Item) {
                                 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 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
         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 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
 
                     // 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 @@ fn resolve_implementation(&mut self,
                               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 @@ fn resolve_implementation(&mut self,
                                     // 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);
index 16cd9186ce9bb43e251b29c5c66d61c799256457..db535e22f194d1a9bd5e23401d2f8918cacbc3e9 100644 (file)
@@ -299,8 +299,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
                             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 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
             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),
index 27a8c1f1df47686e3b0d6f66a127ab80685c831d..d6866b27f98a56869da645060afa69fb7a84a6ab 100644 (file)
@@ -895,7 +895,7 @@ fn compare_str<'blk, 'tcx>(bcx: 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)
     }
 
index 23c4258caf7bd9c5ca873ba44d9c4ac28880f2d0..d48ec98a20dfb3d308a0cfa73507d9569d879269 100644 (file)
@@ -48,7 +48,7 @@
 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 @@ fn find_ptr<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Option<DiscrField> {
 
 fn get_cases<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        adt: ty::AdtDef<'tcx>,
-                       substs: &subst::Substs<'tcx>)
+                       substs: &Substs<'tcx>)
                        -> Vec<Case<'tcx>> {
     adt.variants.iter().map(|vi| {
         let field_tys = vi.fields.iter().map(|field| {
index 5e2c0805c2ea3a6c4bda553e9d773ffbdd58ff91..25a1479c289488c43af1001a3b26db4556300efa 100644 (file)
@@ -252,7 +252,7 @@ pub fn symbol_name(self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
         // 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())
index c78cda75e820e548d5a585c1b5e2d1736745f3d0..f190fbeb6feb9553d42e7cda76ceb1cf77620ac1 100644 (file)
@@ -39,7 +39,7 @@
 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 @@ pub fn new(ccx: &'blk CrateContext<'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 @@ fn create_entry_fn(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
index aaec2a47025a2e2a7d788e57ac96c817f8a4596b..d50959b5ab3023d9cfaf99bec87929f8580dc6e6 100644 (file)
@@ -22,7 +22,7 @@
 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 @@ pub fn method<'blk>(bcx: Block<'blk, '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 @@ pub fn def<'a>(ccx: &CrateContext<'a, '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 @@ pub fn reify<'a>(self, ccx: &CrateContext<'a, '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();
 
index acc302430aee68383513650f15f2db85cf1b3aa2..76910304eebb0e40c43717fbe1c4f8cf1c3ad2ff 100644 (file)
 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);
index 79cf77cd9d35d534c8434dc1dac8b5dd4d444d3a..b1aaea7d984c9ee4d20b04927b1f04ba8b578ac0 100644 (file)
@@ -523,7 +523,7 @@ pub fn eh_personality(&self) -> ValueRef {
         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 @@ pub fn eh_unwind_resume(&self) -> Callee<'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 {
index 3ecba3691d279d22dd994b002a66de89e556db4b..0e9898896778c0a0b577b5f864694db6c1927493 100644 (file)
@@ -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<ValueRef, ConstEvalFailure> {
     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())?;
index 65eea1bbb6337cba32e1737be9da86b04a3f6d19..c31dbf8943e08972e2daee47d320e78d97c74a70 100644 (file)
@@ -30,7 +30,7 @@
 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 @@ pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'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<Sha256> {
@@ -999,11 +992,6 @@ pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'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>);
index 8845f124218bc437b3da19d2a9048be5c97eba88..8b3a8a2bfccfb87d1bff788c10f021dd08314e83 100644 (file)
@@ -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
 }
index 3fe8b2b66791a8c65b3db77cca77596c7b167a9d..f505efb1ab2f9aa18e994fbc2f2dbfd4d93acecc 100644 (file)
@@ -27,7 +27,7 @@
 
 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 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, '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 @@ fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut 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 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, '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,
 }
index d6a4ce3c43a4ecc9b9ec67e0c1522daf93ed5889..1ee000992b9c59cba899c758850ca1c5e47d1126 100644 (file)
@@ -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 @@ fn get_template_parameters<'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 = &param_substs.types;
 
         if actual_types.is_empty() {
             return create_DIArray(DIB(cx), &[]);
@@ -381,10 +381,11 @@ fn get_template_parameters<'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 @@ fn get_template_parameters<'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<ast::Name> {
+        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) {
index 73b1c828663e1b660751578045a2dce73b28e956..2a996ca75a37e78597be98fafdf760ca2f0d291b 100644 (file)
@@ -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 @@ fn push_item_name(cx: &CrateContext,
     // 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;
index 6c894ddad1a94981559d56da9aef60ad564f84e7..beb589c80bfc56f27a2d9f7d1aa74b1e2872aba6 100644 (file)
@@ -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,
index 93e5f4ba1e205cec5dfd64577a54ea7564065a8f..080844782f2051c31983602065c5afa43255a448 100644 (file)
@@ -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,
index 7be173d17b487ded0132b7408c214a96becb84e5..ecee4705510595bc991844e1d79b48882acf5122 100644 (file)
@@ -15,8 +15,7 @@
 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<hir::Expr>]>,
      llargs: &[ValueRef],
index 3d6093d4d6960f16aeeab3e697a71564414bc823..b051028ebda6b6036f880752e352163c1f6b0c31 100644 (file)
@@ -15,8 +15,7 @@
 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<Option<ImplMethod<'tcx>>>
 {
     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(|| {
index 31fee560fe36925bde7073a40f0c7d14338dbe02..4da973bb7f946ec2d5754d27b9aba4c7389857bd 100644 (file)
@@ -232,12 +232,9 @@ fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
                  args: IndexVec<mir::Arg, Const<'tcx>>)
                  -> Result<Const<'tcx>, 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);
index e9aacaa0f954f2e4fc20daa8d50ba442bcabc0b8..d1837883aaeb032cbb91328b4013d0f344c3cb92 100644 (file)
@@ -12,7 +12,6 @@
 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 @@
 
 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, &[])
     }
 }
 
index ade6e8abeb32a5ac07d27eba578131c015c9cac4..87d0ea0fe81f30d83b20ac75099a7c0ca098d1d9 100644 (file)
@@ -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));
             }
index 90058f0b8329a30afdc3f0d694c9438599fffd7a..580882e31dd603248fba65ca64b4c96eb6dbefc4 100644 (file)
@@ -28,7 +28,7 @@
 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 @@ pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
             },
             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<Ty<'tcx>>,
-                              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);
index e6794149fcb3b5b7088dc476b7aa6b1977d6abcd..6862002ed83b25a448e2319656cb7610d506b6be 100644 (file)
@@ -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[..])
           }
       }
index ed67c9fbe30bee94e3f7ebeb94dc8a0831e28bfe..f6984f42cab341301d52864b2b6e691d1e5217ac 100644 (file)
@@ -55,8 +55,7 @@
 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<NodeMap<Ty<'tcx>>>;
 
+    /// 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 @@ fn trait_defines_associated_type_named(&self, trait_def_id: DefId, name: ast::Na
     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<ty::TypeParameterDef<'tcx>>,
-                substs: Option<&mut Substs<'tcx>>,
-                space: Option<ParamSpace>,
-                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<ty::PolyProjectionPredicate<'tcx>>);
 
+/// 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 @@ pub fn ast_path_substs_for_ty(&self,
         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<ty::Region>)
-        -> Substs<'tcx>
+        param_mode: PathParamMode,
+        def_id: DefId,
+        parameters: &hir::PathParameters,
+        self_ty: Option<Ty<'tcx>>)
+        -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
     {
         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 @@ fn create_region_substs(&self,
                 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<Ty<'tcx>>,
-        types_provided: Vec<Ty<'tcx>>,
-        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<Ty<'tcx>>,
-                                param_mode: PathParamMode,
-                                ty_param_defs: &[ty::TypeParameterDef<'tcx>],
-                                mut substs: Substs<'tcx>,
-                                self_ty: Option<Ty<'tcx>>)
-                                -> Vec<Ty<'tcx>>
-    {
-        fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
-                                        -> Option<ty::TypeParameterDef<'tcx>>
-        {
-            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<Ty<'tcx>>,
-                                              Vec<ConvertedBinding<'tcx>>)
-    {
-        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, &region_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 @@ fn convert_ty_with_lifetime_elision(&self,
 
     fn convert_parenthesized_parameters(&self,
                                         rscope: &RegionScope,
-                                        span: Span,
-                                        decl_generics: &ty::Generics<'tcx>,
+                                        region_substs: &Substs<'tcx>,
                                         data: &hir::ParenthesizedParameterData)
-                                        -> (Substs<'tcx>,
-                                            Vec<Ty<'tcx>>,
-                                            Vec<ConvertedBinding<'tcx>>)
+                                        -> (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, &region_substs, a_t))
-                       .collect::<Vec<Ty<'tcx>>>();
-
+        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 @@ fn convert_parenthesized_parameters(&self,
             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<Ty<'tcx>>,
+        self_ty: Ty<'tcx>,
         poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
         -> ty::PolyTraitRef<'tcx>
     {
@@ -729,7 +678,7 @@ pub fn instantiate_poly_trait_ref(&self,
     pub fn instantiate_mono_trait_ref(&self,
         rscope: &RegionScope,
         trait_ref: &hir::TraitRef,
-        self_ty: Option<Ty<'tcx>>)
+        self_ty: Ty<'tcx>)
         -> ty::TraitRef<'tcx>
     {
         let trait_def_id = self.trait_def_id(trait_ref);
@@ -755,32 +704,12 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
         }
     }
 
-    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::PolyProjectionPredicate<'tcx>>)
-        -> 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<Ty<'tcx>>,
+        self_ty: Ty<'tcx>,
         path_id: ast::NodeId,
         trait_segment: &hir::PathSegment,
         poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
@@ -803,21 +732,14 @@ fn ast_path_to_poly_trait_ref(&self,
                                                  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 @@ fn ast_path_to_mono_trait_ref(&self,
                                   span: Span,
                                   param_mode: PathParamMode,
                                   trait_def_id: DefId,
-                                  self_ty: Option<Ty<'tcx>>,
+                                  self_ty: Ty<'tcx>,
                                   trait_segment: &hir::PathSegment)
                                   -> ty::TraitRef<'tcx>
     {
@@ -849,7 +771,7 @@ fn create_substs_for_ast_trait_ref(&self,
                                        span: Span,
                                        param_mode: PathParamMode,
                                        trait_def_id: DefId,
-                                       self_ty: Option<Ty<'tcx>>,
+                                       self_ty: Ty<'tcx>,
                                        trait_segment: &hir::PathSegment)
                                        -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
     {
@@ -865,8 +787,8 @@ fn create_substs_for_ast_trait_ref(&self,
             }
         };
 
-        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 @@ fn create_substs_for_ast_trait_ref(&self,
                         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 @@ fn create_substs_for_ast_trait_ref(&self,
                                      "\
                         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<Ty<'tcx>>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
         binding: &ConvertedBinding<'tcx>)
         -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
     {
@@ -962,62 +877,39 @@ fn ast_type_binding_to_poly_projection_predicate(
 
         // 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<ty::PolyTraitRef> =
+        let candidates: Vec<ty::PolyTraitRef> =
             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 @@ fn ast_path_to_ty(&self,
         -> 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 @@ fn ast_path_to_ty(&self,
         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<TraitAndProjections<'tcx>, 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 @@ fn ast_ty_to_trait_ref(&self,
          * 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 @@ fn ast_ty_to_trait_ref(&self,
                     }
                 }
                 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<ty::PolyProjectionPredicate<'tcx>>,
-                                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,
+                                               &region_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 @@ fn make_object_type(&self,
         }
 
         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 @@ fn make_object_type(&self,
             })
             .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 @@ fn make_object_type(&self,
                         .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 @@ fn associated_path_def_to_ty(&self,
                     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 @@ fn associated_path_def_to_ty(&self,
                 }
             }
             _ => {
-                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 @@ fn qpath_to_ty(&self,
                                                         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 @@ fn qpath_to_ty(&self,
     /// # 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 @@ fn base_def_to_ty(&self,
             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 @@ fn base_def_to_ty(&self,
                                     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 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 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 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 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 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 // 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 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                     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 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 // 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 @@ pub fn ty_of_arg(&self,
     {
         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 @@ pub fn ty_of_closure(&self,
         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 @@ pub fn ty_of_closure(&self,
         }
     }
 
-    /// 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<ty::PolyProjectionPredicate<'tcx>>,
-        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 @@ fn conv_ty_poly_trait_ref(&self,
     {
         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<ty::PolyProjectionPredicate<'tcx>>, // 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,
-                                               &region_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 @@ pub fn conv_existential_bounds_from_partitioned_bounds(&self,
     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<ty::Region> // if None, use the default
     {
@@ -2226,7 +2099,7 @@ fn compute_object_lifetime_bound(&self,
         // 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"
index 04f22b195110f59b6bb7306695bc77808b98c8ab..af24a7b51176ccca97c67e3f167da966e33a44a4 100644 (file)
@@ -547,10 +547,7 @@ fn check_pat_path(&self,
         }
 
         // 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 @@ fn check_pat_tuple_struct(&self,
         }
 
         // 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.
index 265422468fe2a1c4a18b6ca9f790f005d2f539d5..9a3cbabe553314fd77bf3719a3686c8aba61bc62 100644 (file)
@@ -101,7 +101,7 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'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);
index 7a4cc09a7d5064d3a9ac408103df64cdf885dca3..fb78d3a37ca236404c5706916566637f1d3be83c 100644 (file)
@@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
         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() {
index 3acb8017eec509acaadd09ef48ed36c343095c2d..377ca5eaebe302745e97093c011a20cb5ae1571f 100644 (file)
@@ -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 @@ fn deduce_expectations_from_expected_type(&self, expected_ty: Ty<'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 @@ fn deduce_sig_from_projection(&self,
             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);
 
index e6ddc6ad69379922d7f94282c66389683edb8c50..6bcf21563cb98c919e907e2e4f431660f6cb7b86 100644 (file)
@@ -13,7 +13,7 @@
 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 @@ fn check_region_bounds_on_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(|_| {
index f3a01ef7409fa48fa7a86b600b963d7f9a59e4da..82545d564a20c807f69fd91e3e7b82d4f877cf2b 100644 (file)
@@ -15,7 +15,7 @@
 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;
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 ///
 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<T> - 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)
         }
index 4334f043772e361962a409b94e1ec0e7c6a82a0c..b2873bf686578bed51c985eafd2d4a125a7fdab0 100644 (file)
@@ -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 {
index 5fac65bbfd6552d365eab1b611a55c93994aff70..9e0b38fd9fe517a163c9cffcdfce403b394f8b31 100644 (file)
@@ -12,7 +12,7 @@
 
 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 @@ fn confirm(&mut self,
 
         // 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 @@ fn adjust_self_ty(&mut self,
     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 @@ fn fresh_receiver_substs(&mut self,
 
             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 @@ fn fresh_receiver_substs(&mut self,
                     // 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 @@ fn fresh_receiver_substs(&mut self,
                 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<R, F>(&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<R, F>(&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 @@ fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R wh
         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 @@ fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R wh
 
     fn instantiate_method_substs(&mut self,
                                  pick: &probe::Pick<'tcx>,
-                                 supplied_method_types: Vec<Ty<'tcx>>,
-                                 substs: subst::Substs<'tcx>)
-                                 -> subst::Substs<'tcx>
+                                 mut supplied_method_types: Vec<Ty<'tcx>>,
+                                 substs: &Substs<'tcx>)
+                                 -> &'tcx Substs<'tcx>
     {
         // Determine the values for the generic parameters of the method.
         // If they were not explicitly supplied, just construct fresh
         // 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 @@ fn unify_receivers(&mut self,
 
     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 @@ fn instantiate_method_sig(&mut self,
         // 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 @@ fn instantiate_method_sig(&mut self,
         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,
index e6401be5b3ef655f9b78785448932ee0a92e525e..bcb410e1b8d0132b284ce0932e43cec3f366b85b 100644 (file)
@@ -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 @@ pub fn lookup_method_in_trait_adjusted(&self,
 
         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<input_tys>`
-        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 @@ pub fn lookup_method_in_trait_adjusted(&self,
         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);
index 99f1b13d4e4ab422a6c218dd0c202da6812b037e..c306463ec1de0795b7352e6a01cf89a90462543c 100644 (file)
@@ -16,8 +16,7 @@
 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<traits::PredicateObligation<'tcx>>),
-    ExtensionImplCandidate(/* Impl */ DefId, subst::Substs<'tcx>,
+    ExtensionImplCandidate(/* Impl */ DefId, &'tcx Substs<'tcx>,
                            /* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
     ObjectCandidate,
     TraitCandidate,
@@ -290,8 +289,8 @@ fn assemble_probe(&mut self, self_ty: Ty<'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 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
         }
 
         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 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
 
     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 @@ fn assemble_inherent_candidates_from_object(&mut self,
         // 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 @@ fn assemble_inherent_candidates_from_param(&mut self,
                        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 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
             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 @@ fn assemble_closure_candidates(&mut self,
             // 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 @@ fn assemble_projection_candidates(&mut self,
 
             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 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
     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 @@ fn xform_self_ty(&self,
     fn xform_method_self_ty(&self,
                             method: &Rc<ty::Method<'tcx>>,
                             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 @@ fn xform_method_self_ty(&self,
         // 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
index 54521782474fe05ac1e8b15ae5e0fec19a193def..573dae46456baa2f3b78146e3bab014e63112671 100644 (file)
@@ -54,10 +54,8 @@ fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool {
 
                 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 @@ fn is_local(ty: Ty) -> bool {
             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,
 
index d985d3ccbea89751909d018202a7cc999f6086df..e573655b8c9847ffd045a7e07110e0e7109c1130 100644 (file)
@@ -88,9 +88,8 @@
 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 @@ fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'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<ty::TypeScheme<'tcx>, ErrorReported>
     {
@@ -1333,7 +1333,7 @@ fn get_type_parameter_bounds(&self,
                                   .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 @@ fn trait_defines_associated_type_named(&self,
         trait_def.associated_type_names.contains(&assoc_name)
     }
 
-    fn ty_infer(&self,
-                ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
-                substs: Option<&mut subst::Substs<'tcx>>,
-                space: Option<subst::ParamSpace>,
-                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 @@ fn instantiate_bounds(&self,
                           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 @@ pub fn instantiate_type_path(&self,
                                  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 @@ pub fn impl_self_ty(&self,
                         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 @@ pub fn check_struct_path(&self,
                 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 @@ pub fn check_struct_path(&self,
             _ => 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 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
               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 @@ fn check_block_with_expected(&self,
         *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<Ty<'tcx>>,
                                   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 @@ pub fn instantiate_value_path(&self,
         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 {
-                    // `<T>::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 @@ pub fn instantiate_value_path(&self,
                     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 {
-                    // `<T>::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];
+                    // `<T>::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 @@ pub fn instantiate_value_path(&self,
             // 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 `<T as Trait<A, B>>::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 @@ pub fn instantiate_value_path(&self,
         // 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 @@ pub fn instantiate_value_path(&self,
 
         // 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 @@ pub fn instantiate_value_path(&self,
             // 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 @@ pub fn instantiate_value_path(&self,
         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<ty::TypeParameterDef<'tcx>>,
-        region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
-        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<ty::TypeParameterDef<'tcx>>,
-        region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
-        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<ty::TypeParameterDef<'tcx>>,
-        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<Ty> =
-            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<Ty> =
-            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<ty::TypeParameterDef<'tcx>>,
-        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<ty::RegionParameterDef>,
-        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<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
index 22ffcfbaae111df894576ee75b2fdce6675fb10e..859d5ff0543d01bcf6f56d0c55bd60c0ad7ea620 100644 (file)
@@ -824,11 +824,11 @@ fn walk_cast(&mut self,
             }
 
             /*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 @@ fn projection_must_outlive(&self,
         // 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 @@ fn declared_projection_bounds_from_trait(&self,
         //
         // we can thus deduce that `<T as SomeTrait<'a>>::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| {
index 4bb9f4fd332f2e3c183d75d79a5790622b8cfe13..7ed4b2bcb1918f3ab01e060395877a339515c8f5 100644 (file)
 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 @@ fn check_variances_for_type_defn(&self,
 
         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 @@ fn check_variances_for_type_defn(&self,
                                          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 @@ fn report_bivariance(&self,
 }
 
 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::<HashSet<_>>();
+    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 @@ fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'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 => {
index 5f8861f309948d1dfdff5a65d1b18a2f931bc14c..cfc1292c34b78af0275585300c5acb9bd5f36d1e 100644 (file)
@@ -18,7 +18,6 @@
 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 @@ pub fn resolve_type_vars_in_fn(&self,
         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 @@ fn new(fcx: &'cx FnCtxt<'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 @@ fn visit_closures(&self) {
         }
     }
 
-    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 @@ fn visit_anon_types(&self) {
                 }
             });
 
-            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)
             });
         }
     }
index 9b26e95f7fa55b3255c9514cfe6d21331827ced6..4a1e401f9820f7d40948c25feb761b4eaf6b4766 100644 (file)
@@ -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 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
             }
 
             TyTrait(ref t) => {
-                Some(t.principal_def_id())
+                Some(t.principal.def_id())
             }
 
             TyBox(_) => {
@@ -386,7 +386,7 @@ fn check_implementations_of_coerce_unsized(&self) {
 
             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);
 
index e426f0cb643b7ab99159ed0ec331e438f5b23514..97aed4d5e82f9f1fb583046d97ab01bf5ed38ceb 100644 (file)
@@ -80,7 +80,7 @@ fn check_item(&self, item: &hir::Item) {
                         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() {
index 46a9ef8d5babb0edcc4fe4de4e44894e41910425..f60fb9583a66113a6ca8970350d358e18f30b965 100644 (file)
@@ -168,14 +168,14 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                     // 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 \
index d38065f4f1238912f3624ef2dbff74702f5c0c5e..ed406b9379e353fecc9dc5ec006cc520e822ba69 100644 (file)
@@ -65,7 +65,7 @@
 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 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 @@ fn report_cycle(&self,
         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 @@ fn report_cycle(&self,
 
         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 @@ fn report_cycle(&self,
         }
 
         match cycle[0] {
+            AstConvRequest::GetGenerics(def_id) |
             AstConvRequest::GetItemTypeScheme(def_id) |
             AstConvRequest::GetTraitDef(def_id) => {
                 err.note(
@@ -303,6 +306,14 @@ fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'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<ty::TypeScheme<'tcx>, ErrorReported>
     {
@@ -362,11 +373,7 @@ fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
         None
     }
 
-    fn ty_infer(&self,
-                _ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
-                _substs: Option<&mut Substs<'tcx>>,
-                _space: Option<ParamSpace>,
-                span: Span) -> Ty<'tcx> {
+    fn ty_infer(&self, span: Span) -> Ty<'tcx> {
         struct_span_err!(
             self.tcx().sess,
             span,
@@ -452,35 +459,38 @@ fn get_type_parameter_bounds(&self,
 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<ty::Predicate<'tcx>>
     {
         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 predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-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::<Vec<String>>().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::<Vec<String>>()
-                                 .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<DefId>,
+                                  super_predicates: Vec<ty::Predicate<'tcx>>,
+                                  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., `<T:Foo>`).
     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,
                                     &param.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 &param.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 &region_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<hir::Ty>,
-                                            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(&param.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::PolyProjectionPredicate<'tcx>>)
-                                         -> 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", &param_ty.to_string());
+            report_unused_parameter(ccx, param.span, "type", &param_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(&region) && // (*)
             !input_parameters.contains(&ctp::Parameter::Region(region))
index 337b87ce994ad93e50b21f740d0fe1eea2de75dc..fe1cb3d6badcd06dc97ba5f9f834ed5fa73d02ee 100644 (file)
@@ -4018,7 +4018,7 @@ struct Simba {
 //  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 @@ struct Simba {
 //  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,
index 11743ade2d469260008a5b01688be69e48a938d5..8a8232535c77592ae9936d6545899bc1e257ad58 100644 (file)
 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,
index 58d1ec9d02a954d32047024e8b23b6919a03f9b8..9aca779dd89c4f7ee01758eee09ae012eefff077 100644 (file)
@@ -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 @@ fn anon_type_scope(&self) -> Option<AnonTypeScope> {
 }
 
 #[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<R> {
     base_scope: R,
-    anon_scope: Option<AnonTypeScope<'a>>
+    anon_scope: Option<AnonTypeScope>
 }
 
-impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R>  {
-    pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope<'a>>) -> Self {
+impl<R: RegionScope> MaybeWithAnonTypes<R>  {
+    pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
         MaybeWithAnonTypes {
             base_scope: base_scope,
             anon_scope: anon_scope
@@ -105,7 +108,7 @@ pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope<'a>>) -> Self {
     }
 }
 
-impl<'a, R: RegionScope> RegionScope for MaybeWithAnonTypes<'a, R> {
+impl<R: RegionScope> RegionScope for MaybeWithAnonTypes<R> {
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
         self.base_scope.object_lifetime_default(span)
     }
index a4faee8f633ed71a423c5bce34392a1daae94365..536fa629fd611837154ddb733c386f7a09da7af2 100644 (file)
@@ -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 @@ fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
         let tcx = self.terms_cx.tcx;
         assert!(is_lifetime(&tcx.map, param_id));
         match tcx.named_region_map.defs.get(&param_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 @@ fn declared_variance(&self,
                          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 @@ fn declared_variance(&self,
             // 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 @@ fn add_constraints_from_trait_ref(&mut self,
         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 @@ fn add_constraints_from_ty(&mut self,
                 // 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 @@ fn add_constraints_from_ty(&mut self,
                 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<T+'a>` 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 @@ fn add_constraints_from_substs(&mut self,
                                    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 @@ fn add_constraints_from_substs(&mut self,
 
         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 @@ fn add_constraints_from_substs(&mut self,
 
         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 @@ fn add_constraints_from_region(&mut self,
                                    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);
index 0763cfd7e2e6064d5c1a31f918c603301b5a3798..d3b63119bcb324fad45016f1ea72e4b2ea98eae7 100644 (file)
@@ -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 @@ fn write(&self) {
         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);
index d9e7e8cbf7df4eb16c948e1666bf239366605784..d30cbc8f117cf03c98668f4409789aad0e660e91 100644 (file)
@@ -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 @@ fn add_inferreds_for_item(&mut self,
 
         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 @@ fn add_inferreds_for_item(&mut self,
     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 @@ fn add_inferred(&mut self,
         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
         }
     }
 
index 3d6925041cf5b0e2839e3e1d5fea9e137f406149..013433336a1d5396e08f90bf0e37d3c2d2f4e9f9 100644 (file)
@@ -21,7 +21,6 @@
 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,
         }
     });
index 99d2732c4bb06c300bad012c7589c08770d94626..75d21399f05e69d28f59a2aa35b0d9d6fb12c8e8 100644 (file)
@@ -41,7 +41,7 @@
 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 @@ fn clean(&self, cx: &DocContext) -> Vec<U> {
     }
 }
 
-impl<T: Clean<U>, U> Clean<VecPerParamSpace<U>> for VecPerParamSpace<T> {
-    fn clean(&self, cx: &DocContext) -> VecPerParamSpace<U> {
-        self.map(|x| x.clean(cx))
-    }
-}
-
 impl<T: Clean<U>, U> Clean<U> for P<T> {
     fn clean(&self, cx: &DocContext) -> U {
         (**self).clean(cx)
@@ -630,33 +624,10 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
     }
 }
 
-impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
-        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<DefId>,
-                        bindings: Vec<TypeBinding>, 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<DefId>, has_self: bool,
+                        bindings: Vec<TypeBinding>, 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<DefId>,
 
 // 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<DefId>,
-                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
+fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self: bool,
+                 bindings: Vec<TypeBinding>, 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 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
             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 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
         };
         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 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
     }
 }
 
-impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
+impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
     fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
         let mut v = Vec::new();
-        v.extend(self.regions.iter().filter_map(|r| r.clean(cx)).map(RegionBound));
+        v.extend(self.regions.iter().filter_map(|r| r.clean(cx))
+                     .map(RegionBound));
         v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
             trait_: t.clean(cx),
             lifetimes: vec![]
@@ -910,7 +882,7 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
 impl<'a> Clean<WherePredicate> 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 @@ fn clean(&self, cx: &DocContext) -> Generics {
 }
 
 impl<'a, 'tcx> Clean<Generics> 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::<Vec<_>>();
-        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::<Vec<_>>();
 
-        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 @@ fn clean(&self, cx: &DocContext) -> Item {
 
 impl<'tcx> Clean<Item> 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 @@ fn fold_ty(&mut self, ty: P<hir::Ty>) -> P<hir::Ty> {
     fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime {
         let def = self.tcx.named_region_map.defs.get(&lt.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 @@ fn clean(&self, cx: &DocContext) -> Type {
                 };
                 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 @@ fn clean(&self, cx: &DocContext) -> Type {
                     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 @@ fn clean(&self, cx: &DocContext) -> Type {
                 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 @@ fn clean(&self, cx: &DocContext) -> Item {
             // 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 @@ fn clean(&self, cx: &DocContext) -> Item {
     }
 }
 
-impl<'a> Clean<Typedef> 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<DefId>,
                t: ty::Ty, name: &str,
                fallback: fn(Box<Type>) -> Type) -> Type {
index c0faa04323e47ddd2435a393f72166920a848757..7ae177439064f9c19d642c82009068b0ded9391c 100644 (file)
 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<WP>) -> Vec<WP> {
@@ -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_))
 }
index 2b3b83cb7ec631bca0e173ceccea19002a54f018..47892781902ea8491fbdb9063236bfc30d14166c 100644 (file)
@@ -37,7 +37,7 @@ impl SomeGenericTrait<u64> 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]<u64, i32>
+    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0]<i32, u64>
 }
 
 // Non-generic impl of generic trait
@@ -54,16 +54,16 @@ fn main() {
     //~ TRANS_ITEM fn trait_method_default_impl::SomeTrait[0]::bar[0]<i8, &str>
     let _ = 2i8.bar("&str");
 
-    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u64, i32, char>
+    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i32, u64, char>
     0i32.bar(0u64, 'c');
 
-    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u64, i32, &str>
+    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i32, u64, &str>
     0i32.bar(0u64, "&str");
 
-    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i8, u32, &[char; 1]>
+    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i8, &[char; 1]>
     0u32.bar(0i8, &['c']);
 
-    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<i16, u32, ()>
+    //~ TRANS_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::bar[0]<u32, i16, ()>
     0u32.bar(0i16, ());
 }
 
index 3d3b795b2291a095241b5a94b59dd9575a07d231..ddf16a2278e5bd140cca704c6992e27dafb09f8e 100644 (file)
@@ -25,7 +25,8 @@ impl Foo for Def {
 }
 
 pub fn test<A: Foo, B: Foo>() {
-    let _array: [u32; <A as Foo>::Y]; //~ error: the parameter type
+    let _array: [u32; <A as Foo>::Y];
+    //~^ ERROR the trait bound `A: Foo` is not satisfied
 }
 
 fn main() {
index b6d5e5458ff0866405159e693076477f2cf32a40..2591d7bcbaef4e2cc73e50bc17ff70ae97d4f000 100644 (file)
@@ -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<T: ?Sized> Mirror for T { type It = Self; }
 struct S(Option<<S as Mirror>::It>);
 
-#[rustc_no_mir] // FIXME #27840 MIR tries to represent `std::option::Option<S>` first.
 fn main() {
     let _s = S(None);
 }
index 060a66846d36f7afcaba4e4a38ac03f7d95c9fe3..1dd008810788b0fb4a56bdd9bb35a609b3af2ec3 100644 (file)
@@ -10,5 +10,7 @@
 
 #![feature(default_type_parameter_fallback)]
 
-fn avg<T=T::Item>(_: T) {} //~ ERROR associated type `Item` not found for `T`
+fn avg<T=T::Item>(_: T) {}
+//~^ ERROR type parameters with a default cannot use forward declared identifiers
+
 fn main() {}
index 0ed0861d34af1fe7744a6db319611db233e7e1ca..5539a26d2a1702df997d0457a511c76c9ea8ae67 100644 (file)
@@ -20,12 +20,12 @@ fn method(&'a self) { }
 }
 
 #[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: <T as Trait<'a>>::Type
 }
 
index 2b7b05970d90f4c15f8830398eeaa50b76cc1e5d..2f422bfd38cc7fcb340f3068b8a109e6faf3221e 100644 (file)
@@ -18,7 +18,7 @@
 // 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<Fn(i32) -> &'a i32 + 'static>
 }
 
index dfa5dc1444151ac76e58cea7aa5a71443fd62657..99416057b25408341ea5b60582dbaf79de2376b2 100644 (file)
 #![feature(rustc_attrs)]
 
 #[rustc_variance]
-trait Foo: 'static { //~ ERROR types=[[];[o];[]]
+trait Foo: 'static { //~ ERROR types=[o]
 }
 
 #[rustc_variance]
-trait Bar<T> { //~ ERROR types=[[o];[o];[]]
+trait Bar<T> { //~ ERROR types=[o, o]
     fn do_it(&self)
         where T: 'static;
 }
index bb452eecbfc8b3551522d1acab284f0e7a4feaaa..78591063de8abc4db2094b6a42a1c1dd63562bd1 100644 (file)
@@ -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 @@
 // 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 @@
 // 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 @@
 // 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),
 }
 
 // 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 @@
 // 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),
index 9beb90d0b24835777550fc03adbda379e34faf9f..d8af30da163bf8a735550357ce20257c5d865525 100644 (file)
@@ -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]),
 }
 
 #[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>
 }
 
index b6f197987bab1df73c4b5a3552f229f36f9234a3..150a1aa56fe721e956614328416e07c1b0eff0ca 100644 (file)
 // influence variance.
 
 #[rustc_variance]
-trait Getter<T> { //~ ERROR types=[[o];[o];[]]
+trait Getter<T> { //~ ERROR types=[o, o]
     fn get(&self) -> T;
 }
 
 #[rustc_variance]
-trait Setter<T> { //~ ERROR types=[[o];[o];[]]
+trait Setter<T> { //~ ERROR types=[o, o]
     fn get(&self, T);
 }
 
 #[rustc_variance]
-struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[[+, +];[];[]]
+struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[+, +]
     t: T, u: U
 }
 
 #[rustc_variance]
-enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[*, +];[];[]]
+enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[*, +]
     //~^ ERROR parameter `U` is never used
     Foo(T)
 }
 
 #[rustc_variance]
-trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[o, o];[o];[]]
+trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[o, o, o]
     fn getter(&self, u: U) -> T;
 }
 
 #[rustc_variance]
-trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[o];[o];[]]
+trait TestTrait2<U> : Getter<U> { //~ ERROR types=[o, o]
 }
 
 #[rustc_variance]
-trait TestTrait3<U> { //~ ERROR types=[[o];[o];[]]
+trait TestTrait3<U> { //~ ERROR types=[o, o]
     fn getter<T:Getter<U>>(&self);
 }
 
 #[rustc_variance]
-struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[[*, +];[];[]]
+struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[*, +]
     //~^ ERROR parameter `U` is never used
     t: T
 }
 
 #[rustc_variance]
-struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[[*, +];[];[]]
+struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[*, +]
     //~^ ERROR parameter `U` is never used
     t: T
 }
index f0ca1edd5638718c50ace55b5dfb97571f520f39..4244b0e1d8b8b27104150a40cd03449694e724b0 100644 (file)
@@ -21,7 +21,7 @@
 trait T { fn foo(&self); }
 
 #[rustc_variance]
-struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
+struct TOption<'a> { //~ ERROR regions=[-]
     v: Option<Box<T + 'a>>,
 }
 
index a02f20656e7b579362431f2150b53c18aa9523dd..c47710d6d376d0e2bcdf1354fd62cf2c7411687e 100644 (file)
 #![feature(rustc_attrs)]
 
 #[rustc_variance]
-struct TestImm<A, B> { //~ ERROR types=[[+, +];[];[]]
+struct TestImm<A, B> { //~ ERROR types=[+, +]
     x: A,
     y: B,
 }
 
 #[rustc_variance]
-struct TestMut<A, B:'static> { //~ ERROR types=[[+, o];[];[]]
+struct TestMut<A, B:'static> { //~ ERROR types=[+, o]
     x: A,
     y: &'static mut B,
 }
 
 #[rustc_variance]
-struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[+, o];[];[]]
+struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[+, o]
     m: TestMut<A, B>
 }
 
 #[rustc_variance]
-struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[o, o];[];[]]
+struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[o, o]
     n: TestMut<A, B>,
     m: TestMut<B, A>
 }
 
 #[rustc_variance]
-trait Getter<A> { //~ ERROR types=[[o];[o];[]]
+trait Getter<A> { //~ ERROR types=[o, o]
     fn get(&self) -> A;
 }
 
 #[rustc_variance]
-trait Setter<A> { //~ ERROR types=[[o];[o];[]]
+trait Setter<A> { //~ ERROR types=[o, o]
     fn set(&mut self, a: A);
 }
 
 #[rustc_variance]
-trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]]
+trait GetterSetter<A> { //~ ERROR types=[o, o]
     fn get(&self) -> A;
     fn set(&mut self, a: A);
 }
 
 #[rustc_variance]
-trait GetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
+trait GetterInTypeBound<A> { //~ 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<A>`.  Since this dictionary is an input, it is
 }
 
 #[rustc_variance]
-trait SetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
+trait SetterInTypeBound<A> { //~ ERROR types=[o, o]
     fn do_it<T:Setter<A>>(&self);
 }
 
 #[rustc_variance]
-struct TestObject<A, R> { //~ ERROR types=[[o, o];[];[]]
+struct TestObject<A, R> { //~ ERROR types=[o, o]
     n: Box<Setter<A>+Send>,
     m: Box<Getter<R>+Send>,
 }
index 2fd8bf20c79974beef8c80e77077a1dd8dedf268..d5164412358fc4dbba312b0e7dab4858ee6f61d5 100644 (file)
 // 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<A> { //~ ERROR types=[[o];[];[]]
+struct InvariantCell<A> { //~ ERROR types=[o]
     t: Cell<A>
 }
 
 #[rustc_variance]
-struct InvariantIndirect<A> { //~ ERROR types=[[o];[];[]]
+struct InvariantIndirect<A> { //~ ERROR types=[o]
     t: InvariantCell<A>
 }
 
 #[rustc_variance]
-struct Covariant<A> { //~ ERROR types=[[+];[];[]]
+struct Covariant<A> { //~ ERROR types=[+]
     t: A, u: fn() -> A
 }
 
 #[rustc_variance]
-struct Contravariant<A> { //~ ERROR types=[[-];[];[]]
+struct Contravariant<A> { //~ ERROR types=[-]
     t: fn(A)
 }
 
 #[rustc_variance]
-enum Enum<A,B,C> { //~ ERROR types=[[+, -, o];[];[]]
+enum Enum<A,B,C> { //~ ERROR types=[+, -, o]
     Foo(Covariant<A>),
     Bar(Contravariant<B>),
     Zed(Covariant<C>,Contravariant<C>)
index b116d9c3c41cfd114622f1c4701ea2ef073e4070..f93447b642a2050b5aa5a98a5d53207624812547 100644 (file)
@@ -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<i32>(tmp2,); // scope 1 at storage_ranges.rs:14:18: 14:25
+//         tmp1 = std::option::Option<i32>::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