about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-01-25 22:01:11 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-02-25 17:07:59 +0200
commite8d01ea4c76f6f3cb4f71dbff261355f825d12bb (patch)
treebd71bb08ce70f9e7e9eebcddd20d084b12dbf96c /src
parent1572bf104dbf65d58bd6b889fa46229c9b92d6f9 (diff)
downloadrust-e8d01ea4c76f6f3cb4f71dbff261355f825d12bb.tar.gz
rust-e8d01ea4c76f6f3cb4f71dbff261355f825d12bb.zip
rustc: store type parameter defaults outside of ty::Generics.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/lowering.rs2
-rw-r--r--src/librustc/infer/mod.rs15
-rw-r--r--src/librustc/middle/cstore.rs15
-rw-r--r--src/librustc/middle/resolve_lifetime.rs4
-rw-r--r--src/librustc/ty/context.rs16
-rw-r--r--src/librustc/ty/error.rs8
-rw-r--r--src/librustc/ty/maps.rs2
-rw-r--r--src/librustc/ty/mod.rs31
-rw-r--r--src/librustc/ty/structural_impls.rs36
-rw-r--r--src/librustc/ty/subst.rs14
-rw-r--r--src/librustc/util/ppaux.rs9
-rw-r--r--src/librustc_metadata/cstore_impl.rs18
-rw-r--r--src/librustc_metadata/decoder.rs25
-rw-r--r--src/librustc_metadata/encoder.rs61
-rw-r--r--src/librustc_metadata/schema.rs17
-rw-r--r--src/librustc_privacy/lib.rs12
-rw-r--r--src/librustc_resolve/diagnostics.rs27
-rw-r--r--src/librustc_resolve/lib.rs78
-rw-r--r--src/librustc_trans/debuginfo/mod.rs6
-rw-r--r--src/librustc_trans/debuginfo/utils.rs8
-rw-r--r--src/librustc_typeck/astconv.rs58
-rw-r--r--src/librustc_typeck/check/compare_method.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs18
-rw-r--r--src/librustc_typeck/collect.rs157
-rw-r--r--src/librustc_typeck/diagnostics.rs27
-rw-r--r--src/librustc_typeck/lib.rs25
-rw-r--r--src/librustc_typeck/variance/constraints.rs14
-rw-r--r--src/librustdoc/clean/mod.rs10
-rw-r--r--src/libsyntax/visit.rs49
-rw-r--r--src/test/compile-fail/cycle-trait-default-type-trait.rs1
-rw-r--r--src/test/compile-fail/generic-non-trailing-defaults.rs4
-rw-r--r--src/test/compile-fail/generic-type-params-forward-mention.rs2
-rw-r--r--src/test/compile-fail/issue-18183.rs4
-rw-r--r--src/test/compile-fail/resolve-self-in-impl.rs2
34 files changed, 394 insertions, 385 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 8572119e989..82e644d710d 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -525,7 +525,7 @@ impl<'a> LoweringContext<'a> {
                         return n;
                     }
                     assert!(!def_id.is_local());
-                    let (n, _) = self.sess.cstore.item_generics_own_param_counts(def_id);
+                    let n = self.sess.cstore.item_generics(def_id).regions.len();
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index c3a6a62764d..64256247bb5 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1197,16 +1197,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// as the substitutions for the default, `(T, U)`.
     pub fn type_var_for_def(&self,
                             span: Span,
-                            def: &ty::TypeParameterDef<'tcx>,
+                            def: &ty::TypeParameterDef,
                             substs: &[Kind<'tcx>])
                             -> Ty<'tcx> {
-        let default = def.default.map(|default| {
-            type_variable::Default {
+        let default = if def.has_default {
+            let default = self.tcx.item_type(def.def_id);
+            Some(type_variable::Default {
                 ty: default.subst_spanned(self.tcx, substs, Some(span)),
                 origin_span: span,
-                def_id: def.default_def_id
-            }
-        });
+                def_id: def.def_id
+            })
+        } else {
+            None
+        };
 
 
         let ty_var_id = self.type_variables
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 2d80fc32c46..671da0d1197 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -28,7 +28,6 @@ use hir::map as hir_map;
 use hir::map::definitions::{Definitions, DefKey, DisambiguatedDefPathData};
 use hir::svh::Svh;
 use middle::lang_items;
-use middle::resolve_lifetime::ObjectLifetimeDefault;
 use ty::{self, Ty, TyCtxt};
 use mir::Mir;
 use session::Session;
@@ -182,11 +181,7 @@ pub trait CrateStore<'tcx> {
                            -> ty::GenericPredicates<'tcx>;
     fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                  -> ty::GenericPredicates<'tcx>;
-    fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                         -> ty::Generics<'tcx>;
-    fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize);
-    fn item_generics_object_lifetime_defaults(&self, def: DefId)
-                                              -> Vec<ObjectLifetimeDefault>;
+    fn item_generics(&self, def: DefId) -> ty::Generics;
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
     fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef;
     fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef;
@@ -335,13 +330,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
                            -> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
     fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                  -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
-    fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                         -> ty::Generics<'tcx> { bug!("item_generics") }
-    fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize)
-        { bug!("item_generics_own_param_counts") }
-    fn item_generics_object_lifetime_defaults(&self, def: DefId)
-                                              -> Vec<ObjectLifetimeDefault>
-        { bug!("item_generics_object_lifetime_defaults") }
+    fn item_generics(&self, def: DefId) -> ty::Generics { 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
         { bug!("trait_def") }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 9bad98dda83..95cbd738651 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -995,7 +995,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             } else {
                 let cstore = &self.sess.cstore;
                 self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
-                    cstore.item_generics_object_lifetime_defaults(def_id)
+                    cstore.item_generics(def_id).types.into_iter().map(|def| {
+                        def.object_lifetime_default
+                    }).collect()
                 })
             };
             unsubst.iter().map(|set| {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 19bb8a63aa2..2f062e2e5b1 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -64,7 +64,7 @@ pub struct GlobalArenas<'tcx> {
     layout: TypedArena<Layout>,
 
     // references
-    generics: TypedArena<ty::Generics<'tcx>>,
+    generics: TypedArena<ty::Generics>,
     trait_def: TypedArena<ty::TraitDef>,
     adt_def: TypedArena<ty::AdtDef>,
     mir: TypedArena<RefCell<Mir<'tcx>>>,
@@ -467,9 +467,6 @@ pub struct GlobalCtxt<'tcx> {
     // Cache for the type-contents routine. FIXME -- track deps?
     pub tc_cache: RefCell<FxHashMap<Ty<'tcx>, ty::contents::TypeContents>>,
 
-    // FIXME no dep tracking, but we should be able to remove this
-    pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
-
     // FIXME dep tracking -- should be harmless enough
     pub normalized_cache: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
 
@@ -646,15 +643,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn type_parameter_def(self,
-                              node_id: NodeId)
-                              -> ty::TypeParameterDef<'tcx>
-    {
-        self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
-    }
-
-    pub fn alloc_generics(self, generics: ty::Generics<'gcx>)
-                          -> &'gcx ty::Generics<'gcx> {
+    pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
         self.global_arenas.generics.alloc(generics)
     }
 
@@ -785,7 +774,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             tc_cache: RefCell::new(FxHashMap()),
             associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
-            ty_param_defs: RefCell::new(NodeMap()),
             normalized_cache: RefCell::new(FxHashMap()),
             inhabitedness_cache: RefCell::new(FxHashMap()),
             lang_items: lang_items,
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 3ab3fc899e7..44a3aabc056 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -10,7 +10,7 @@
 
 use hir::def_id::DefId;
 use infer::type_variable;
-use ty::{self, BoundRegion, Region, Ty, TyCtxt};
+use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
 
 use std::fmt;
 use syntax::abi;
@@ -287,8 +287,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                         db.span_note(span, "a default was defined here...");
                     }
                     None => {
+                        let item_def_id = self.parent(expected.def_id).unwrap();
                         db.note(&format!("a default is defined on `{}`",
-                                         self.item_path_str(expected.def_id)));
+                                         self.item_path_str(item_def_id)));
                     }
                 }
 
