about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-08-15 01:07:09 +0300
committerEduard Burtescu <edy.burt@gmail.com>2016-08-17 05:50:57 +0300
commitc1cfd58cbdb84f834b8907dc5e1c7242c451225d (patch)
tree3eaab8714d95f7daab2469b39b50d7dc322a7d03
parent4158673ad7150f4fa02fbea3654e8cf1628beb0b (diff)
downloadrust-c1cfd58cbdb84f834b8907dc5e1c7242c451225d.tar.gz
rust-c1cfd58cbdb84f834b8907dc5e1c7242c451225d.zip
rustc: remove SelfSpace from ParamSpace.
-rw-r--r--src/librustc/hir/def.rs5
-rw-r--r--src/librustc/middle/dead.rs2
-rw-r--r--src/librustc/traits/coherence.rs6
-rw-r--r--src/librustc/traits/error_reporting.rs4
-rw-r--r--src/librustc/traits/object_safety.rs9
-rw-r--r--src/librustc/ty/context.rs2
-rw-r--r--src/librustc/ty/error.rs3
-rw-r--r--src/librustc/ty/flags.rs4
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/sty.rs14
-rw-r--r--src/librustc/ty/subst.rs78
-rw-r--r--src/librustc/util/ppaux.rs67
-rw-r--r--src/librustc_borrowck/borrowck/mir/elaborate_drops.rs6
-rw-r--r--src/librustc_metadata/astencode.rs2
-rw-r--r--src/librustc_metadata/tydecode.rs6
-rw-r--r--src/librustc_resolve/lib.rs32
-rw-r--r--src/librustc_save_analysis/lib.rs2
-rw-r--r--src/librustc_trans/partitioning.rs2
-rw-r--r--src/librustc_typeck/astconv.rs52
-rw-r--r--src/librustc_typeck/check/closure.rs2
-rw-r--r--src/librustc_typeck/check/method/mod.rs6
-rw-r--r--src/librustc_typeck/check/method/probe.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs27
-rw-r--r--src/librustc_typeck/check/wfcheck.rs45
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/collect.rs83
-rw-r--r--src/librustc_typeck/variance/constraints.rs8
-rw-r--r--src/librustc_typeck/variance/solve.rs10
-rw-r--r--src/librustc_typeck/variance/terms.rs12
-rw-r--r--src/librustdoc/clean/mod.rs38
-rw-r--r--src/test/compile-fail/issue-26548.rs4
-rw-r--r--src/test/compile-fail/issue-26812.rs4
-rw-r--r--src/test/compile-fail/variance-associated-types.rs4
-rw-r--r--src/test/compile-fail/variance-object-types.rs2
-rw-r--r--src/test/compile-fail/variance-region-bounds.rs4
-rw-r--r--src/test/compile-fail/variance-regions-direct.rs14
-rw-r--r--src/test/compile-fail/variance-regions-indirect.rs10
-rw-r--r--src/test/compile-fail/variance-trait-bounds.rs18
-rw-r--r--src/test/compile-fail/variance-trait-object-bound.rs2
-rw-r--r--src/test/compile-fail/variance-types-bounds.rs20
-rw-r--r--src/test/compile-fail/variance-types.rs12
41 files changed, 276 insertions, 357 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 218681efb7d..d15d51aed09 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use ty::subst::ParamSpace;
 use util::nodemap::NodeMap;
 use syntax::ast;
 use hir;