@@ -301,8 +302,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                         db.span_note(span, "a second default was defined here...");
                     }
                     None => {
+                        let item_def_id = self.parent(found.def_id).unwrap();
                         db.note(&format!("a second default is defined on `{}`",
-                                         self.item_path_str(found.def_id)));
+                                         self.item_path_str(item_def_id)));
                     }
                 }
 
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index d7341d148b7..d2c237d5db6 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -35,7 +35,7 @@ macro_rules! dep_map_ty {
 
 dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem }
 dep_map_ty! { Types: ItemSignature(DefId) -> Ty<'tcx> }
-dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> }
+dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics }
 dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
 dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
 dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc<Vec<DefId>> }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 7937d2ccfe4..1275530b1bd 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -19,9 +19,10 @@ use dep_graph::{self, DepNode};
 use hir::{map as hir_map, FreevarMap, TraitMap};
 use middle;
 use hir::def::{Def, CtorKind, ExportMap};
-use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
+use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
 use traits;
 use ty;
@@ -33,6 +34,7 @@ use util::nodemap::{NodeSet, NodeMap, FxHashMap};
 use serialize::{self, Encodable, Encoder};
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell, Ref};
+use std::collections::BTreeMap;
 use std::hash::{Hash, Hasher};
 use std::ops::Deref;
 use std::rc::Rc;
@@ -585,13 +587,13 @@ pub enum IntVarValue {
     UintType(ast::UintTy),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct TypeParameterDef<'tcx> {
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+pub struct TypeParameterDef {
     pub name: Name,
     pub def_id: DefId,
     pub index: u32,
-    pub default_def_id: DefId, // for use in error reporing about defaults
-    pub default: Option<Ty<'tcx>>,
+    pub has_default: bool,
+    pub object_lifetime_default: ObjectLifetimeDefault,
 
     /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
     /// on generic parameter `T`, asserts data behind the parameter
@@ -628,16 +630,21 @@ impl RegionParameterDef {
 /// Information about the formal type/lifetime parameters associated
 /// with an item or method. Analogous to hir::Generics.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct Generics<'tcx> {
+pub struct Generics {
     pub parent: Option<DefId>,
     pub parent_regions: u32,
     pub parent_types: u32,
     pub regions: Vec<RegionParameterDef>,
-    pub types: Vec<TypeParameterDef<'tcx>>,
+    pub types: Vec<TypeParameterDef>,
+
+    /// Reverse map to each `TypeParameterDef`'s `index` field, from
+    /// `def_id.index` (`def_id.krate` is the same as the item's).
+    pub type_param_to_index: BTreeMap<DefIndex, u32>,
+
     pub has_self: bool,
 }
 
-impl<'tcx> Generics<'tcx> {
+impl Generics {
     pub fn parent_count(&self) -> usize {
         self.parent_regions as usize + self.parent_types as usize
     }
@@ -651,10 +658,12 @@ impl<'tcx> Generics<'tcx> {
     }
 
     pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
+        assert_eq!(self.parent_count(), 0);
         &self.regions[param.index as usize - self.has_self as usize]
     }
 
-    pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef<'tcx> {
+    pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
+        assert_eq!(self.parent_count(), 0);
         &self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
     }
 }
@@ -2319,10 +2328,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Given the did of an item, returns its generics.
-    pub fn item_generics(self, did: DefId) -> &'gcx Generics<'gcx> {
+    pub fn item_generics(self, did: DefId) -> &'gcx Generics {
         lookup_locally_or_in_crate_store(
             "generics", did, &self.generics,
-            || self.alloc_generics(self.sess.cstore.item_generics(self.global_tcx(), did)))
+            || self.alloc_generics(self.sess.cstore.item_generics(did)))
     }
 
     /// Given the did of an item, returns its full set of predicates.
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index aa74e7cc0d0..a1bf58a12eb 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -353,7 +353,7 @@ macro_rules! CopyImpls {
     }
 }
 
-CopyImpls! { (), hir::Unsafety, abi::Abi, ty::RegionParameterDef }
+CopyImpls! { (), hir::Unsafety, abi::Abi }
 
 impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> (T, U) {
@@ -716,40 +716,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> {
     }
 }
 
-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,
-            index: self.index,
-            default: self.default.fold_with(folder),
-            default_def_id: self.default_def_id,
-            pure_wrt_drop: self.pure_wrt_drop,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.default.visit_with(visitor)
-    }
-}
-
-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 {
-            parent: self.parent,
-            parent_regions: self.parent_regions,
-            parent_types: self.parent_types,
-            regions: self.regions.fold_with(folder),
-            types: self.types.fold_with(folder),
-            has_self: self.has_self,
-        }
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.regions.visit_with(visitor) || self.types.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 {
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index c0a529b936b..0a2cc1c30f4 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -184,7 +184,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                             mut mk_type: FT)
                             -> &'tcx Substs<'tcx>
     where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
-          FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
+          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
         let defs = tcx.item_generics(def_id);
         let mut substs = Vec::with_capacity(defs.count());
         Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
@@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
                              mut mk_type: FT)
                              -> &'tcx Substs<'tcx>
     where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
-          FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx>
+          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx>
     {
         let defs = tcx.item_generics(def_id);
         let mut result = Vec::with_capacity(defs.count());
@@ -209,11 +209,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
 
     fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
                          tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                         defs: &ty::Generics<'tcx>,
+                         defs: &ty::Generics,
                          mk_region: &mut FR,
                          mk_type: &mut FT)
     where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
-          FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
+          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
 
         if let Some(def_id) = defs.parent {
             let parent_defs = tcx.item_generics(def_id);
@@ -223,11 +223,11 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
     }
 
     fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
-                           defs: &ty::Generics<'tcx>,
+                           defs: &ty::Generics,
                            mk_region: &mut FR,
                            mk_type: &mut FT)
     where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region,
-          FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> {
+          FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
         // Handle Self first, before all regions.
         let mut types = defs.types.iter();
         if defs.parent.is_none() && defs.has_self {
@@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
         tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
     }
 
-    pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>)
+    pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics)
                        -> &'tcx Substs<'tcx> {
         tcx.mk_substs(self.iter().take(generics.count()).cloned())
     }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index a45c43235eb..2a5cd7b37ca 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -137,11 +137,14 @@ pub fn parameterized(f: &mut fmt::Formatter,
         }
 
         if !verbose {
-            if generics.types.last().map_or(false, |def| def.default.is_some()) {
+            if generics.types.last().map_or(false, |def| def.has_default) {
                 if let Some(substs) = tcx.lift(&substs) {
                     let tps = substs.types().rev().skip(child_types);
                     for (def, actual) in generics.types.iter().rev().zip(tps) {
-                        if def.default.subst(tcx, substs) != Some(actual) {
+                        if !def.has_default {
+                            break;
+                        }
+                        if tcx.item_type(def.def_id).subst(tcx, substs) != actual {
                             break;
                         }
                         num_supplied_defaults += 1;
@@ -326,7 +329,7 @@ impl<'tcx> fmt::Display for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
+impl fmt::Debug for ty::TypeParameterDef {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "TypeParameterDef({}, {:?}, {})",
                self.name,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 7b0177bfd23..bd184c5c5e6 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -17,7 +17,6 @@ use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind, ExternC
 use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
 use rustc::hir::def::{self, Def};
 use rustc::middle::lang_items;
-use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -104,22 +103,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         self.get_crate_data(def.krate).get_super_predicates(def.index, tcx)
     }
 
-    fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                         -> ty::Generics<'tcx>
-    {
-        self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).get_generics(def.index, tcx)
-    }
-
-    fn item_generics_own_param_counts(&self, def: DefId) -> (usize, usize) {
-        self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).generics_own_param_counts(def.index)
-    }
-
-    fn item_generics_object_lifetime_defaults(&self, def: DefId)
-                                              -> Vec<ObjectLifetimeDefault> {
+    fn item_generics(&self, def: DefId) -> ty::Generics {
         self.dep_graph.read(DepNode::MetaData(def));
-        self.get_crate_data(def.krate).generics_object_lifetime_defaults(def.index)
+        self.get_crate_data(def.krate).get_generics(def.index)
     }
 
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 53883e50a5b..22fa9411cc1 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -20,7 +20,6 @@ use rustc::middle::cstore::LinkagePreference;
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::middle::lang_items;
-use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
@@ -601,30 +600,8 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_generics(&self,
-                        item_id: DefIndex,
-                        tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                        -> ty::Generics<'tcx> {
-        let g = self.entry(item_id).generics.unwrap().decode(self);
-        ty::Generics {
-            parent: g.parent,
-            parent_regions: g.parent_regions,
-            parent_types: g.parent_types,
-            regions: g.regions.decode((self, tcx)).collect(),
-            types: g.types.decode((self, tcx)).collect(),
-            has_self: g.has_self,
-        }
-    }
-
-    pub fn generics_own_param_counts(&self, item_id: DefIndex) -> (usize, usize) {
-        let g = self.entry(item_id).generics.unwrap().decode(self);
-        (g.regions.len, g.types.len)
-    }
-
-    pub fn generics_object_lifetime_defaults(&self, item_id: DefIndex)
-                                             -> Vec<ObjectLifetimeDefault> {
+    pub fn get_generics(&self, item_id: DefIndex) -> ty::Generics {
         self.entry(item_id).generics.unwrap().decode(self)
-                           .object_lifetime_defaults.decode(self).collect()
     }
 
     pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 0f9491aaf15..a643ed59af1 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -423,26 +423,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         }
     }
 
-    fn encode_generics(&mut self, def_id: DefId) -> Lazy<Generics<'tcx>> {
+    fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
         let tcx = self.tcx;
-        let g = tcx.item_generics(def_id);
-        let regions = self.lazy_seq_ref(&g.regions);
-        let types = self.lazy_seq_ref(&g.types);
-        let mut object_lifetime_defaults = LazySeq::empty();
-        if let Some(id) = tcx.hir.as_local_node_id(def_id) {
-            if let Some(o) = tcx.named_region_map.object_lifetime_defaults.get(&id) {
-                object_lifetime_defaults = self.lazy_seq_ref(o);
-            }
-        }
-        self.lazy(&Generics {
-            parent: g.parent,
-            parent_regions: g.parent_regions,
-            parent_types: g.parent_types,
-            regions: regions,
-            types: types,
-            has_self: g.has_self,
-            object_lifetime_defaults: object_lifetime_defaults,
-        })
+        self.lazy(tcx.item_generics(def_id))
     }
 
     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
@@ -1008,6 +991,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
                           EncodeContext::encode_info_for_foreign_item,
                           (def_id, ni));
     }
+    fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
+        intravisit::walk_generics(self, generics);
+        self.index.encode_info_for_generics(generics);
+    }
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
         intravisit::walk_ty(self, ty);
         self.index.encode_info_for_ty(ty);
@@ -1019,6 +1006,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
+    fn encode_info_for_generics(&mut self, generics: &hir::Generics) {
+        for ty_param in &generics.ty_params {
+            let def_id = self.tcx.hir.local_def_id(ty_param.id);
+            let has_default = Untracked(ty_param.default.is_some());
+            self.record(def_id, EncodeContext::encode_info_for_ty_param, (def_id, has_default));
+        }
+    }
+
     fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         if let hir::TyImplTrait(_) = ty.node {
             let def_id = self.tcx.hir.local_def_id(ty.id);
@@ -1038,6 +1033,34 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+    fn encode_info_for_ty_param(&mut self,
+                                (def_id, Untracked(has_default)): (DefId, Untracked<bool>))
+                                -> Entry<'tcx> {
+        let tcx = self.tcx;
+        Entry {
+            kind: EntryKind::Type,
+            visibility: self.lazy(&ty::Visibility::Public),
+            span: self.lazy(&tcx.def_span(def_id)),
+            attributes: LazySeq::empty(),
+            children: LazySeq::empty(),
+            stability: None,
+            deprecation: None,
+
+            ty: if has_default {
+                Some(self.encode_item_type(def_id))
+            } else {
+                None
+            },
+            inherent_impls: LazySeq::empty(),
+            variances: LazySeq::empty(),
+            generics: None,
+            predicates: None,
+
+            ast: None,
+            mir: None,
+        }
+    }
+
     fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
         let tcx = self.tcx;
         Entry {
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 777af02772e..ee30063fcbd 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -16,7 +16,6 @@ use rustc::hir::def::{self, CtorKind};
 use rustc::hir::def_id::{DefIndex, DefId};
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
 use rustc::middle::lang_items;
-use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
 use rustc::mir;
 use rustc::ty::{self, Ty, ReprOptions};
 use rustc_back::PanicStrategy;
@@ -212,7 +211,7 @@ pub struct Entry<'tcx> {
     pub ty: Option<Lazy<Ty<'tcx>>>,
     pub inherent_impls: LazySeq<DefIndex>,
     pub variances: LazySeq<ty::Variance>,
-    pub generics: Option<Lazy<Generics<'tcx>>>,
+    pub generics: Option<Lazy<ty::Generics>>,
     pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
 
     pub ast: Option<Lazy<astencode::Ast<'tcx>>>,
@@ -246,20 +245,6 @@ pub enum EntryKind<'tcx> {
     AssociatedConst(AssociatedContainer),
 }
 