@@ -31,7 +30,7 @@ pub enum Def {
     AssociatedTy(DefId /* trait */, DefId),
     Trait(DefId),
     PrimTy(hir::PrimTy),
-    TyParam(ParamSpace, u32, DefId, ast::Name),
+    TyParam(DefId),
     Upvar(DefId,        // def id of closed over local
              ast::NodeId,  // node id of closed over local
              usize,        // index in the freevars list of the closure
@@ -122,7 +121,7 @@ impl Def {
         match *self {
             Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) |
             Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) |
-            Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) |
+            Def::TyParam(id) | Def::Struct(id) | Def::Trait(id) |
             Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) |
             Def::Local(id, _) | Def::Upvar(id, _, _, _) => {
                 id
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 7412b5fc804..20e281816b8 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
             if self.tcx.trait_of_item(def.def_id()).is_some() => {
                 if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
-                    match substs.substs.types.get(subst::SelfSpace, 0).sty {
+                    match substs.substs.types.get(subst::TypeSpace, 0).sty {
                         TyEnum(tyid, _) | TyStruct(tyid, _) => {
                             self.check_def_id(tyid.did)
                         }
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index f1701d60fd0..a5a415dd27c 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -14,7 +14,6 @@ use super::{SelectionContext, Obligation, ObligationCause};
 
 use middle::cstore::LOCAL_CRATE;
 use hir::def_id::DefId;
-use ty::subst::TypeSpace;
 use ty::{self, Ty, TyCtxt};
 use infer::{InferCtxt, TypeOrigin};
 use syntax_pos::DUMMY_SP;
@@ -160,12 +159,9 @@ fn orphan_check_trait_ref<'tcx>(tcx: TyCtxt,
 
     // First, create an ordered iterator over all the type parameters to the trait, with the self
     // type appearing first.
-    let input_tys = Some(trait_ref.self_ty());
-    let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace));
-
     // Find the first input type that either references a type parameter OR
     // some local type.
-    for input_ty in input_tys {
+    for input_ty in trait_ref.input_types() {
         if ty_is_local(tcx, input_ty, infer_is_local) {
             debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
 
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index e67c0ba8053..77c1137c6c3 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 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.get_slice(TypeSpace)[1..].iter()
+                        .zip(&impl_trait_ref.substs.types.get_slice(TypeSpace)[1..])
                         .all(|(u,v)| self.fuzzy_match_tys(u, v))
                     {
                         fuzzy_match_impls.push(def_id);
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index ecfa7930d02..11cf759859c 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -20,7 +20,7 @@
 use super::elaborate_predicates;
 
 use hir::def_id::DefId;
-use ty::subst::{self, SelfSpace, TypeSpace};
+use ty::subst;
 use traits;
 use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
 use std::rc::Rc;
@@ -146,10 +146,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 match predicate {
                     ty::Predicate::Trait(ref data) => {
                         // In the case of a trait predicate, we can skip the "self" type.
-                        data.0.trait_ref.substs.types.get_slice(TypeSpace)
-                                                     .iter()
-                                                     .cloned()
-                                                     .any(|t| t.has_self_ty())
+                        data.0.trait_ref.input_types()[1..].iter().any(|t| t.has_self_ty())
                     }
                     ty::Predicate::Projection(..) |
                     ty::Predicate::WellFormed(..) |
@@ -325,7 +322,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         ty.maybe_walk(|ty| {
             match ty.sty {
                 ty::TyParam(ref param_ty) => {
-                    if param_ty.space == SelfSpace {
+                    if param_ty.is_self() {
                         error = true;
                     }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 9356b408a51..c2daa81ca7d 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1353,7 +1353,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn mk_self_type(self) -> Ty<'tcx> {
-        self.mk_param(subst::SelfSpace, 0, keywords::SelfType.name())
+        self.mk_param(subst::TypeSpace, 0, keywords::SelfType.name())
     }
 
     pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 933746ebc2a..17f9b6c2599 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use ty::subst;
 use infer::type_variable;
 use ty::{self, BoundRegion, Region, Ty, TyCtxt};
 
@@ -258,7 +257,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
             ty::TyInfer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
             ty::TyProjection(_) => "associated type".to_string(),
             ty::TyParam(ref p) => {
-                if p.space == subst::SelfSpace {
+                if p.is_self() {
                     "Self".to_string()
                 } else {
                     "type parameter".to_string()
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 312b09cd27d..900e1841fb5 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ty::subst::{self, Substs};
+use ty::subst::Substs;
 use ty::{self, Ty, TypeFlags, TypeFoldable};
 
 pub struct FlagComputation {
@@ -77,7 +77,7 @@ impl FlagComputation {
 
             &ty::TyParam(ref p) => {
                 self.add_flags(TypeFlags::HAS_LOCAL_NAMES);
-                if p.space == subst::SelfSpace {
+                if p.is_self() {
                     self.add_flags(TypeFlags::HAS_SELF);
                 } else {
                     self.add_flags(TypeFlags::HAS_PARAMS);
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 36784e40064..96537904d36 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1225,7 +1225,7 @@ impl<'tcx> TraitRef<'tcx> {
     }
 
     pub fn self_ty(&self) -> Ty<'tcx> {
-        *self.substs.types.get(subst::SelfSpace, 0)
+        *self.substs.types.get(subst::TypeSpace, 0)
     }
 
     pub fn input_types(&self) -> &[Ty<'tcx>] {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index f31b844f04f..8786e2d16d2 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -305,7 +305,7 @@ pub struct TraitObject<'tcx> {
 ///
 /// 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`.
+/// `TypeSpace` and `U` as parameter 1 in the `TypeSpace`.
 ///
 /// Trait references also appear in object types like `Foo<U>`, but in
 /// that case the `Self` parameter is absent from the substitutions.
@@ -512,7 +512,7 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn for_self() -> ParamTy {
-        ParamTy::new(subst::SelfSpace, 0, keywords::SelfType.name())
+        ParamTy::new(subst::TypeSpace, 0, keywords::SelfType.name())
     }
 
     pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
@@ -524,7 +524,13 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 
     pub fn is_self(&self) -> bool {
-        self.space == subst::SelfSpace && self.idx == 0
+        if self.name == keywords::SelfType.name() {
+            assert_eq!(self.space, subst::TypeSpace);
+            assert_eq!(self.idx, 0);
+            true
+        } else {
+            false
+        }
     }
 }
 
@@ -954,7 +960,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
 
     pub fn is_self(&self) -> bool {
         match self.sty {
-            TyParam(ref p) => p.space == subst::SelfSpace,
+            TyParam(ref p) => p.is_self(),
             _ => false
         }
     }
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 00537f9d6c5..2f95baa5625 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -47,8 +47,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                   r: Vec<ty::Region>)
                   -> &'tcx Substs<'tcx>
     {
-        Substs::new(tcx, VecPerParamSpace::new(vec![], vec![], t),
-                    VecPerParamSpace::new(vec![], vec![], r))
+        Substs::new(tcx, VecPerParamSpace::new(vec![], t),
+                    VecPerParamSpace::new(vec![], r))
     }
 
     pub fn new_type(tcx: TyCtxt<'a, 'gcx, 'tcx>,
@@ -56,18 +56,19 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                     r: Vec<ty::Region>)
                     -> &'tcx Substs<'tcx>
     {
-        Substs::new(tcx, VecPerParamSpace::new(vec![], t, vec![]),
-                    VecPerParamSpace::new(vec![], r, vec![]))
+        Substs::new(tcx, VecPerParamSpace::new(t, vec![]),
+                    VecPerParamSpace::new(r, vec![]))
     }
 
     pub fn new_trait(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                     t: Vec<Ty<'tcx>>,
+                     mut t: Vec<Ty<'tcx>>,
                      r: Vec<ty::Region>,
                      s: Ty<'tcx>)
                     -> &'tcx Substs<'tcx>
     {
-        Substs::new(tcx, VecPerParamSpace::new(vec![s], t, vec![]),
-                    VecPerParamSpace::new(vec![], r, vec![]))
+        t.insert(0, s);
+        Substs::new(tcx, VecPerParamSpace::new(t, vec![]),
+                    VecPerParamSpace::new(r, vec![]))
     }
 
     pub fn empty(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
@@ -90,12 +91,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
         let defs = tcx.lookup_generics(def_id);
         let mut substs = Substs {
             types: VecPerParamSpace {
-                self_limit: 0,
                 type_limit: 0,
                 content: Vec::with_capacity(defs.types.content.len())
             },
             regions: VecPerParamSpace {
-                self_limit: 0,
                 type_limit: 0,
                 content: Vec::with_capacity(defs.regions.content.len())
             }
@@ -104,7 +103,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
         for &space in &ParamSpace::all() {
             for def in defs.regions.get_slice(space) {
                 assert_eq!(def.space, space);
-                assert!(space != SelfSpace);
 
                 let region = mk_region(def, &substs);
                 substs.regions.content.push(region);
@@ -120,11 +118,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                 let ty = mk_type(def, &substs);
                 substs.types.content.push(ty);
 
-                if space == SelfSpace {
-                    substs.types.self_limit += 1;
-                }
-
-                if space <= TypeSpace {
+                if space == TypeSpace {
                     substs.types.type_limit += 1;
                 }
             }
@@ -155,7 +149,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                        target_substs: &Substs<'tcx>)
                        -> &'tcx Substs<'tcx> {
         let defs = tcx.lookup_generics(source_ancestor);
-        assert_eq!(self.types.len(SelfSpace), defs.types.len(SelfSpace));
         assert_eq!(self.types.len(TypeSpace), defs.types.len(TypeSpace));
         assert_eq!(target_substs.types.len(FnSpace), 0);
         assert_eq!(defs.types.len(FnSpace), 0);
@@ -195,29 +188,26 @@ impl<'tcx> Decodable for &'tcx Substs<'tcx> {
 #[derive(PartialOrd, Ord, PartialEq, Eq, Copy,
            Clone, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub enum ParamSpace {
-    SelfSpace,  // Self parameter on a trait
     TypeSpace,  // Type parameters attached to a type definition, trait, or impl
     FnSpace,    // Type parameters attached to a method or fn
 }
 
 impl ParamSpace {
-    pub fn all() -> [ParamSpace; 3] {
-        [SelfSpace, TypeSpace, FnSpace]
+    pub fn all() -> [ParamSpace; 2] {
+        [TypeSpace, FnSpace]
     }
 
     pub fn to_uint(self) -> usize {
         match self {
-            SelfSpace => 0,
-            TypeSpace => 1,
-            FnSpace => 2,
+            TypeSpace => 0,
+            FnSpace => 1,
         }
     }
 
     pub fn from_uint(u: usize) -> ParamSpace {
         match u {
-            0 => SelfSpace,
-            1 => TypeSpace,
-            2 => FnSpace,
+            0 => TypeSpace,
+            1 => FnSpace,
             _ => bug!("Invalid ParamSpace: {}", u)
         }
     }
@@ -235,18 +225,15 @@ pub struct VecPerParamSpace<T> {
     // Here is how the representation corresponds to the abstraction
     // i.e. the "abstraction function" AF:
     //
-    // AF(self) = (self.content[..self.self_limit],
-    //             self.content[self.self_limit..self.type_limit],
+    // AF(self) = (self.content[..self.type_limit],
     //             self.content[self.type_limit..])
-    self_limit: usize,
     type_limit: usize,
     content: 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(SelfSpace),
+        write!(f, "[{:?};{:?}]",
                self.get_slice(TypeSpace),
                self.get_slice(FnSpace))
     }
@@ -255,43 +242,34 @@ impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
 impl<T> VecPerParamSpace<T> {
     fn limits(&self, space: ParamSpace) -> (usize, usize) {
         match space {
-            SelfSpace => (0, self.self_limit),
-            TypeSpace => (self.self_limit, self.type_limit),
+            TypeSpace => (0, self.type_limit),
             FnSpace => (self.type_limit, self.content.len()),
         }
     }
 
     pub fn empty() -> VecPerParamSpace<T> {
         VecPerParamSpace {
-            self_limit: 0,
             type_limit: 0,
             content: Vec::new()
         }
     }
 
-    /// `s` is the self space.
     /// `t` is the type space.
     /// `f` is the fn space.
-    pub fn new(s: Vec<T>, t: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
-        let self_limit = s.len();
-        let type_limit = self_limit + t.len();
+    pub fn new(t: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
+        let type_limit = t.len();
 
-        let mut content = s;
-        content.extend(t);
+        let mut content = t;
         content.extend(f);
 
         VecPerParamSpace {
-            self_limit: self_limit,
             type_limit: type_limit,
             content: content,
         }
     }
 
-    fn new_internal(content: Vec<T>, self_limit: usize, type_limit: usize)
-                    -> VecPerParamSpace<T>
-    {
+    fn new_internal(content: Vec<T>, type_limit: usize) -> VecPerParamSpace<T> {
         VecPerParamSpace {
-            self_limit: self_limit,
             type_limit: type_limit,
             content: content,
         }
@@ -336,18 +314,14 @@ impl<T> VecPerParamSpace<T> {
 
     pub fn map<U, P>(&self, pred: P) -> VecPerParamSpace<U> where P: FnMut(&T) -> U {
         let result = self.as_full_slice().iter().map(pred).collect();
-        VecPerParamSpace::new_internal(result,
-                                       self.self_limit,
-                                       self.type_limit)
+        VecPerParamSpace::new_internal(result, self.type_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.self_limit,
-                                       self.type_limit)
+        VecPerParamSpace::new_internal(result, self.type_limit)
     }
 }
 
@@ -639,8 +613,6 @@ impl<'a, 'gcx, 'tcx> ty::ExistentialTraitRef<'tcx> {
                          -> ty::ExistentialTraitRef<'tcx> {
         let Substs { mut types, regions } = trait_ref.substs.clone();
 
-        assert_eq!(types.self_limit, 1);
-        types.self_limit = 0;
         types.type_limit -= 1;
         types.content.remove(0);
 
@@ -665,8 +637,6 @@ impl<'a, 'gcx, 'tcx> ty::PolyExistentialTraitRef<'tcx> {
         self.map_bound(|trait_ref| {
             let Substs { mut types, regions } = trait_ref.substs.clone();
 
-            assert_eq!(types.self_limit, 0);
-            types.self_limit = 1;
             types.type_limit += 1;
             types.content.insert(0, self_ty);
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index cdbd3070523..800ad865208 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -62,35 +62,36 @@ pub enum Ns {
     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 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)| {
-            substs.and_then(|substs| def.default.subst(tcx, substs))
-                == Some(actual)
-        }).count()
-    } else {
-        0
-    }
-}
-
 pub fn parameterized(f: &mut fmt::Formatter,
                      substs: &subst::Substs,
                      did: DefId,
                      ns: Ns,
                      projections: &[ty::ProjectionPredicate])
                      -> fmt::Result {
-    let (fn_trait_kind, verbose, item_name, is_in_trait) = ty::tls::with(|tcx| {
-        let is_in_trait = ns == Ns::Value && tcx.trait_of_item(did).is_some();
-        if is_in_trait {
-            write!(f, "<{} as ", substs.types.get(subst::SelfSpace, 0))?;
+    let mut verbose = false;
+    let mut num_supplied_defaults = 0;
+    let mut has_self = false;
+    let (fn_trait_kind, item_name) = ty::tls::with(|tcx| {
+        verbose = tcx.sess.verbose();
+        let generics = tcx.lookup_generics(did);
+        if !verbose {
+            let ty_params = generics.types.get_slice(subst::TypeSpace);
+            if ty_params.last().map_or(false, |def| def.default.is_some()) {
+                if let Some(substs) = tcx.lift(&substs) {
+                    let tps = substs.types.get_slice(subst::TypeSpace);
+                    for (def, actual) in ty_params.iter().zip(tps).rev() {
+                        if def.default.subst(tcx, substs) != Some(actual) {
+                            break;
+                        }
+                        num_supplied_defaults += 1;
+                    }
+                }
+            }
+        }
+
+        has_self = generics.has_self;
+        if ns == Ns::Value && has_self {
+            write!(f, "<{} as ", substs.types.get(subst::TypeSpace, 0))?;
         }
 
         let (did, item_name) = if ns == Ns::Value {
@@ -107,15 +108,12 @@ pub fn parameterized(f: &mut fmt::Formatter,
             (did, None)
         };
         write!(f, "{}", tcx.item_path_str(did))?;
-        Ok((tcx.lang_items.fn_trait_kind(did),
-            tcx.sess.verbose(),
-            item_name,
-            is_in_trait))
+        Ok((tcx.lang_items.fn_trait_kind(did), item_name))
     })?;
 
     if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
         let projection_ty = projections[0].ty;
-        if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 0).sty {
+        if let TyTuple(ref args) = substs.types.get(subst::TypeSpace, 1).sty {
             return fn_sig(f, args, false, projection_ty);
         }
     }
@@ -160,18 +158,9 @@ pub fn parameterized(f: &mut fmt::Formatter,
 
     print_regions(f, "<", substs.regions.get_slice(subst::TypeSpace))?;
 
-    let num_supplied_defaults = if verbose {
-        0
-    } else {
-        ty::tls::with(|tcx| {
-            let generics = tcx.lookup_generics(did);
-            number_of_supplied_defaults(tcx, substs, subst::TypeSpace, generics)
-        })
-    };
-
     let tps = substs.types.get_slice(subst::TypeSpace);
 
-    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)?;
     }
@@ -189,7 +178,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
     if ns == Ns::Value {
         empty.set(true);
 
-        if is_in_trait {
+        if has_self {
             write!(f, ">")?;
         }
 
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
index df91ec2b98d..9f300b5b29b 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
@@ -16,7 +16,7 @@ use super::{drop_flag_effects_for_location, on_all_children_bits};
 use super::{DropFlagState, MoveDataParamEnv};
 use super::patch::MirPatch;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::subst::{Subst, Substs, VecPerParamSpace};
+use rustc::ty::subst::{Subst, Substs};
 use rustc::mir::repr::*;
 use rustc::mir::transform::{Pass, MirPass, MirSource};
 use rustc::middle::const_val::ConstVal;
@@ -859,9 +859,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let unit_temp = Lvalue::Temp(self.patch.new_temp(tcx.mk_nil()));
         let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem)
             .unwrap_or_else(|e| tcx.sess.fatal(&e));
-        let substs = Substs::new(tcx,
-            VecPerParamSpace::new(vec![], vec![], vec![ty]),
-            VecPerParamSpace::new(vec![], vec![], vec![]));
+        let substs = Substs::new_fn(tcx, vec![ty], vec![]);
         let fty = tcx.lookup_item_type(free_func).ty.subst(tcx, substs);
 
         self.patch.new_block(BasicBlockData {
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 1b00eee76f6..1ef48e6d656 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -413,7 +413,7 @@ impl tr for Def {
           Def::AssociatedTy(trait_did, did) =>
               Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
           Def::PrimTy(p) => Def::PrimTy(p),
-          Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n),
+          Def::TyParam(did) => Def::TyParam(did.tr(dcx)),
           Def::Upvar(_, nid1, index, nid2) => {
               let nid1 = dcx.tr_id(nid1);
               let nid2 = dcx.tr_id(nid2);
diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs
index 3f0fa9073aa..82d050a1de9 100644
--- a/src/librustc_metadata/tydecode.rs
+++ b/src/librustc_metadata/tydecode.rs
@@ -131,15 +131,15 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
     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 a, mut b, mut c) =  (vec![], vec![], vec![]);
-        for r in &mut [&mut a, &mut b, &mut c] {
+        let (mut a, mut b) =  (vec![], vec![]);
+        for r in &mut [&mut a, &mut b] {
             assert_eq!(self.next(), '[');
             while self.peek() != ']' {
                 r.push(f(self));
             }
             assert_eq!(self.next(), ']');
         }
-        VecPerParamSpace::new(a, b, c)
+        VecPerParamSpace::new(a, b)
     }
 
     pub fn parse_substs(&mut self) -> &'tcx Substs<'tcx> {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 962509be324..65e14eee4bc 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -49,7 +49,6 @@ use rustc::lint;
 use rustc::hir::def::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::ty;
-use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
 use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
 use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
 
@@ -557,7 +556,7 @@ impl<'a> Visitor for Resolver<'a> {
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
         let type_parameters = match foreign_item.node {
             ForeignItemKind::Fn(_, ref generics) => {
-                HasTypeParameters(generics, FnSpace, ItemRibKind)
+                HasTypeParameters(generics, ItemRibKind)
             }
             ForeignItemKind::Static(..) => NoTypeParameters,
         };
@@ -625,10 +624,6 @@ enum TypeParameters<'a, 'b> {
     HasTypeParameters(// Type parameters.
                       &'b Generics,
 
-                      // Identifies the things that these parameters
-                      // were declared on (type, fn, etc)
-                      ParamSpace,
-
                       // The kind of the rib used for type parameters.
                       RibKind<'a>),
 }
@@ -1613,12 +1608,9 @@ impl<'a> Resolver<'a> {
         match item.node {
             ItemKind::Enum(_, ref generics) |
             ItemKind::Ty(_, ref generics) |
-            ItemKind::Struct(_, ref generics) => {
-                self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind),
-                                             |this| visit::walk_item(this, item));
-            }
+            ItemKind::Struct(_, ref generics) |
             ItemKind::Fn(_, _, _, _, ref generics, _) => {
-                self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind),
+                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
                                              |this| visit::walk_item(this, item));
             }
 
@@ -1634,10 +1626,7 @@ impl<'a> Resolver<'a> {
 
             ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the trait-wide type parameters.
-                self.with_type_parameter_rib(HasTypeParameters(generics,
-                                                               TypeSpace,
-                                                               ItemRibKind),
-                                             |this| {
+                self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
                     let local_def_id = this.definitions.local_def_id(item.id);
                     this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
@@ -1660,7 +1649,6 @@ impl<'a> Resolver<'a> {
                                 TraitItemKind::Method(ref sig, _) => {
                                     let type_parameters =
                                         HasTypeParameters(&sig.generics,
-                                                          FnSpace,
                                                           MethodRibKind(!sig.decl.has_self()));
                                     this.with_type_parameter_rib(type_parameters, |this| {
                                         visit::walk_trait_item(this, trait_item)
@@ -1729,10 +1717,10 @@ impl<'a> Resolver<'a> {
         where F: FnOnce(&mut Resolver)
     {
         match type_parameters {
-            HasTypeParameters(generics, space, rib_kind) => {
+            HasTypeParameters(generics, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = HashSet::new();
-                for (index, type_parameter) in generics.ty_params.iter().enumerate() {
+                for type_parameter in &generics.ty_params {
                     let name = type_parameter.ident.name;
                     debug!("with_type_parameter_rib: {}", type_parameter.id);
 
@@ -1745,7 +1733,7 @@ impl<'a> Resolver<'a> {
 
                     // plain insert (no renaming)
                     let def_id = self.definitions.local_def_id(type_parameter.id);
-                    let def = Def::TyParam(space, index as u32, def_id, name);
+                    let def = Def::TyParam(def_id);
                     function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def);
                     self.record_def(type_parameter.id, PathResolution::new(def));
                 }
@@ -1917,10 +1905,7 @@ impl<'a> Resolver<'a> {
                               item_id: NodeId,
                               impl_items: &[ImplItem]) {
         // If applicable, create a rib for the type parameters.
-        self.with_type_parameter_rib(HasTypeParameters(generics,
-                                                       TypeSpace,
-                                                       ItemRibKind),
-                                     |this| {
+        self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
             // Resolve the type parameters.
             this.visit_generics(generics);
 
@@ -1953,7 +1938,6 @@ impl<'a> Resolver<'a> {
                                     // specific type parameters.
                                     let type_parameters =
                                         HasTypeParameters(&sig.generics,
-                                                          FnSpace,
                                                           MethodRibKind(!sig.decl.has_self()));
                                     this.with_type_parameter_rib(type_parameters, |this| {
                                         visit::walk_impl_item(this, impl_item);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 6c9cf1a5625..db535e22f19 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -490,7 +490,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Def::Enum(def_id) |
             Def::TyAlias(def_id) |
             Def::Trait(def_id) |
-            Def::TyParam(_, _, def_id, _) => {
+            Def::TyParam(def_id) => {
                 Some(Data::TypeRefData(TypeRefData {
                     span: sub_span.unwrap(),
                     ref_id: Some(def_id),
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index f24ab0f6557..1e90f273301 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -488,7 +488,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             // DefId, we use the location of the impl after all.
 
             if tcx.trait_of_item(instance.def).is_some() {
-                let self_ty = *instance.substs.types.get(subst::SelfSpace, 0);
+                let self_ty = *instance.substs.types.get(subst::TypeSpace, 0);
                 // This is an implementation of a trait method.
                 return characteristic_def_id_of_type(self_ty).or(Some(instance.def));
             }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5655c7c8e72..109cfd2abf6 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -55,7 +55,7 @@ use hir::def_id::DefId;
 use hir::print as pprust;
 use middle::resolve_lifetime as rl;
 use rustc::lint;
-use rustc::ty::subst::{TypeSpace, SelfSpace, Subst, Substs};
+use rustc::ty::subst::{TypeSpace, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
@@ -455,6 +455,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         // 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.get_slice(TypeSpace);
+            let ty_param_defs = &ty_param_defs[self_ty.is_some() as usize..];
             check_type_argument_count(tcx, span, num_provided, ty_param_defs);
         }
 
@@ -476,13 +477,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             assert_eq!(def.space, TypeSpace);
             regions[def.index as usize]
         }, |def, substs| {
-            assert!(def.space == SelfSpace || def.space == TypeSpace);
+            assert!(def.space == TypeSpace);
             let i = def.index as usize;
-            if def.space == SelfSpace {
-                // Self, which must have been provided.
-                assert_eq!(i, 0);
-                self_ty.expect("Self type parameter missing")
-            } else if num_types_provided.map_or(false, |n| i < n) {
+
+            // Handle Self first, so we can adjust the index to match the AST.
+            if let (0, Some(ty)) = (i, self_ty) {
+                return ty;
+            }
+
+            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) => {
@@ -1325,8 +1329,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
-            (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
+            (&ty::TyParam(_), Def::TyParam(param_did)) => {
                 let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
+                let param_name = tcx.type_parameter_def(param_node_id).name;
                 match self.find_bound_for_assoc_item(param_node_id,
                                                      param_name,
                                                      assoc_name,
@@ -1336,10 +1341,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 }
             }
             _ => {
-                self.report_ambiguous_associated_type(span,
-                                                      &ty.to_string(),
-                                                      "Trait",
-                                                      &assoc_name.as_str());
+                // Don't print TyErr to the user.
+                if !ty.references_error() {
+                    self.report_ambiguous_associated_type(span,
+                                                          &ty.to_string(),
+                                                          "Trait",
+                                                          &assoc_name.as_str());
+                }
                 return (tcx.types.err, Def::Err);
             }
         };
@@ -1477,9 +1485,25 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                                     did,
                                     base_segments.last().unwrap())
             }
-            Def::TyParam(space, index, _, name) => {
+            Def::TyParam(did) => {
                 tcx.prohibit_type_params(base_segments);
-                tcx.mk_param(space, index, name)
+
+                let node_id = tcx.map.as_local_node_id(did).unwrap();
+                let param = tcx.ty_param_defs.borrow().get(&node_id)
+                               .map(ty::ParamTy::for_def);
+                if let Some(p) = param {
+                    p.to_ty(tcx)
+                } else {
+                    // Only while computing defaults of earlier type
+                    // parameters can a type parameter be missing its def.
+                    struct_span_err!(tcx.sess, span, E0128,
+                                     "type parameters with a default cannot use \
+                                      forward declared identifiers")
+                        .span_label(span, &format!("defaulted type parameters \
+                                                    cannot be forward declared"))
+                        .emit();
+                    tcx.types.err
+                }
             }
             Def::SelfTy(_, Some(impl_id)) => {
                 // Self in impl (we know the concrete type).
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 8a007293e64..087549a2f1c 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             return None;
         }
 
-        let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0);
+        let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1);
         let arg_param_ty = self.resolve_type_vars_if_possible(&arg_param_ty);
         debug!("deduce_sig_from_projection: arg_param_ty {:?}", arg_param_ty);
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index e5107af6ca0..a9e08461fd2 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -183,7 +183,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let trait_def = self.tcx.lookup_trait_def(trait_def_id);
 
         if let Some(ref input_types) = opt_input_types {
-            assert_eq!(trait_def.generics.types.len(subst::TypeSpace), input_types.len());
+            assert_eq!(trait_def.generics.types.len(subst::TypeSpace) - 1, input_types.len());
         }
         assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
         assert!(trait_def.generics.regions.is_empty());
@@ -192,10 +192,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
             self.region_var_for_def(span, def)
         }, |def, substs| {
-            if def.space == subst::SelfSpace {
+            if def.index == 0 {
                 self_ty
             } else if let Some(ref input_types) = opt_input_types {
-                input_types[def.index as usize]
+                input_types[def.index as usize - 1]
             } else {
                 self.type_var_for_def(span, def, substs)
             }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 448ea243655..044de179917 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -522,10 +522,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                            trait_ref.substs.types.len(subst::TypeSpace));
                 assert_eq!(m.generics.regions.len(subst::TypeSpace),
                            trait_ref.substs.regions.len(subst::TypeSpace));
-                assert_eq!(m.generics.types.len(subst::SelfSpace),
-                           trait_ref.substs.types.len(subst::SelfSpace));
-                assert_eq!(m.generics.regions.len(subst::SelfSpace),
-                           trait_ref.substs.regions.len(subst::SelfSpace));
             }
 
             // Because this trait derives from a where-clause, it
@@ -755,11 +751,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
             let substs = Substs::for_item(self.tcx, trait_def_id, |def, _| {
                 self.region_var_for_def(self.span, def)
             }, |def, substs| {
-                if def.space == subst::SelfSpace {
-                    assert_eq!(def.index, 0);
+                if def.index == 0 {
                     step.self_ty
                 } else {
-                    assert_eq!(def.space, subst::TypeSpace);
                     self.type_var_for_def(self.span, def, substs)
                 }
             });
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 700fb2ecf42..ae3378f41f9 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4225,7 +4225,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| {
             let i = def.index as usize;
             let segment = match def.space {
-                subst::SelfSpace => None,
                 subst::TypeSpace => type_segment,
                 subst::FnSpace => fn_segment
             };
@@ -4241,9 +4240,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.region_var_for_def(span, def)
             }
         }, |def, substs| {
-            let i = def.index as usize;
+            let mut i = def.index as usize;
             let segment = match def.space {
-                subst::SelfSpace => None,
                 subst::TypeSpace => type_segment,
                 subst::FnSpace => fn_segment
             };
@@ -4252,18 +4250,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 Some(&hir::ParenthesizedParameters(_)) => bug!(),
                 None => &[]
             };
+
+            // Handle Self first, so we can adjust the index to match the AST.
+            if scheme.generics.has_self && def.space == subst::TypeSpace {
+                if i == 0 {
+                    return opt_self_ty.unwrap_or_else(|| {
+                        self.type_var_for_def(span, def, substs)
+                    });
+                }
+                i -= 1;
+            }
+
             let can_omit = def.space != subst::TypeSpace || !require_type_space;
             let default = if can_omit && types.len() == 0 {
                 def.default
             } else {
                 None
             };
-
-            if def.space == subst::SelfSpace && opt_self_ty.is_some() {
-                // Self, which has been provided.
-                assert_eq!(i, 0);
-                opt_self_ty.unwrap()
-            } else if let Some(ast_ty) = types.get(i) {
+            if let Some(ast_ty) = types.get(i) {
                 // A provided type parameter.
                 self.to_ty(ast_ty)
             } else if let Some(default) = default {
@@ -4371,6 +4375,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         // Check provided type parameters.
         let type_defs = generics.types.get_slice(space);
+        let type_defs = if space == subst::TypeSpace {
+            &type_defs[generics.has_self as usize..]
+        } else {
+            type_defs
+        };
         let required_len = type_defs.iter()
                                     .take_while(|d| d.default.is_none())
                                     .count();
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 678c102a4de..f2076895f08 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -14,13 +14,12 @@ use CrateCtxt;
 use hir::def_id::DefId;
 use middle::region::{CodeExtent};
 use rustc::infer::TypeOrigin;
-use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
+use rustc::ty::subst;
 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;
 
@@ -461,7 +460,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
             variances.types
                      .iter_enumerated()
                      .filter(|&(_, _, &variance)| variance != ty::Bivariant)
-                     .map(|(space, index, _)| self.param_ty(ast_generics, space, index))
+                     .map(|(_, index, _)| self.param_ty(ast_generics, index))
                      .map(|p| Parameter::Type(p))
                      .collect();
 
@@ -470,52 +469,34 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
                                          &mut constrained_parameters);
 
         for (space, index, _) in variances.types.iter_enumerated() {
-            let param_ty = self.param_ty(ast_generics, space, index);
+            assert_eq!(space, subst::TypeSpace);
+
+            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() {
+            assert_eq!(space, subst::TypeSpace);
+
             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 {
+            space: subst::TypeSpace,
+            idx: index as u32,
+            name: ast_generics.ty_params[index].name
         }
     }
 
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 485e744bf91..17a84e98e61 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
 
             let source = tcx.lookup_item_type(impl_did).ty;
             let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap();
-            let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
+            let target = *trait_ref.substs.types.get(subst::TypeSpace, 1);
             debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
                    source, target);
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 77723ea9733..8eef384f2cf 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -65,7 +65,7 @@ use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
 use rustc_const_eval::EvalHint::UncheckedExprHint;
 use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
-use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
+use rustc::ty::subst::{Substs, FnSpace, ParamSpace, TypeSpace, VecPerParamSpace};
 use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
 use rustc::ty::{VariantKind};
@@ -85,7 +85,6 @@ use std::rc::Rc;
 
 use syntax::{abi, ast, attr};
 use syntax::parse::token::keywords;
-use syntax::ptr::P;
 use syntax_pos::Span;
 
 use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
@@ -546,7 +545,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
@@ -1333,7 +1332,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
 
     // add in the explicit where-clauses
     let mut trait_predicates =
-        ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
+        ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates, true);
 
     let assoc_predicates = predicates_for_associated_types(ccx,
                                                            generics,
@@ -1430,7 +1429,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         let parent = ccx.tcx.map.get_parent(param_id);
 
                         let def = ty::TypeParameterDef {
-                            space: SelfSpace,
+                            space: TypeSpace,
                             index: 0,
                             name: keywords::SelfType.name(),
                             def_id: tcx.map.local_def_id(param_id),
@@ -1477,27 +1476,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         }).collect();
 
         // Now create the real type parameters.
-        let types = ast_generics.ty_params.iter().enumerate().map(|(i, _)| {
-            get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32, allow_defaults)
+        let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
+            let i = opt_self.is_some() as u32 + i as u32;
+            get_or_create_type_parameter_def(ccx, ast_generics, space, i, p, allow_defaults)
         }).collect();
 
         let has_self = base_generics.has_self || opt_self.is_some();
         let (regions, types) = match space {
-            SelfSpace => bug!(),
             TypeSpace => {
                 assert_eq!(base_generics.regions.as_full_slice().len(), 0);
                 assert_eq!(base_generics.types.as_full_slice().len(), 0);
-                (VecPerParamSpace::new(vec![], regions, vec![]),
-                 VecPerParamSpace::new(opt_self.into_iter().collect(), types, vec![]))
+                (VecPerParamSpace::new(regions, vec![]),
+                 VecPerParamSpace::new(opt_self.into_iter().chain(types).collect(), vec![]))
             }
             FnSpace => {
                 assert_eq!(base_generics.regions.len(FnSpace), 0);
                 assert_eq!(base_generics.types.len(FnSpace), 0);
-                (VecPerParamSpace::new(base_generics.regions.get_slice(SelfSpace).to_vec(),
-                                       base_generics.regions.get_slice(TypeSpace).to_vec(),
+                (VecPerParamSpace::new(base_generics.regions.get_slice(TypeSpace).to_vec(),
                                        regions),
-                 VecPerParamSpace::new(base_generics.types.get_slice(SelfSpace).to_vec(),
-                                       base_generics.types.get_slice(TypeSpace).to_vec(),
+                 VecPerParamSpace::new(base_generics.types.get_slice(TypeSpace).to_vec(),
                                        types))
             }
         };
@@ -1674,7 +1671,7 @@ 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())
+    ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty(), false)
 }
 
 fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
@@ -1682,7 +1679,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                          base_predicates: &ty::GenericPredicates<'tcx>)
                                          -> ty::GenericPredicates<'tcx>
 {
-    ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
+    ty_generic_predicates(ccx, FnSpace, generics, base_predicates, false)
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
@@ -1752,7 +1749,8 @@ 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>)
+                                  base_predicates: &ty::GenericPredicates<'tcx>,
+                                  has_self: bool)
                                   -> ty::GenericPredicates<'tcx>
 {
     let tcx = ccx.tcx;
@@ -1761,7 +1759,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     // 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 index = has_self as u32 + index as u32;
         let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx);
         let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
                                     param_ty,
@@ -1850,50 +1848,22 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     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,
@@ -1922,6 +1892,10 @@ 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: {:?}, {:?}",
@@ -2153,7 +2127,7 @@ pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
 
 /// 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)
 {
@@ -2173,12 +2147,11 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                        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.as_full_slice().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());
         }
     }
 }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 8c9b4beb79d..2b88689ff12 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -361,9 +361,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
                 // 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(
@@ -394,14 +392,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             }
 
             ty::TyTrait(ref data) => {
-                let poly_trait_ref =
-                    data.principal.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.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);
 
                 for projection in &data.projection_bounds {
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
index 22edf219dff..9048d892b09 100644
--- a/src/librustc_typeck/variance/solve.rs
+++ b/src/librustc_typeck/variance/solve.rs
@@ -110,8 +110,8 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
         while index < num_inferred {
             let item_id = inferred_infos[index].item_id;
 
-            let (mut rs, mut rt, mut rf) = (vec![], vec![], vec![]);
-            let (mut ts, mut tt, mut tf) = (vec![], vec![], vec![]);
+            let (mut rt, mut rf) = (vec![], vec![]);
+            let (mut tt, mut tf) = (vec![], vec![]);
 
             while index < num_inferred && inferred_infos[index].item_id == item_id {
                 let info = &inferred_infos[index];
@@ -121,7 +121,6 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
                 match info.kind {
                     TypeParam => {
                         let types = match info.space {
-                            subst::SelfSpace => &mut ts,
                             subst::TypeSpace => &mut tt,
                             subst::FnSpace => &mut tf
                         };
@@ -130,7 +129,6 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
                     }
                     RegionParam => {
                         let regions = match info.space {
-                            subst::SelfSpace => &mut rs,
                             subst::TypeSpace => &mut rt,
                             subst::FnSpace => &mut rf
                         };
@@ -143,8 +141,8 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
             }
 
             let item_variances = ty::ItemVariances {
-                regions: subst::VecPerParamSpace::new(rs, rt, rf),
-                types: subst::VecPerParamSpace::new(ts, tt, tf)
+                regions: subst::VecPerParamSpace::new(rt, rf),
+                types: subst::VecPerParamSpace::new(tt, tf)
             };
 
             debug!("item_id={} item_variances={:?}",
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 72f8d9cb23b..9dc38bb195c 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -21,7 +21,7 @@
 
 use arena::TypedArena;
 use dep_graph::DepTrackingMapConfig;
-use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace};
+use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace};
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::maps::ItemVariances;
 use std::fmt;
@@ -164,16 +164,16 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
 
         let inferreds_on_entry = self.num_inferred();
 
-        if has_self {
-            self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id);
-        }
-
         for (i, p) in generics.lifetimes.iter().enumerate() {
             let id = p.lifetime.id;
             self.add_inferred(item_id, RegionParam, TypeSpace, i, id);
         }
 
+        if has_self {
+            self.add_inferred(item_id, TypeParam, TypeSpace, 0, item_id);
+        }
         for (i, p) in generics.ty_params.iter().enumerate() {
+            let i = has_self as usize + i;
             self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
         }
 
@@ -233,7 +233,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
                              -> ty::Variance
     {
         match space {
-            SelfSpace | FnSpace => {
+            FnSpace => {
                 ty::Bivariant
             }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index f8a3a0af697..6fae7ddc24a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -41,7 +41,7 @@ use rustc::hir::def::Def;
 use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
 use rustc::hir::fold::Folder;
 use rustc::hir::print as pprust;
-use rustc::ty::subst::{self, ParamSpace, Substs, VecPerParamSpace};
+use rustc::ty::subst::{self, Substs, VecPerParamSpace};
 use rustc::ty;
 use rustc::middle::stability;
 
@@ -630,13 +630,14 @@ impl Clean<TyParamBound> for hir::TyParamBound {
     }
 }
 
-fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
+fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool,
                         bindings: Vec<TypeBinding>, substs: &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();
+    let types = substs.types.get_slice(subst::TypeSpace);
+    let types = 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
@@ -675,13 +676,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>,
+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)
         }],
     }
 }
@@ -696,16 +697,16 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
         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 {
@@ -728,14 +729,14 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         };
         inline::record_extern_fqn(cx, self.def_id, TypeTrait);
         let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
-                                 Some(self.def_id), vec![], self.substs);
+                                 Some(self.def_id), true, vec![], self.substs);
 
         debug!("ty::TraitRef\n  substs.types(TypeSpace): {:?}\n",
-               self.substs.types.get_slice(ParamSpace::TypeSpace));
+               &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 {
@@ -982,8 +983,13 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
         // 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.get_slice(space).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 mut srp = rp.clone();
@@ -1820,7 +1826,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 };
                 inline::record_extern_fqn(cx, did, kind);
                 let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
-                                         None, vec![], substs);
+                                         None, false, vec![], substs);
                 ResolvedPath {
                     path: path,
                     typarams: None,
@@ -1847,7 +1853,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 }
 
                 let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
-                                         Some(did), bindings, obj.principal.0.substs);
+                                         Some(did), false, bindings, obj.principal.0.substs);
                 ResolvedPath {
                     path: path,
                     typarams: Some(typarams),
diff --git a/src/test/compile-fail/issue-26548.rs b/src/test/compile-fail/issue-26548.rs
index b6d5e5458ff..2591d7bcbae 100644
--- a/src/test/compile-fail/issue-26548.rs
+++ b/src/test/compile-fail/issue-26548.rs
@@ -8,15 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: overflow representing the type `S`
+// error-pattern: overflow representing the type
 
-#![feature(rustc_attrs)]
 
 trait Mirror { type It: ?Sized; }
 impl<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);
 }
diff --git a/src/test/compile-fail/issue-26812.rs b/src/test/compile-fail/issue-26812.rs
index 060a66846d3..1dd00881078 100644
--- a/src/test/compile-fail/issue-26812.rs
+++ b/src/test/compile-fail/issue-26812.rs
@@ -10,5 +10,7 @@
 
 #![feature(default_type_parameter_fallback)]
 
-fn avg<T=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() {}
diff --git a/src/test/compile-fail/variance-associated-types.rs b/src/test/compile-fail/variance-associated-types.rs
index a3456b0628b..9aa4d29c4ec 100644
--- a/src/test/compile-fail/variance-associated-types.rs
+++ b/src/test/compile-fail/variance-associated-types.rs
@@ -20,12 +20,12 @@ trait Trait<'a> {
 }
 
 #[rustc_variance]
-struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[+];[]], regions=[[];[-];[]])
+struct Foo<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[+];[]], regions=[[-];[]])
     field: (T, &'a ())
 }
 
 #[rustc_variance]
-struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[];[o];[]], regions=[[];[o];[]])
+struct Bar<'a, T : Trait<'a>> { //~ ERROR ItemVariances(types=[[o];[]], regions=[[o];[]])
     field: <T as Trait<'a>>::Type
 }
 
diff --git a/src/test/compile-fail/variance-object-types.rs b/src/test/compile-fail/variance-object-types.rs
index ffd829c38d3..3c8b27f965a 100644
--- a/src/test/compile-fail/variance-object-types.rs
+++ b/src/test/compile-fail/variance-object-types.rs
@@ -18,7 +18,7 @@ use std::cell::Cell;
 // For better or worse, associated types are invariant, and hence we
 // get an invariant result for `'a`.
 #[rustc_variance]
-struct Foo<'a> { //~ ERROR regions=[[];[o];[]]
+struct Foo<'a> { //~ ERROR regions=[[o];[]]
     x: Box<Fn(i32) -> &'a i32 + 'static>
 }
 
diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs
index 6dd791f2558..ae5a8674f44 100644
--- a/src/test/compile-fail/variance-region-bounds.rs
+++ b/src/test/compile-fail/variance-region-bounds.rs
@@ -13,11 +13,11 @@
 #![feature(rustc_attrs)]
 
 #[rustc_variance]
-trait Foo: 'static { //~ ERROR types=[[o];[];[]]
+trait Foo: 'static { //~ ERROR types=[[o];[]]
 }
 
 #[rustc_variance]
-trait Bar<T> { //~ ERROR types=[[o];[o];[]]
+trait Bar<T> { //~ ERROR types=[[o, o];[]]
     fn do_it(&self)
         where T: 'static;
 }
diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs
index 0c712d3fa03..93d3d277314 100644
--- a/src/test/compile-fail/variance-regions-direct.rs
+++ b/src/test/compile-fail/variance-regions-direct.rs
@@ -16,7 +16,7 @@
 // Regions that just appear in normal spots are contravariant:
 
 #[rustc_variance]
-struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]]
+struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[]]
     x: &'a isize,
     y: &'b [isize],
     c: &'c str
@@ -25,7 +25,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[];[-, -, -];[]]
 // Those same annotations in function arguments become covariant:
 
 #[rustc_variance]
-struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]]
+struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[]]
     x: extern "Rust" fn(&'a isize),
     y: extern "Rust" fn(&'b [isize]),
     c: extern "Rust" fn(&'c str),
@@ -34,7 +34,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[];[+, +, +];[]]
 // Mutability induces invariance:
 
 #[rustc_variance]
-struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]]
+struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]]
     x: &'a mut &'b isize,
 }
 
@@ -42,7 +42,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]]
 // contravariant context:
 
 #[rustc_variance]
-struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]]
+struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[]]
     x: extern "Rust" fn(&'a mut &'b isize),
 }
 
@@ -52,14 +52,14 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[];[+, o];[]]
 // argument list occurs in an invariant context.
 
 #[rustc_variance]
-struct Test6<'a, 'b:'a> { //~ ERROR regions=[[];[-, o];[]]
+struct Test6<'a, 'b:'a> { //~ ERROR regions=[[-, o];[]]
     x: &'a mut extern "Rust" fn(&'b isize),
 }
 
 // No uses at all is bivariant:
 
 #[rustc_variance]
-struct Test7<'a> { //~ ERROR regions=[[];[*];[]]
+struct Test7<'a> { //~ ERROR regions=[[*];[]]
     //~^ ERROR parameter `'a` is never used
     x: isize
 }
@@ -67,7 +67,7 @@ struct Test7<'a> { //~ ERROR regions=[[];[*];[]]
 // Try enums too.
 
 #[rustc_variance]
-enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]]
+enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]]
     Test8A(extern "Rust" fn(&'a isize)),
     Test8B(&'b [isize]),
     Test8C(&'b mut &'c str),
diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs
index 9bdb05e188d..eeb981b707e 100644
--- a/src/test/compile-fail/variance-regions-indirect.rs
+++ b/src/test/compile-fail/variance-regions-indirect.rs
@@ -15,7 +15,7 @@
 #![feature(rustc_attrs)]
 
 #[rustc_variance]
-enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]]
+enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[]]
     //~^ ERROR parameter `'d` is never used
     Test8A(extern "Rust" fn(&'a isize)),
     Test8B(&'b [isize]),
@@ -23,25 +23,25 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[];[+, -, o, *];[]]
 }
 
 #[rustc_variance]
-struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[];[*, o, -, +];[]]
+struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[]]
     //~^ ERROR parameter `'w` is never used
     f: Base<'z, 'y, 'x, 'w>
 }
 
 #[rustc_variance] // Combine - and + to yield o
-struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[];[o, o, *];[]]
+struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[]]
     //~^ ERROR parameter `'c` is never used
     f: Base<'a, 'a, 'b, 'c>
 }
 
 #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
-struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[];[o, -, *];[]]
+struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[]]
     //~^ ERROR parameter `'c` is never used
     f: Base<'a, 'b, 'a, 'c>
 }
 
 #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
-struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[];[+, -, o];[]]
+struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[]]
     f: Base<'a, 'b, 'c, 'a>
 }
 
diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs
index 528be50c0b8..860dd6deefd 100644
--- a/src/test/compile-fail/variance-trait-bounds.rs
+++ b/src/test/compile-fail/variance-trait-bounds.rs
@@ -15,48 +15,48 @@
 // influence variance.
 
 #[rustc_variance]
-trait Getter<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
 }
diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs
index b5854020498..b37007a6d34 100644
--- a/src/test/compile-fail/variance-trait-object-bound.rs
+++ b/src/test/compile-fail/variance-trait-object-bound.rs
@@ -21,7 +21,7 @@ use std::mem;
 trait T { fn foo(&self); }
 
 #[rustc_variance]
-struct TOption<'a> { //~ ERROR regions=[[];[-];[]]
+struct TOption<'a> { //~ ERROR regions=[[-];[]]
     v: Option<Box<T + 'a>>,
 }
 
diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs
index d110c402d3b..8eb96814fa8 100644
--- a/src/test/compile-fail/variance-types-bounds.rs
+++ b/src/test/compile-fail/variance-types-bounds.rs
@@ -14,46 +14,46 @@
 #![feature(rustc_attrs)]
 
 #[rustc_variance]
-struct TestImm<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
@@ -63,12 +63,12 @@ trait GetterInTypeBound<A> { //~ ERROR types=[[o];[o];[]]
 }
 
 #[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>,
 }
diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs
index 8c1a544334c..791b56caea0 100644
--- a/src/test/compile-fail/variance-types.rs
+++ b/src/test/compile-fail/variance-types.rs
@@ -17,32 +17,32 @@ use std::cell::Cell;
 // not considered bivariant.
 
 #[rustc_variance]
-struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[];[o, o];[]], regions=[[];[-];[]]
+struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[]], regions=[[-];[]]
     t: &'a mut (A,B)
 }
 
 #[rustc_variance]
-struct InvariantCell<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>)