-/// A copy of `ty::Generics` which allows lazy decoding of
-/// `regions` and `types` (e.g. knowing the number of type
-/// and lifetime parameters before `TyCtxt` is created).
-#[derive(RustcEncodable, RustcDecodable)]
-pub struct Generics<'tcx> {
-    pub parent: Option<DefId>,
-    pub parent_regions: u32,
-    pub parent_types: u32,
-    pub regions: LazySeq<ty::RegionParameterDef>,
-    pub types: LazySeq<ty::TypeParameterDef<'tcx>>,
-    pub has_self: bool,
-    pub object_lifetime_defaults: LazySeq<ObjectLifetimeDefault>,
-}
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
     pub reexports: LazySeq<def::Export>,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 9dc94745cff..72347f1616e 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -334,7 +334,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
 
 impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
     fn generics(&mut self) -> &mut Self {
-        self.ev.tcx.item_generics(self.item_def_id).visit_with(self);
+        for def in &self.ev.tcx.item_generics(self.item_def_id).types {
+            if def.has_default {
+                self.ev.tcx.item_type(def.def_id).visit_with(self);
+            }
+        }
         self
     }
 
@@ -892,7 +896,11 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     fn generics(&mut self) -> &mut Self {
-        self.tcx.item_generics(self.item_def_id).visit_with(self);
+        for def in &self.tcx.item_generics(self.item_def_id).types {
+            if def.has_default {
+                self.tcx.item_type(def.def_id).visit_with(self);
+            }
+        }
         self
     }
 
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 2fada8a9ec2..8f6b1b8971e 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -15,6 +15,33 @@
 // use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
 register_long_diagnostics! {
 
+E0128: r##"
+Type parameter defaults can only use parameters that occur before them.
+Erroneous code example:
+
+```compile_fail,E0128
+struct Foo<T=U, U=()> {
+    field1: T,
+    filed2: U,
+}
+// error: type parameters with a default cannot use forward declared
+// identifiers
+```
+
+Since type parameters are evaluated in-order, you may be able to fix this issue
+by doing:
+
+```
+struct Foo<U=(), T=U> {
+    field1: T,
+    filed2: U,
+}
+```
+
+Please also verify that this wasn't because of a name-clash and rename the type
+parameter if so.
+"##,
+
 E0154: r##"
 ## Note: this error code is no longer emitted by the compiler.
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index eefe83d7da6..0565db28ec5 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -136,6 +136,8 @@ enum ResolutionError<'a> {
     AttemptToUseNonConstantValueInConstant,
     /// error E0530: X bindings cannot shadow Ys
     BindingShadowsSomethingUnacceptable(&'a str, Name, &'a NameBinding<'a>),
+    /// error E0128: type parameters with a default cannot use forward declared identifiers
+    ForwardDeclaredTyParam,
 }
 
 fn resolve_error<'sess, 'a>(resolver: &'sess Resolver,
@@ -322,6 +324,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             err.span_label(binding.span, msg);
             err
         }
+        ResolutionError::ForwardDeclaredTyParam => {
+            let mut err = struct_span_err!(resolver.session, span, E0128,
+                                           "type parameters with a default cannot use \
+                                            forward declared identifiers");
+            err.span_label(span, &format!("defaulted type parameters \
+                                           cannot be forward declared"));
+            err
+        }
     }
 }
 
@@ -674,6 +684,32 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         self.label_ribs.pop();
         self.ribs[ValueNS].pop();
     }
+    fn visit_generics(&mut self, generics: &'tcx Generics) {
+        // For type parameter defaults, we have to ban access
+        // to following type parameters, as the Substs can only
+        // provide previous type parameters as they're built.
+        let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind);
+        default_ban_rib.bindings.extend(generics.ty_params.iter()
+            .skip_while(|p| p.default.is_none())
+            .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err)));
+
+        for param in &generics.ty_params {
+            for bound in &param.bounds {
+                self.visit_ty_param_bound(bound);
+            }
+
+            if let Some(ref ty) = param.default {
+                self.ribs[TypeNS].push(default_ban_rib);
+                self.visit_ty(ty);
+                default_ban_rib = self.ribs[TypeNS].pop().unwrap();
+            }
+
+            // Allow all following defaults to refer to this type parameter.
+            default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name));
+        }
+        for lt in &generics.lifetimes { self.visit_lifetime_def(lt); }
+        for p in &generics.where_clause.predicates { self.visit_where_predicate(p); }
+    }
 }
 
 pub type ErrorMessage = Option<(Span, String)>;
@@ -718,6 +754,11 @@ enum RibKind<'a> {
 
     // We passed through a `macro_rules!` statement with the given expansion
     MacroDefinition(Mark),
+
+    // All bindings in this rib are type parameters that can't be used
+    // from the default of a type parameter because they're not declared
+    // before said type parameter. Also see the `visit_generics` override.
+    ForwardTyParamBanRibKind,
 }
 
 /// One local scope.
@@ -736,13 +777,6 @@ impl<'a> Rib<'a> {
     }
 }
 
-/// A definition along with the index of the rib it was found on
-#[derive(Copy, Clone, Debug)]
-struct LocalDef {
-    ribs: Option<(Namespace, usize)>,
-    def: Def,
-}
-
 enum LexicalScopeBinding<'a> {
     Item(&'a NameBinding<'a>),
     Def(Def),
@@ -1428,7 +1462,7 @@ impl<'a> Resolver<'a> {
             if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Def(
-                    self.adjust_local_def(LocalDef { ribs: Some((ns, i)), def: def }, record_used)
+                    self.adjust_local_def(ns, i, def, record_used)
                 ));
             }
 
@@ -2527,12 +2561,23 @@ impl<'a> Resolver<'a> {
     }
 
     // Resolve a local definition, potentially adjusting for closures.
-    fn adjust_local_def(&mut self, local_def: LocalDef, record_used: Option<Span>) -> Def {
-        let ribs = match local_def.ribs {
-            Some((ns, i)) => &self.ribs[ns][i + 1..],
-            None => &[] as &[_],
-        };
-        let mut def = local_def.def;
+    fn adjust_local_def(&mut self,
+                        ns: Namespace,
+                        rib_index: usize,
+                        mut def: Def,
+                        record_used: Option<Span>) -> Def {
+        let ribs = &self.ribs[ns][rib_index + 1..];
+
+        // An invalid forward use of a type parameter from a previous default.
+        if let ForwardTyParamBanRibKind = self.ribs[ns][rib_index].kind {
+            if let Some(span) = record_used {
+                resolve_error(self, span,
+                        ResolutionError::ForwardDeclaredTyParam);
+            }
+            assert_eq!(def, Def::Err);
+            return Def::Err;
+        }
+
         match def {
             Def::Upvar(..) => {
                 span_bug!(record_used.unwrap_or(DUMMY_SP), "unexpected {:?} in bindings", def)
@@ -2540,7 +2585,8 @@ impl<'a> Resolver<'a> {
             Def::Local(def_id) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) => {
+                        NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) |
+                        ForwardTyParamBanRibKind => {
                             // Nothing to do. Continue.
                         }
                         ClosureRibKind(function_id) => {
@@ -2593,7 +2639,7 @@ impl<'a> Resolver<'a> {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | MethodRibKind(_) | ClosureRibKind(..) |
-                        ModuleRibKind(..) | MacroDefinition(..) => {
+                        ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind => {
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index e9b592ec8fd..4a8b0ff4552 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -332,7 +332,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 
     fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                         generics: &ty::Generics<'tcx>,
+                                         generics: &ty::Generics,
                                          substs: &Substs<'tcx>,
                                          file_metadata: DIFile,
                                          name_to_append_suffix_to: &mut String)
@@ -382,9 +382,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         return create_DIArray(DIB(cx), &template_params[..]);
     }
 
-    fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                          generics: &ty::Generics<'tcx>)
-                                          -> Vec<ast::Name> {
+    fn get_type_parameter_names(cx: &CrateContext, generics: &ty::Generics) -> Vec<ast::Name> {
         let mut names = generics.parent.map_or(vec![], |def_id| {
             get_type_parameter_names(cx, cx.tcx().item_generics(def_id))
         });
diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs
index 15a1c990aad..ceff96a39b2 100644
--- a/src/librustc_trans/debuginfo/utils.rs
+++ b/src/librustc_trans/debuginfo/utils.rs
@@ -14,6 +14,7 @@ use super::{CrateDebugContext};
 use super::namespace::item_namespace;
 
 use rustc::hir::def_id::DefId;
+use rustc::ty::DefIdTree;
 
 use llvm;
 use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
@@ -74,11 +75,8 @@ pub fn DIB(cx: &CrateContext) -> DIBuilderRef {
 
 pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
                                    -> (DIScope, Span) {
-    let containing_scope = item_namespace(cx, DefId {
-        krate: def_id.krate,
-        index: cx.tcx().def_key(def_id).parent
-                 .expect("get_namespace_and_span_for_item: missing parent?")
-    });
+    let containing_scope = item_namespace(cx, cx.tcx().parent(def_id)
+        .expect("get_namespace_and_span_for_item: missing parent?"));
 
     // Try to get some span information, if we have an inlined item.
     let definition_span = cx.tcx().def_span(def_id);
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index ab1897101eb..8f556726f22 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -42,7 +42,7 @@ use std::cell::RefCell;
 use std::iter;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub trait AstConv<'gcx, 'tcx> {
@@ -53,7 +53,7 @@ pub trait AstConv<'gcx, '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>;
+                    -> Result<&'tcx ty::Generics, ErrorReported>;
 
     /// Identify the type for an item, like a type alias, fn, or struct.
     fn get_item_type(&self, span: Span, id: DefId) -> Result<Ty<'tcx>, ErrorReported>;
@@ -89,7 +89,7 @@ pub trait AstConv<'gcx, 'tcx> {
 
     /// Same as ty_infer, but with a known type parameter definition.
     fn ty_infer_for_def(&self,
-                        _def: &ty::TypeParameterDef<'tcx>,
+                        _def: &ty::TypeParameterDef,
                         _substs: &[Kind<'tcx>],
                         span: Span) -> Ty<'tcx> {
         self.ty_infer(span)
@@ -277,9 +277,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         }
 
         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() {
+        let default_needs_object_self = |p: &ty::TypeParameterDef| {
+            if is_object && p.has_default {
+                let default = self.get_item_type(span, p.def_id).ok();
+                if default.has_self_ty() {
                     // There is no suitable inference default for a type parameter
                     // that references self, in an object type.
                     return true;
@@ -327,7 +328,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     self.ty_infer(span)
                 };
                 ty_var
-            } else if let Some(default) = def.default {
+            } else if def.has_default {
                 // No type parameter provided, but a default exists.
 
                 // If we are converting an object type, then the
@@ -346,7 +347,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     tcx.types.err
                 } else {
                     // This is a default type parameter.
-                    default.subst_spanned(tcx, substs, Some(span))
+                    match self.get_item_type(span, def.def_id) {
+                        Ok(ty) => ty.subst_spanned(tcx, substs, Some(span)),
+                        Err(ErrorReported) => tcx.types.err
+                    }
                 }
             } else {
                 // We've already errored above about the mismatch.
@@ -954,19 +958,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                     Err(ErrorReported) => return (tcx.types.err, Def::Err),
                 }
             }
-            (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
-                let trait_node_id = tcx.hir.as_local_node_id(trait_did).unwrap();
-                match self.find_bound_for_assoc_item(trait_node_id,
-                                                     keywords::SelfType.name(),
-                                                     assoc_name,
-                                                     span) {
-                    Ok(bound) => bound,
-                    Err(ErrorReported) => return (tcx.types.err, Def::Err),
-                }
-            }
+            (&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) |
             (&ty::TyParam(_), Def::TyParam(param_did)) => {
                 let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
-                let param_name = tcx.type_parameter_def(param_node_id).name;
+                let param_name = ::ty_param_name(tcx, param_node_id);
                 match self.find_bound_for_assoc_item(param_node_id,
                                                      param_name,
                                                      assoc_name,
@@ -1063,21 +1058,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 tcx.prohibit_type_params(&path.segments);
 
                 let node_id = tcx.hir.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
-                }
+                let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
+                let index = match self.get_generics(span, item_def_id) {
+                    Ok(generics) => {
+                        generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
+                    }
+                    Err(ErrorReported) => return tcx.types.err
+                };
+                tcx.mk_param(index, ::ty_param_name(tcx, node_id))
             }
             Def::SelfTy(_, Some(def_id)) => {
                 // Self in impl (we know the concrete type).
@@ -1510,7 +1498,7 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: 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();
+    let required = ty_param_defs.iter().take_while(|x| !x.has_default).count();
     if supplied < required {
         let expected = if required < accepted {
             "expected at least"
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index d110c16cf33..bdeb7165356 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -386,8 +386,8 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                 span: Span,
                                                 impl_m: &ty::AssociatedItem,
-                                                trait_generics: &ty::Generics<'tcx>,
-                                                impl_generics: &ty::Generics<'tcx>,
+                                                trait_generics: &ty::Generics,
+                                                impl_generics: &ty::Generics,
                                                 trait_to_skol_substs: &Substs<'tcx>,
                                                 impl_to_skol_substs: &Substs<'tcx>)
                                                 -> Result<(), ErrorReported> {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 14dacb0ca97..60805625b7b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1360,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn get_generics(&self, _: Span, id: DefId)
-                    -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
+                    -> Result<&'tcx ty::Generics, ErrorReported>
     {
         Ok(self.tcx().item_generics(id))
     }
@@ -1390,14 +1390,17 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
                                  node_id: ast::NodeId)
                                  -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
     {
-        let def = self.tcx.type_parameter_def(node_id);
+        let tcx = self.tcx;
+        let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
+        let generics = tcx.item_generics(item_def_id);
+        let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
         let r = self.parameter_environment
                                   .caller_bounds
                                   .iter()
                                   .filter_map(|predicate| {
                                       match *predicate {
                                           ty::Predicate::Trait(ref data) => {
-                                              if data.0.self_ty().is_param(def.index) {
+                                              if data.0.self_ty().is_param(index) {
                                                   Some(data.to_poly_trait_ref())
                                               } else {
                                                   None
@@ -1426,7 +1429,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn ty_infer_for_def(&self,
-                        ty_param_def: &ty::TypeParameterDef<'tcx>,
+                        ty_param_def: &ty::TypeParameterDef,
                         substs: &[Kind<'tcx>],
                         span: Span) -> Ty<'tcx> {
         self.type_var_for_def(span, ty_param_def, substs)
@@ -4423,8 +4426,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             if let Some(ast_ty) = types.get(i) {
                 // A provided type parameter.
                 self.to_ty(ast_ty)
-            } else if let (false, Some(default)) = (infer_types, def.default) {
+            } else if !infer_types && def.has_default {
                 // No type parameter provided, but a default exists.
+                let default = self.tcx.item_type(def.def_id);
                 default.subst_spanned(self.tcx, substs, Some(span))
             } else {
                 // No type parameters were provided, we can infer all.
@@ -4537,9 +4541,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 &generics.types
             }
         });
-        let required_len = type_defs.iter()
-                                    .take_while(|d| d.default.is_none())
-                                    .count();
+        let required_len = type_defs.iter().take_while(|d| !d.has_default).count();
         if types.len() > type_defs.len() {
             let span = types[type_defs.len()].span;
             let expected_text = count_type_params(type_defs.len());
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 217405a81ec..d168f5d4241 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -62,6 +62,7 @@ use lint;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
+use middle::resolve_lifetime as rl;
 use rustc_const_eval::EvalHint::UncheckedExprHint;
 use rustc_const_eval::{ConstContext, report_const_eval_err};
 use rustc::ty::subst::Substs;
@@ -76,6 +77,7 @@ use CrateCtxt;
 use rustc_const_math::ConstInt;
 
 use std::cell::RefCell;
+use std::collections::BTreeMap;
 
 use syntax::{abi, ast, attr};
 use syntax::symbol::{Symbol, keywords};
@@ -186,6 +188,16 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
         intravisit::walk_item(self, item);
     }
 
+    fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
+        for param in &generics.ty_params {
+            if param.default.is_some() {
+                let def_id = self.ccx.tcx.hir.local_def_id(param.id);
+                type_of_def_id(self.ccx, def_id);
+            }
+        }
+        intravisit::walk_generics(self, generics);
+    }
+
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         if let hir::ExprClosure(..) = expr.node {
             let def_id = self.ccx.tcx.hir.local_def_id(expr.id);
@@ -277,11 +289,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                              tcx.item_path_str(def_id)));
             }
             AstConvRequest::GetTypeParameterBounds(id) => {
-                let def = tcx.type_parameter_def(id);
                 err.note(
                     &format!("the cycle begins when computing the bounds \
                               for type parameter `{}`...",
-                             def.name));
+                             ::ty_param_name(tcx, id)));
             }
         }
 
@@ -300,11 +311,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                                  tcx.item_path_str(def_id)));
                 }
                 AstConvRequest::GetTypeParameterBounds(id) => {
-                    let def = tcx.type_parameter_def(id);
                     err.note(
                         &format!("...which then requires computing the bounds \
                                   for type parameter `{}`...",
-                                 def.name));
+                                 ::ty_param_name(tcx, id)));
                 }
             }
         }
@@ -324,11 +334,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                              tcx.item_path_str(def_id)));
             }
             AstConvRequest::GetTypeParameterBounds(id) => {
-                let def = tcx.type_parameter_def(id);
                 err.note(
                     &format!("...which then again requires computing the bounds \
                               for type parameter `{}`, completing the cycle.",
-                             def.name));
+                             ::ty_param_name(tcx, id)));
             }
         }
         err.emit();
@@ -385,7 +394,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
     }
 
     fn get_generics(&self, span: Span, id: DefId)
-                    -> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
+                    -> Result<&'tcx ty::Generics, ErrorReported>
     {
         self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || {
             Ok(generics_of_def_id(self.ccx, id))
@@ -531,20 +540,23 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
                                  node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>
     {
-        let def = astconv.tcx().type_parameter_def(node_id);
+        let tcx = astconv.tcx();
+        let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
+        let generics = tcx.item_generics(item_def_id);
+        let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
 
         let mut results = self.parent.map_or(vec![], |def_id| {
-            let parent = astconv.tcx().item_predicates(def_id);
+            let parent = tcx.item_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)
+                    data.skip_binder().self_ty().is_param(index)
                 }
                 ty::Predicate::TypeOutlives(ref data) => {
-                    data.skip_binder().0.is_param(def.index)
+                    data.skip_binder().0.is_param(index)
                 }
                 ty::Predicate::Equate(..) |
                 ty::Predicate::RegionOutlives(..) |
@@ -568,7 +580,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
 impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
     fn get_type_parameter_bounds(&self,
                                  astconv: &AstConv<'tcx, 'tcx>,
-                                 _: Span,
+                                 span: Span,
                                  node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>
     {
@@ -576,8 +588,15 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
         // written inline like `<T:Foo>` or in a where clause like
         // `where T:Foo`.
 
-        let def = astconv.tcx().type_parameter_def(node_id);
-        let ty = astconv.tcx().mk_param_from_def(&def);
+        let tcx = astconv.tcx();
+        let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
+        let index = match astconv.get_generics(span, item_def_id) {
+            Ok(generics) => {
+                generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
+            }
+            Err(ErrorReported) => return vec![]
+        };
+        let ty = tcx.mk_param(index, ::ty_param_name(tcx, node_id));
 
         let from_ty_params =
             self.ty_params
@@ -594,7 +613,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
                     hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
                     _ => None
                 })
-                .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
+                .filter(|bp| is_param(tcx, &bp.bounded_ty, node_id))
                 .flat_map(|bp| bp.bounds.iter())
                 .flat_map(|b| predicates_from_bound(astconv, ty, b));
 
@@ -625,7 +644,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                           struct_generics: &'tcx ty::Generics<'tcx>,
+                           struct_generics: &'tcx ty::Generics,
                            struct_predicates: &ty::GenericPredicates<'tcx>,
                            field: &hir::StructField,
                            ty_f: &'tcx ty::FieldDef)
@@ -938,7 +957,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                         def: &'tcx ty::AdtDef,
                                         ty: Ty<'tcx>,
-                                        generics: &'tcx ty::Generics<'tcx>,
+                                        generics: &'tcx ty::Generics,
                                         predicates: ty::GenericPredicates<'tcx>,
                                         variants: &[hir::Variant]) {
     // fill the field types
@@ -1325,7 +1344,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
 
 fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 def_id: DefId)
-                                -> &'tcx ty::Generics<'tcx> {
+                                -> &'tcx ty::Generics {
     let tcx = ccx.tcx;
     let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
         id
@@ -1402,18 +1421,14 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         // the node id for the Self type parameter.
                         let param_id = item.id;
 
-                        let parent = ccx.tcx.hir.get_parent(param_id);
-
-                        let def = ty::TypeParameterDef {
+                        opt_self = Some(ty::TypeParameterDef {
                             index: 0,
                             name: keywords::SelfType.name(),
                             def_id: tcx.hir.local_def_id(param_id),
-                            default_def_id: tcx.hir.local_def_id(parent),
-                            default: None,
+                            has_default: false,
+                            object_lifetime_default: rl::Set1::Empty,
                             pure_wrt_drop: false,
-                        };
-                        tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
-                        opt_self = Some(def);
+                        });
 
                         allow_defaults = true;
                         generics
@@ -1459,11 +1474,36 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             }
         }).collect::<Vec<_>>();
 
+        let object_lifetime_defaults =
+            tcx.named_region_map.object_lifetime_defaults.get(&node_id);
+
         // Now create the real type parameters.
         let type_start = own_start + regions.len() as u32;
         let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
-            let i = type_start + i as u32;
-            get_or_create_type_parameter_def(ccx, i, p, allow_defaults)
+            if p.name == keywords::SelfType.name() {
+                span_bug!(p.span, "`Self` should not be the name of a regular parameter");
+            }
+
+            if !allow_defaults && p.default.is_some() {
+                if !tcx.sess.features.borrow().default_type_parameter_fallback {
+                    tcx.sess.add_lint(
+                        lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+                        p.id,
+                        p.span,
+                        format!("defaults for type parameters are only allowed in `struct`, \
+                                 `enum`, `type`, or `trait` definitions."));
+                }
+            }
+
+            ty::TypeParameterDef {
+                index: type_start + i as u32,
+                name: p.name,
+                def_id: tcx.hir.local_def_id(p.id),
+                has_default: p.default.is_some(),
+                object_lifetime_default:
+                    object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]),
+                pure_wrt_drop: p.pure_wrt_drop,
+            }
         });
         let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
 
@@ -1476,19 +1516,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     index: type_start + i as u32,
                     name: Symbol::intern("<upvar>"),
                     def_id: def_id,
-                    default_def_id: parent_def_id.unwrap(),
-                    default: None,
+                    has_default: false,
+                    object_lifetime_default: rl::Set1::Empty,
                     pure_wrt_drop: false,
                }));
             });
         }
 
+        let mut type_param_to_index = BTreeMap::new();
+        for param in &types {
+            type_param_to_index.insert(param.def_id.index, param.index);
+        }
+
         tcx.alloc_generics(ty::Generics {
             parent: parent_def_id,
             parent_regions: parent_regions,
             parent_types: parent_types,
             regions: regions,
             types: types,
+            type_param_to_index: type_param_to_index,
             has_self: has_self || parent_has_self
         })
     })
@@ -1576,6 +1622,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     |def, _| ccx.tcx.mk_param_from_def(def)
                 ))
             }
+            NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => {
+                ccx.icx(&()).to_ty(ty)
+            }
             x => {
                 bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
             }
@@ -1808,54 +1857,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     }
 }
 
-fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                                             index: u32,
-                                             param: &hir::TyParam,
-                                             allow_defaults: bool)
-                                             -> ty::TypeParameterDef<'tcx>
-{
-    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| ccx.icx(&()).to_ty(def));
-
-    let parent = tcx.hir.get_parent(param.id);
-
-    if !allow_defaults && default.is_some() {
-        if !tcx.sess.features.borrow().default_type_parameter_fallback {
-            tcx.sess.add_lint(
-                lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
-                param.id,
-                param.span,
-                format!("defaults for type parameters are only allowed in `struct`, \
-                         `enum`, `type`, or `trait` definitions."));
-        }
-    }
-
-    let def = ty::TypeParameterDef {
-        index: index,
-        name: param.name,
-        def_id: ccx.tcx.hir.local_def_id(param.id),
-        default_def_id: ccx.tcx.hir.local_def_id(parent),
-        default: default,
-        pure_wrt_drop: param.pure_wrt_drop,
-    };
-
-    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
-}
-
 pub enum SizedByDefault { Yes, No, }
 
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 5bfc3a934af..1ff6944d98d 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1701,33 +1701,6 @@ struct Foo {
 ```
 "##,
 
-E0128: r##"
-Type parameter defaults can only use parameters that occur before them.
-Erroneous code example:
-
-```compile_fail,E0128
-struct Foo<T=U, U=()> {
-    field1: T,
-    filed2: U,
-}
-// error: type parameters with a default cannot use forward declared
-// identifiers
-```
-
-Since type parameters are evaluated in-order, you may be able to fix this issue
-by doing:
-
-```
-struct Foo<U=(), T=U> {
-    field1: T,
-    filed2: U,
-}
-```
-
-Please also verify that this wasn't because of a name-clash and rename the type
-parameter if so.
-"##,
-
 E0131: r##"
 It is not possible to define `main` with type parameters, or even with function
 parameters. When `main` is present, it must take no arguments and return `()`.
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 0bcf8ab7d6c..03175782c38 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -116,6 +116,7 @@ use util::common::time;
 
 use syntax::ast;
 use syntax::abi::Abi;
+use syntax::symbol::keywords;
 use syntax_pos::Span;
 
 use std::iter;
@@ -193,6 +194,30 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     })
 }
 
+fn ty_param_owner(tcx: TyCtxt, id: ast::NodeId) -> ast::NodeId {
+    match tcx.hir.get(id) {
+        hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => id,
+        hir::map::NodeTyParam(_) => tcx.hir.get_parent_node(id),
+        _ => {
+            bug!("ty_param_owner: {} not a type parameter",
+                 tcx.hir.node_to_string(id))
+        }
+    }
+}
+
+fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name {
+    match tcx.hir.get(id) {
+        hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => {
+            keywords::SelfType.name()
+        }
+        hir::map::NodeTyParam(tp) => tp.name,
+        _ => {
+            bug!("ty_param_name: {} not a type parameter",
+                 tcx.hir.node_to_string(id))
+        }
+    }
+}
+
 fn check_main_fn_ty(ccx: &CrateCtxt,
                     main_id: ast::NodeId,
                     main_span: Span) {
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 860f6d98370..b22db940798 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -279,7 +279,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     }
 
     fn add_constraints_from_trait_ref(&mut self,
-                                      generics: &ty::Generics<'tcx>,
+                                      generics: &ty::Generics,
                                       trait_ref: ty::TraitRef<'tcx>,
                                       variance: VarianceTermPtr<'a>) {
         debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
@@ -305,7 +305,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// in a context with the generics defined in `generics` and
     /// ambient variance `variance`
     fn add_constraints_from_ty(&mut self,
-                               generics: &ty::Generics<'tcx>,
+                               generics: &ty::Generics,
                                ty: Ty<'tcx>,
                                variance: VarianceTermPtr<'a>) {
         debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
@@ -433,9 +433,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// Adds constraints appropriate for a nominal type (enum, struct,
     /// object, etc) appearing in a context with ambient variance `variance`
     fn add_constraints_from_substs(&mut self,
-                                   generics: &ty::Generics<'tcx>,
+                                   generics: &ty::Generics,
                                    def_id: DefId,
-                                   type_param_defs: &[ty::TypeParameterDef<'tcx>],
+                                   type_param_defs: &[ty::TypeParameterDef],
                                    region_param_defs: &[ty::RegionParameterDef],
                                    substs: &Substs<'tcx>,
                                    variance: VarianceTermPtr<'a>) {
@@ -465,7 +465,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// Adds constraints appropriate for a function with signature
     /// `sig` appearing in a context with ambient variance `variance`
     fn add_constraints_from_sig(&mut self,
-                                generics: &ty::Generics<'tcx>,
+                                generics: &ty::Generics,
                                 sig: &ty::PolyFnSig<'tcx>,
                                 variance: VarianceTermPtr<'a>) {
         let contra = self.contravariant(variance);
@@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// Adds constraints appropriate for a region appearing in a
     /// context with ambient variance `variance`
     fn add_constraints_from_region(&mut self,
-                                   generics: &ty::Generics<'tcx>,
+                                   generics: &ty::Generics,
                                    region: &'tcx ty::Region,
                                    variance: VarianceTermPtr<'a>) {
         match *region {
@@ -518,7 +518,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// Adds constraints appropriate for a mutability-type pair
     /// appearing in a context with ambient variance `variance`
     fn add_constraints_from_mt(&mut self,
-                               generics: &ty::Generics<'tcx>,
+                               generics: &ty::Generics,
                                mt: &ty::TypeAndMut<'tcx>,
                                variance: VarianceTermPtr<'a>) {
         match mt.mutbl {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 751ed7d443d..dc09fc2b8d3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -596,14 +596,18 @@ impl Clean<TyParam> for hir::TyParam {
     }
 }
 
-impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
+impl<'tcx> Clean<TyParam> for ty::TypeParameterDef {
     fn clean(&self, cx: &DocContext) -> TyParam {
         cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
         TyParam {
             name: self.name.clean(cx),
             did: self.def_id,
             bounds: vec![], // these are filled in from the where-clauses
-            default: self.default.clean(cx),
+            default: if self.has_default {
+                Some(cx.tcx.item_type(self.def_id).clean(cx))
+            } else {
+                None
+            }
         }
     }
 }
@@ -965,7 +969,7 @@ impl Clean<Generics> for hir::Generics {
     }
 }
 
-impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>,
+impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
                                     &'a ty::GenericPredicates<'tcx>) {
     fn clean(&self, cx: &DocContext) -> Generics {
         use self::WherePredicate as WP;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index bfab7a250c6..013632141de 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -68,6 +68,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_expr_post(&mut self, _ex: &'ast Expr) { }
     fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) }
     fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) }
+    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
+        walk_where_predicate(self, p)
+    }
     fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
         walk_fn(self, fk, fd, s)
     }
@@ -488,28 +491,30 @@ pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics
         walk_list!(visitor, visit_attribute, &*param.attrs);
     }
     walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
-    for predicate in &generics.where_clause.predicates {
-        match *predicate {
-            WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
-                                                               ref bounds,
-                                                               ref bound_lifetimes,
-                                                               ..}) => {
-                visitor.visit_ty(bounded_ty);
-                walk_list!(visitor, visit_ty_param_bound, bounds);
-                walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
-            }
-            WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
-                                                                 ref bounds,
-                                                                 ..}) => {
-                visitor.visit_lifetime(lifetime);
-                walk_list!(visitor, visit_lifetime, bounds);
-            }
-            WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
-                                                         ref rhs_ty,
-                                                         ..}) => {
-                visitor.visit_ty(lhs_ty);
-                visitor.visit_ty(rhs_ty);
-            }
+    walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates);
+}
+
+pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a WherePredicate) {
+    match *predicate {
+        WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
+                                                           ref bounds,
+                                                           ref bound_lifetimes,
+                                                           ..}) => {
+            visitor.visit_ty(bounded_ty);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
+        }
+        WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
+                                                             ref bounds,
+                                                             ..}) => {
+            visitor.visit_lifetime(lifetime);
+            walk_list!(visitor, visit_lifetime, bounds);
+        }
+        WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty,
+                                                     ref rhs_ty,
+                                                     ..}) => {
+            visitor.visit_ty(lhs_ty);
+            visitor.visit_ty(rhs_ty);
         }
     }
 }
diff --git a/src/test/compile-fail/cycle-trait-default-type-trait.rs b/src/test/compile-fail/cycle-trait-default-type-trait.rs
index e6caeb34a8c..6825572b26c 100644
--- a/src/test/compile-fail/cycle-trait-default-type-trait.rs
+++ b/src/test/compile-fail/cycle-trait-default-type-trait.rs
@@ -13,6 +13,7 @@
 
 trait Foo<X = Box<Foo>> {
     //~^ ERROR unsupported cyclic reference
+    //~| ERROR unsupported cyclic reference
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/generic-non-trailing-defaults.rs b/src/test/compile-fail/generic-non-trailing-defaults.rs
index 77e55203263..13b7753082c 100644
--- a/src/test/compile-fail/generic-non-trailing-defaults.rs
+++ b/src/test/compile-fail/generic-non-trailing-defaults.rs
@@ -10,10 +10,10 @@
 
 struct Heap;
 
-struct Vec<A = Heap, T>;
+struct Vec<A = Heap, T>(A, T);
 //~^ ERROR type parameters with a default must be trailing
 
-struct Foo<A, B = Vec<C>, C>;
+struct Foo<A, B = Vec<C>, C>(A, B, C);
 //~^ ERROR type parameters with a default must be trailing
 //~| ERROR type parameters with a default cannot use forward declared identifiers
 
diff --git a/src/test/compile-fail/generic-type-params-forward-mention.rs b/src/test/compile-fail/generic-type-params-forward-mention.rs
index eda1b014fa7..bfa6af0da43 100644
--- a/src/test/compile-fail/generic-type-params-forward-mention.rs
+++ b/src/test/compile-fail/generic-type-params-forward-mention.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // Ensure that we get an error and not an ICE for this problematic case.
-struct Foo<T = Option<U>, U = bool>;
+struct Foo<T = Option<U>, U = bool>(T, U);
 //~^ ERROR type parameters with a default cannot use forward declared identifiers
 fn main() {
     let x: Foo;
diff --git a/src/test/compile-fail/issue-18183.rs b/src/test/compile-fail/issue-18183.rs
index b3fc3aea148..feab04531b7 100644
--- a/src/test/compile-fail/issue-18183.rs
+++ b/src/test/compile-fail/issue-18183.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub struct Foo<Bar=Bar>; //~ ERROR E0128
-                         //~| NOTE defaulted type parameters cannot be forward declared
+pub struct Foo<Bar=Bar>(Bar); //~ ERROR E0128
+                              //~| NOTE defaulted type parameters cannot be forward declared
 pub struct Baz(Foo);
 fn main() {}
diff --git a/src/test/compile-fail/resolve-self-in-impl.rs b/src/test/compile-fail/resolve-self-in-impl.rs
index 04f98c7ab32..ab9ac039825 100644
--- a/src/test/compile-fail/resolve-self-in-impl.rs
+++ b/src/test/compile-fail/resolve-self-in-impl.rs
@@ -15,7 +15,7 @@ impl Tr<Self> for S {} // OK
 
 // FIXME: `Self` cannot be used in bounds because it depends on bounds itself.
 impl<T: Tr<Self>> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
-impl<T = Self> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
+impl<T = Self> Tr<T> for S {}
 impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined
 impl Tr for S where S<Self>: Copy {} //~ ERROR `Self` type is used before it's determined
 impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined