diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 0c941a4a230..e261c699b6a 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -110,7 +110,6 @@ pub enum DepNode<D: Clone + Debug> {
     // predicates for an item wind up in `ItemSignature`).
     AssociatedItems(D),
     ItemSignature(D),
-    FieldTy(D),
     SizedConstraint(D),
     AssociatedItemDefIds(D),
     InherentImpls(D),
@@ -161,7 +160,6 @@ impl<D: Clone + Debug> DepNode<D> {
             TypeckItemBody,
             AssociatedItems,
             ItemSignature,
-            FieldTy,
             AssociatedItemDefIds,
             InherentImpls,
             TraitImpls,
@@ -229,7 +227,6 @@ impl<D: Clone + Debug> DepNode<D> {
             TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
             AssociatedItems(ref d) => op(d).map(AssociatedItems),
             ItemSignature(ref d) => op(d).map(ItemSignature),
-            FieldTy(ref d) => op(d).map(FieldTy),
             SizedConstraint(ref d) => op(d).map(SizedConstraint),
             AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
             InherentImpls(ref d) => op(d).map(InherentImpls),
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 484e2f1535e..822fb4d6770 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -278,8 +278,8 @@ pub trait CrateStore<'tcx> {
     fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                          -> ty::Generics<'tcx>;
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
-    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>;
-    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>;
+    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;
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;
 
@@ -425,9 +425,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                          -> ty::Generics<'tcx> { bug!("item_generics") }
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
-    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>
+    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef
         { bug!("trait_def") }
-    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
+    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef
         { bug!("adt_def") }
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 01d5792441f..b3e61f1e570 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -701,7 +701,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         // are properly handled.
         self.walk_expr(with_expr);
 
-        fn contains_field_named(field: ty::FieldDef,
+        fn contains_field_named(field: &ty::FieldDef,
                                 fields: &[hir::Field])
                                 -> bool
         {
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index b3cec6ec8ff..3cd35804732 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -462,7 +462,7 @@ pub enum TerminatorKind<'tcx> {
     /// lvalue evaluates to some enum; jump depending on the branch
     Switch {
         discr: Lvalue<'tcx>,
-        adt_def: AdtDef<'tcx>,
+        adt_def: &'tcx AdtDef,
         targets: Vec<BasicBlock>,
     },
 
@@ -866,7 +866,7 @@ pub enum ProjectionElem<'tcx, V> {
     /// "Downcast" to a variant of an ADT. Currently, we only introduce
     /// this for ADTs with more than one variant. It may be better to
     /// just introduce it always, or always for enums.
-    Downcast(AdtDef<'tcx>, usize),
+    Downcast(&'tcx AdtDef, usize),
 }
 
 /// Alias for projections as they appear in lvalues, where the base is an lvalue
@@ -1035,7 +1035,7 @@ pub enum AggregateKind<'tcx> {
     /// The second field is variant number (discriminant), it's equal to 0
     /// for struct and union expressions. The fourth field is active field
     /// number and is present only for union expressions.
-    Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>, Option<usize>),
+    Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option<usize>),
     Closure(DefId, ClosureSubsts<'tcx>),
 }
 
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 73ea84e94ae..03530945e04 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -25,7 +25,7 @@ pub enum LvalueTy<'tcx> {
     Ty { ty: Ty<'tcx> },
 
     /// Downcast to a particular variant of an enum.
-    Downcast { adt_def: AdtDef<'tcx>,
+    Downcast { adt_def: &'tcx AdtDef,
                substs: &'tcx Substs<'tcx>,
                variant_index: usize },
 }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 2e8e45468dd..76a5e2764f2 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -244,11 +244,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         for item in self.tcx.get_attrs(def_id).iter() {
             if item.check_name("rustc_on_unimplemented") {
                 let err_sp = item.meta().span.substitute_dummy(span);
-                let def = self.tcx.lookup_trait_def(trait_ref.def_id);
-                let trait_str = def.trait_ref.to_string();
+                let trait_str = self.tcx.item_path_str(trait_ref.def_id);
                 if let Some(istring) = item.value_str() {
                     let istring = &*istring.as_str();
-                    let generic_map = def.generics.types.iter().map(|param| {
+                    let generics = self.tcx.item_generics(trait_ref.def_id);
+                    let generic_map = generics.types.iter().map(|param| {
                         (param.name.as_str().to_string(),
                          trait_ref.substs.type_for_def(param).to_string())
                     }).collect::<FxHashMap<String, String>>();
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 0681be129b6..ceee6c236e4 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -21,7 +21,8 @@ use super::elaborate_predicates;
 
 use hir::def_id::DefId;
 use traits;
-use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::subst::Substs;
 use syntax::ast;
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -126,9 +127,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn supertraits_reference_self(self, trait_def_id: DefId) -> bool {
-        let trait_def = self.lookup_trait_def(trait_def_id);
-        let trait_ref = trait_def.trait_ref.clone();
-        let trait_ref = trait_ref.to_poly_trait_ref();
+        let trait_ref = ty::Binder(ty::TraitRef {
+            def_id: trait_def_id,
+            substs: Substs::identity_for_item(self, trait_def_id)
+        });
         let predicates = self.item_super_predicates(trait_def_id);
         predicates
             .predicates
@@ -317,8 +319,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
                     // Compute supertraits of current trait lazily.
                     if supertraits.is_none() {
-                        let trait_def = self.lookup_trait_def(trait_def_id);
-                        let trait_ref = ty::Binder(trait_def.trait_ref.clone());
+                        let trait_ref = ty::Binder(ty::TraitRef {
+                            def_id: trait_def_id,
+                            substs: Substs::identity_for_item(self, trait_def_id)
+                        });
                         supertraits = Some(traits::supertraits(self, trait_ref).collect());
                     }
 
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 38a228034dd..c54c0bf74ef 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2544,7 +2544,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             (&ty::TyAdt(def, substs_a), &ty::TyAdt(_, substs_b)) => {
                 let fields = def
                     .all_fields()
-                    .map(|f| f.unsubst_ty())
+                    .map(|f| tcx.item_type(f.did))
                     .collect::<Vec<_>>();
 
                 // The last field of the structure has to exist and contain type parameters.
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 5a6809f1fad..a41523f2def 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -297,18 +297,18 @@ impl<'a, 'gcx, 'tcx> Node {
     }
 }
 
-pub struct Ancestors<'a, 'tcx: 'a> {
-    trait_def: &'a TraitDef<'tcx>,
+pub struct Ancestors<'a> {
+    trait_def: &'a TraitDef,
     current_source: Option<Node>,
 }
 
-impl<'a, 'tcx> Iterator for Ancestors<'a, 'tcx> {
+impl<'a> Iterator for Ancestors<'a> {
     type Item = Node;
     fn next(&mut self) -> Option<Node> {
         let cur = self.current_source.take();
         if let Some(Node::Impl(cur_impl)) = cur {
             let parent = self.trait_def.specialization_graph.borrow().parent(cur_impl);
-            if parent == self.trait_def.def_id() {
+            if parent == self.trait_def.def_id {
                 self.current_source = Some(Node::Trait(parent));
             } else {
                 self.current_source = Some(Node::Impl(parent));
@@ -332,7 +332,7 @@ impl<T> NodeItem<T> {
     }
 }
 
-impl<'a, 'gcx, 'tcx> Ancestors<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> Ancestors<'a> {
     /// Search the items from the given ancestors, returning each definition
     /// with the given name and the given kind.
     #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
@@ -347,9 +347,7 @@ impl<'a, 'gcx, 'tcx> Ancestors<'a, 'tcx> {
 
 /// Walk up the specialization ancestors of a given impl, starting with that
 /// impl itself.
-pub fn ancestors<'a, 'tcx>(trait_def: &'a TraitDef<'tcx>,
-                           start_from_impl: DefId)
-                           -> Ancestors<'a, 'tcx> {
+pub fn ancestors<'a>(trait_def: &'a TraitDef, start_from_impl: DefId) -> Ancestors<'a> {
     Ancestors {
         trait_def: trait_def,
         current_source: Some(Node::Impl(start_from_impl)),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index c23ee489a28..17c335fc9c7 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -68,8 +68,8 @@ pub struct CtxtArenas<'tcx> {
 
     // references
     generics: TypedArena<ty::Generics<'tcx>>,
-    trait_def: TypedArena<ty::TraitDef<'tcx>>,
-    adt_def: TypedArena<ty::AdtDefData<'tcx, 'tcx>>,
+    trait_def: TypedArena<ty::TraitDef>,
+    adt_def: TypedArena<ty::AdtDef>,
     mir: TypedArena<RefCell<Mir<'tcx>>>,
 }
 
@@ -425,6 +425,7 @@ pub struct GlobalCtxt<'tcx> {
     pub impl_trait_refs: RefCell<DepTrackingMap<maps::ImplTraitRefs<'tcx>>>,
     pub trait_defs: RefCell<DepTrackingMap<maps::TraitDefs<'tcx>>>,
     pub adt_defs: RefCell<DepTrackingMap<maps::AdtDefs<'tcx>>>,
+    pub adt_sized_constraint: RefCell<DepTrackingMap<maps::AdtSizedConstraint<'tcx>>>,
 
     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
     /// associated generics and predicates.
@@ -688,38 +689,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.global_interners.arenas.mir.alloc(RefCell::new(mir))
     }
 
-    pub fn intern_trait_def(self, def: ty::TraitDef<'gcx>)
-                            -> &'gcx ty::TraitDef<'gcx> {
-        let did = def.trait_ref.def_id;
-        let interned = self.alloc_trait_def(def);
-        if let Some(prev) = self.trait_defs.borrow_mut().insert(did, interned) {
-            bug!("Tried to overwrite interned TraitDef: {:?}", prev)
-        }
-        self.generics.borrow_mut().insert(did, interned.generics);
-        interned
-    }
-
-    pub fn alloc_trait_def(self, def: ty::TraitDef<'gcx>)
-                           -> &'gcx ty::TraitDef<'gcx> {
+    pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
         self.global_interners.arenas.trait_def.alloc(def)
     }
 
-    pub fn insert_adt_def(self, did: DefId, adt_def: ty::AdtDefMaster<'gcx>) {
-        // this will need a transmute when reverse-variance is removed
-        if let Some(prev) = self.adt_defs.borrow_mut().insert(did, adt_def) {
-            bug!("Tried to overwrite interned AdtDef: {:?}", prev)
-        }
-    }
-
-    pub fn intern_adt_def(self,
-                          did: DefId,
-                          kind: AdtKind,
-                          variants: Vec<ty::VariantDefData<'gcx, 'gcx>>)
-                          -> ty::AdtDefMaster<'gcx> {
-        let def = ty::AdtDefData::new(self, did, kind, variants);
-        let interned = self.global_interners.arenas.adt_def.alloc(def);
-        self.insert_adt_def(did, interned);
-        interned
+    pub fn alloc_adt_def(self,
+                         did: DefId,
+                         kind: AdtKind,
+                         variants: Vec<ty::VariantDef>)
+                         -> &'gcx ty::AdtDef {
+        let def = ty::AdtDef::new(self, did, kind, variants);
+        self.global_interners.arenas.adt_def.alloc(def)
     }
 
     pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
@@ -815,6 +795,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
+            adt_sized_constraint: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             generics: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
@@ -1392,7 +1373,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
     }
 
-    pub fn mk_adt(self, def: AdtDef<'tcx>, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+    pub fn mk_adt(self, def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
         // take a copy of substs so that we own the vectors inside
         self.mk_ty(TyAdt(def, substs))
     }
diff --git a/src/librustc/ty/ivar.rs b/src/librustc/ty/ivar.rs
deleted file mode 100644
index 634599406af..00000000000
--- a/src/librustc/ty/ivar.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use dep_graph::DepNode;
-use hir::def_id::DefId;
-use ty::{Ty, TyS};
-use ty::tls;
-
-use rustc_data_structures::ivar;
-
-use std::fmt;
-use std::marker::PhantomData;
-use core::nonzero::NonZero;
-
-/// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
-/// on the lifetime of the IVar. This is required because of variance
-/// problems: the IVar needs to be variant with respect to 'tcx (so
-/// it can be referred to from Ty) but can only be modified if its
-/// lifetime is exactly 'tcx.
-///
-/// Safety invariants:
-///     (A) self.0, if fulfilled, is a valid Ty<'tcx>
-///     (B) no aliases to this value with a 'tcx longer than this
-///         value's 'lt exist
-///
-/// Dependency tracking: each ivar does not know what node in the
-/// dependency graph it is associated with, so when you get/fulfill
-/// you must supply a `DepNode` id. This should always be the same id!
-///
-/// NonZero is used rather than Unique because Unique isn't Copy.
-pub struct TyIVar<'tcx, 'lt: 'tcx>(ivar::Ivar<NonZero<*const TyS<'static>>>,
-                                   PhantomData<fn(TyS<'lt>)->TyS<'tcx>>);
-
-impl<'tcx, 'lt> TyIVar<'tcx, 'lt> {
-    #[inline]
-    pub fn new() -> Self {
-        // Invariant (A) satisfied because the IVar is unfulfilled
-        // Invariant (B) because 'lt : 'tcx
-        TyIVar(ivar::Ivar::new(), PhantomData)
-    }
-
-    #[inline]
-    pub fn get(&self, dep_node: DepNode<DefId>) -> Option<Ty<'tcx>> {
-        tls::with(|tcx| tcx.dep_graph.read(dep_node));
-        self.untracked_get()
-    }
-
-    /// Reads the ivar without registered a dep-graph read. Use with
-    /// caution.
-    #[inline]
-    pub fn untracked_get(&self) -> Option<Ty<'tcx>> {
-        match self.0.get() {
-            None => None,
-            // valid because of invariant (A)
-            Some(v) => Some(unsafe { &*(*v as *const TyS<'tcx>) })
-        }
-    }
-
-    #[inline]
-    pub fn unwrap(&self, dep_node: DepNode<DefId>) -> Ty<'tcx> {
-        self.get(dep_node).unwrap()
-    }
-
-    pub fn fulfill(&self, dep_node: DepNode<DefId>, value: Ty<'lt>) {
-        tls::with(|tcx| tcx.dep_graph.write(dep_node));
-
-        // Invariant (A) is fulfilled, because by (B), every alias
-        // of this has a 'tcx longer than 'lt.
-        let value: *const TyS<'lt> = value;
-        // FIXME(27214): unneeded [as *const ()]
-        let value = value as *const () as *const TyS<'static>;
-        self.0.fulfill(unsafe { NonZero::new(value) })
-    }
-}
-
-impl<'tcx, 'lt> fmt::Debug for TyIVar<'tcx, 'lt> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.untracked_get() {
-            Some(val) => write!(f, "TyIVar({:?})", val),
-            None => f.write_str("TyIVar(<unfulfilled>)")
-        }
-    }
-}
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index bf044585879..42b3544421f 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -39,8 +39,9 @@ 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>> }
 dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>> }
-dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> }
-dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
+dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef }
+dep_map_ty! { AdtDefs: ItemSignature(DefId) -> &'tcx ty::AdtDef }
+dep_map_ty! { AdtSizedConstraint: SizedConstraint(DefId) -> Ty<'tcx> }
 dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>> }
 dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
 dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 3ce092db482..df12c252907 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -93,7 +93,6 @@ pub mod util;
 mod contents;
 mod context;
 mod flags;
-mod ivar;
 mod structural_impls;
 mod sty;
 
@@ -623,10 +622,6 @@ pub struct RegionParameterDef<'tcx> {
 }
 
 impl<'tcx> RegionParameterDef<'tcx> {
-    pub fn to_early_bound_region(&self) -> ty::Region {
-        ty::ReEarlyBound(self.to_early_bound_region_data())
-    }
-
     pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
         ty::EarlyBoundRegion {
             index: self.index,
@@ -1313,106 +1308,64 @@ bitflags! {
     }
 }
 
-pub type AdtDef<'tcx> = &'tcx AdtDefData<'tcx, 'static>;
-pub type VariantDef<'tcx> = &'tcx VariantDefData<'tcx, 'static>;
-pub type FieldDef<'tcx> = &'tcx FieldDefData<'tcx, 'static>;
-
-// See comment on AdtDefData for explanation
-pub type AdtDefMaster<'tcx> = &'tcx AdtDefData<'tcx, 'tcx>;
-pub type VariantDefMaster<'tcx> = &'tcx VariantDefData<'tcx, 'tcx>;
-pub type FieldDefMaster<'tcx> = &'tcx FieldDefData<'tcx, 'tcx>;
-
-pub struct VariantDefData<'tcx, 'container: 'tcx> {
+pub struct VariantDef {
     /// The variant's DefId. If this is a tuple-like struct,
     /// this is the DefId of the struct's ctor.
     pub did: DefId,
     pub name: Name, // struct's name if this is a struct
     pub disr_val: Disr,
-    pub fields: Vec<FieldDefData<'tcx, 'container>>,
+    pub fields: Vec<FieldDef>,
     pub ctor_kind: CtorKind,
 }
 
-pub struct FieldDefData<'tcx, 'container: 'tcx> {
+pub struct FieldDef {
     pub did: DefId,
     pub name: Name,
     pub vis: Visibility,
-    /// TyIVar is used here to allow for variance (see the doc at
-    /// AdtDefData).
-    ///
-    /// Note: direct accesses to `ty` must also add dep edges.
-    ty: ivar::TyIVar<'tcx, 'container>
 }
 
 /// The definition of an abstract data type - a struct or enum.
 ///
 /// These are all interned (by intern_adt_def) into the adt_defs
 /// table.
-///
-/// Because of the possibility of nested tcx-s, this type
-/// needs 2 lifetimes: the traditional variant lifetime ('tcx)
-/// bounding the lifetime of the inner types is of course necessary.
-/// However, it is not sufficient - types from a child tcx must
-/// not be leaked into the master tcx by being stored in an AdtDefData.
-///
-/// The 'container lifetime ensures that by outliving the container
-/// tcx and preventing shorter-lived types from being inserted. When
-/// write access is not needed, the 'container lifetime can be
-/// erased to 'static, which can be done by the AdtDef wrapper.
-pub struct AdtDefData<'tcx, 'container: 'tcx> {
+pub struct AdtDef {
     pub did: DefId,
-    pub variants: Vec<VariantDefData<'tcx, 'container>>,
+    pub variants: Vec<VariantDef>,
     destructor: Cell<Option<DefId>>,
-    flags: Cell<AdtFlags>,
-    sized_constraint: ivar::TyIVar<'tcx, 'container>,
+    flags: Cell<AdtFlags>
 }
 
-impl<'tcx, 'container> PartialEq for AdtDefData<'tcx, 'container> {
-    // AdtDefData are always interned and this is part of TyS equality
+impl PartialEq for AdtDef {
+    // AdtDef are always interned and this is part of TyS equality
     #[inline]
     fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
 }
 
-impl<'tcx, 'container> Eq for AdtDefData<'tcx, 'container> {}
+impl Eq for AdtDef {}
 
-impl<'tcx, 'container> Hash for AdtDefData<'tcx, 'container> {
+impl Hash for AdtDef {
     #[inline]
     fn hash<H: Hasher>(&self, s: &mut H) {
-        (self as *const AdtDefData).hash(s)
+        (self as *const AdtDef).hash(s)
     }
 }
 
-impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> {
+impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef {
     fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         self.did.encode(s)
     }
 }
 
-impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {}
-
-impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> {
-    #[inline]
-    pub fn is_uninhabited_recurse(&'tcx self,
-                                  visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
-                                  block: Option<NodeId>,
-                                  cx: TyCtxt<'a, 'gcx, 'tcx>,
-                                  substs: &'tcx Substs<'tcx>) -> bool {
-        if !visited.insert((self.did, substs)) {
-            return false;
-        };
-        self.variants.iter().all(|v| {
-            v.is_uninhabited_recurse(visited, block, cx, substs, self.is_union())
-        })
-    }
-}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum AdtKind { Struct, Union, Enum }
 
-impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
+impl<'a, 'gcx, 'tcx> AdtDef {
     fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
            did: DefId,
            kind: AdtKind,
-           variants: Vec<VariantDefData<'gcx, 'container>>) -> Self {
+           variants: Vec<VariantDef>) -> Self {
         let mut flags = AdtFlags::NO_ADT_FLAGS;
         let attrs = tcx.get_attrs(did);
         if attr::contains_name(&attrs, "fundamental") {
@@ -1429,12 +1382,11 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
             AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
             AdtKind::Struct => {}
         }
-        AdtDefData {
+        AdtDef {
             did: did,
             variants: variants,
             flags: Cell::new(flags),
             destructor: Cell::new(None),
-            sized_constraint: ivar::TyIVar::new(),
         }
     }
 
@@ -1445,6 +1397,20 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
         self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK_VALID)
     }
 
+    #[inline]
+    pub fn is_uninhabited_recurse(&self,
+                                  visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+                                  block: Option<NodeId>,
+                                  tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                  substs: &'tcx Substs<'tcx>) -> bool {
+        if !visited.insert((self.did, substs)) {
+            return false;
+        };
+        self.variants.iter().all(|v| {
+            v.is_uninhabited_recurse(visited, block, tcx, substs, self.is_union())
+        })
+    }
+
     #[inline]
     pub fn is_struct(&self) -> bool {
         !self.is_union() && !self.is_enum()
@@ -1524,7 +1490,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
 
     /// Asserts this is a struct and returns the struct's unique
     /// variant.
-    pub fn struct_variant(&self) -> &VariantDefData<'gcx, 'container> {
+    pub fn struct_variant(&self) -> &VariantDef {
         assert!(!self.is_enum());
         &self.variants[0]
     }
@@ -1537,14 +1503,8 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
     /// Returns an iterator over all fields contained
     /// by this ADT.
     #[inline]
-    pub fn all_fields(&self) ->
-            iter::FlatMap<
-                slice::Iter<VariantDefData<'gcx, 'container>>,
-                slice::Iter<FieldDefData<'gcx, 'container>>,
-                for<'s> fn(&'s VariantDefData<'gcx, 'container>)
-                    -> slice::Iter<'s, FieldDefData<'gcx, 'container>>
-            > {
-        self.variants.iter().flat_map(VariantDefData::fields_iter)
+    pub fn all_fields<'s>(&'s self) -> impl Iterator<Item = &'s FieldDef> {
+        self.variants.iter().flat_map(|v| v.fields.iter())
     }
 
     #[inline]
@@ -1557,7 +1517,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
             self.variants.iter().all(|v| v.fields.is_empty())
     }
 
-    pub fn variant_with_id(&self, vid: DefId) -> &VariantDefData<'gcx, 'container> {
+    pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
         self.variants
             .iter()
             .find(|v| v.did == vid)
@@ -1571,7 +1531,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
             .expect("variant_index_with_id: unknown variant")
     }
 
-    pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> {
+    pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         match def {
             Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
@@ -1594,9 +1554,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
             None => NoDtor,
         }
     }
-}
 
-impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     /// Returns a simpler type such that `Self: Sized` if and only
     /// if that type is Sized, or `TyErr` if this type is recursive.
     ///
@@ -1615,19 +1573,9 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        match self.sized_constraint.get(DepNode::SizedConstraint(self.did)) {
-            None => {
-                let global_tcx = tcx.global_tcx();
-                let this = global_tcx.lookup_adt_def_master(self.did);
-                this.calculate_sized_constraint_inner(global_tcx, &mut Vec::new());
-                self.sized_constraint(tcx)
-            }
-            Some(ty) => ty
-        }
+        self.calculate_sized_constraint_inner(tcx.global_tcx(), &mut Vec::new())
     }
-}
 
-impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     /// Calculates the Sized-constraint.
     ///
     /// As the Sized-constraint of enums can be a *set* of types,
@@ -1643,42 +1591,41 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     ///       such.
     ///     - a TyError, if a type contained itself. The representability
     ///       check should catch this case.
-    fn calculate_sized_constraint_inner(&'tcx self,
+    fn calculate_sized_constraint_inner(&self,
                                         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        stack: &mut Vec<AdtDefMaster<'tcx>>)
+                                        stack: &mut Vec<DefId>)
+                                        -> Ty<'tcx>
     {
-        let dep_node = || DepNode::SizedConstraint(self.did);
+        if let Some(ty) = tcx.adt_sized_constraint.borrow().get(&self.did) {
+            return ty;
+        }
 
         // Follow the memoization pattern: push the computation of
         // DepNode::SizedConstraint as our current task.
-        let _task = tcx.dep_graph.in_task(dep_node());
-        if self.sized_constraint.untracked_get().is_some() {
-            //                   ---------------
-            // can skip the dep-graph read since we just pushed the task
-            return;
-        }
+        let _task = tcx.dep_graph.in_task(DepNode::SizedConstraint(self.did));
 
-        if stack.contains(&self) {
+        if stack.contains(&self.did) {
             debug!("calculate_sized_constraint: {:?} is recursive", self);
             // This should be reported as an error by `check_representable`.
             //
             // Consider the type as Sized in the meanwhile to avoid
             // further errors.
-            self.sized_constraint.fulfill(dep_node(), tcx.types.err);
-            return;
+            tcx.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err);
+            return tcx.types.err;
         }
 
-        stack.push(self);
+        stack.push(self.did);
 
         let tys : Vec<_> =
             self.variants.iter().flat_map(|v| {
                 v.fields.last()
             }).flat_map(|f| {
-                self.sized_constraint_for_ty(tcx, stack, f.unsubst_ty())
+                let ty = tcx.item_type(f.did);
+                self.sized_constraint_for_ty(tcx, stack, ty)
             }).collect();
 
         let self_ = stack.pop().unwrap();
-        assert_eq!(self_, self);
+        assert_eq!(self_, self.did);
 
         let ty = match tys.len() {
             _ if tys.references_error() => tcx.types.err,
@@ -1687,24 +1634,26 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
             _ => tcx.intern_tup(&tys[..])
         };
 
-        match self.sized_constraint.get(dep_node()) {
+        let old = tcx.adt_sized_constraint.borrow().get(&self.did).cloned();
+        match old {
             Some(old_ty) => {
                 debug!("calculate_sized_constraint: {:?} recurred", self);
-                assert_eq!(old_ty, tcx.types.err)
+                assert_eq!(old_ty, tcx.types.err);
+                old_ty
             }
             None => {
                 debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
-                self.sized_constraint.fulfill(dep_node(), ty)
+                tcx.adt_sized_constraint.borrow_mut().insert(self.did, ty);
+                ty
             }
         }
     }
 
-    fn sized_constraint_for_ty(
-        &'tcx self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        stack: &mut Vec<AdtDefMaster<'tcx>>,
-        ty: Ty<'tcx>
-    ) -> Vec<Ty<'tcx>> {
+    fn sized_constraint_for_ty(&self,
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               stack: &mut Vec<DefId>,
+                               ty: Ty<'tcx>)
+                               -> Vec<Ty<'tcx>> {
         let result = match ty.sty {
             TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
             TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
@@ -1726,12 +1675,9 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
 
             TyAdt(adt, substs) => {
                 // recursive case
-                let adt = tcx.lookup_adt_def_master(adt.did);
-                adt.calculate_sized_constraint_inner(tcx, stack);
                 let adt_ty =
-                    adt.sized_constraint
-                    .unwrap(DepNode::SizedConstraint(adt.did))
-                    .subst(tcx, substs);
+                    adt.calculate_sized_constraint_inner(tcx, stack)
+                       .subst(tcx, substs);
                 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
                        ty, adt_ty);
                 if let ty::TyTuple(ref tys) = adt_ty.sty {
@@ -1780,16 +1726,11 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     }
 }
 
-impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
-    #[inline]
-    fn fields_iter(&self) -> slice::Iter<FieldDefData<'tcx, 'container>> {
-        self.fields.iter()
-    }
-
+impl<'a, 'gcx, 'tcx> VariantDef {
     #[inline]
     pub fn find_field_named(&self,
                             name: ast::Name)
-                            -> Option<&FieldDefData<'tcx, 'container>> {
+                            -> Option<&FieldDef> {
         self.fields.iter().find(|f| f.name == name)
     }
 
@@ -1801,55 +1742,32 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
     }
 
     #[inline]
-    pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> {
+    pub fn field_named(&self, name: ast::Name) -> &FieldDef {
         self.find_field_named(name).unwrap()
     }
-}
 
-impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> {
     #[inline]
-    pub fn is_uninhabited_recurse(&'tcx self,
+    pub fn is_uninhabited_recurse(&self,
                                   visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
                                   block: Option<NodeId>,
-                                  cx: TyCtxt<'a, 'gcx, 'tcx>,
+                                  tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                   substs: &'tcx Substs<'tcx>,
                                   is_union: bool) -> bool {
         if is_union {
-            self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
+            self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, tcx, substs))
         } else {
-            self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
+            self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, tcx, substs))
         }
     }
 }
 
-impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
-    pub fn new(did: DefId,
-               name: Name,
-               vis: Visibility) -> Self {
-        FieldDefData {
-            did: did,
-            name: name,
-            vis: vis,
-            ty: ivar::TyIVar::new()
-        }
-    }
-
+impl<'a, 'gcx, 'tcx> FieldDef {
     pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
-        self.unsubst_ty().subst(tcx, subst)
+        tcx.item_type(self.did).subst(tcx, subst)
     }
 
-    pub fn unsubst_ty(&self) -> Ty<'tcx> {
-        self.ty.unwrap(DepNode::FieldTy(self.did))
-    }
-
-    pub fn fulfill_ty(&self, ty: Ty<'container>) {
-        self.ty.fulfill(DepNode::FieldTy(self.did), ty);
-    }
-}
-
-impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> {
     #[inline]
-    pub fn is_uninhabited_recurse(&'tcx self,
+    pub fn is_uninhabited_recurse(&self,
                                   visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
                                   block: Option<NodeId>,
                                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
@@ -2295,7 +2213,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     // Returns `ty::VariantDef` if `def` refers to a struct,
     // or variant or their constructors, panics otherwise.
-    pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {
+    pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
         match def {
             Def::Variant(did) | Def::VariantCtor(did, ..) => {
                 let enum_did = self.parent_def_id(did).unwrap();
@@ -2398,28 +2316,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Given the did of a trait, returns its canonical trait ref.
-    pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef<'gcx> {
+    pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef {
         lookup_locally_or_in_crate_store(
             "trait_defs", did, &self.trait_defs,
             || self.alloc_trait_def(self.sess.cstore.trait_def(self.global_tcx(), did))
         )
     }
 
-    /// Given the did of an ADT, return a master reference to its
-    /// definition. Unless you are planning on fulfilling the ADT's fields,
-    /// use lookup_adt_def instead.
-    pub fn lookup_adt_def_master(self, did: DefId) -> AdtDefMaster<'gcx> {
+    /// Given the did of an ADT, return a reference to its definition.
+    pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef {
         lookup_locally_or_in_crate_store(
             "adt_defs", did, &self.adt_defs,
-            || self.sess.cstore.adt_def(self.global_tcx(), did)
-        )
-    }
-
-    /// Given the did of an ADT, return a reference to its definition.
-    pub fn lookup_adt_def(self, did: DefId) -> AdtDef<'gcx> {
-        // when reverse-variance goes away, a transmute::<AdtDefMaster,AdtDef>
-        // would be needed here.
-        self.lookup_adt_def_master(did)
+            || self.sess.cstore.adt_def(self.global_tcx(), did))
     }
 
     /// Given the did of an item, returns its generics.
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 667db5b6730..59f774b954c 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -113,7 +113,7 @@ pub enum TypeVariants<'tcx> {
     /// That is, even after substitution it is possible that there are type
     /// variables. This happens when the `TyAdt` corresponds to an ADT
     /// definition and not a concrete use of it.
-    TyAdt(AdtDef<'tcx>, &'tcx Substs<'tcx>),
+    TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>),
 
     /// `Box<T>`; this is nominally a struct in the documentation, but is
     /// special-cased internally. For example, it is possible to implicitly
@@ -1267,7 +1267,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         }
     }
 
-    pub fn ty_adt_def(&self) -> Option<AdtDef<'tcx>> {
+    pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
         match self.sty {
             TyAdt(adt, _) => Some(adt),
             _ => None
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 41fcb09fb2d..d6f61a12a3c 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -165,6 +165,14 @@ impl<'tcx> Decodable for Kind<'tcx> {
 pub type Substs<'tcx> = Slice<Kind<'tcx>>;
 
 impl<'a, 'gcx, 'tcx> Substs<'tcx> {
+    /// Creates a Substs that maps each generic parameter to itself.
+    pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
+                             -> &'tcx Substs<'tcx> {
+        Substs::for_item(tcx, def_id, |def, _| {
+            tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
+        }, |def, _| tcx.mk_param_from_def(def))
+    }
+
     /// Creates a Substs for generic parameter definitions,
     /// by calling closures to obtain each region and type.
     /// The closures get to observe the Substs as they're
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index fd81065e61d..c6d862b23bd 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -19,7 +19,9 @@ use hir;
 use util::nodemap::FxHashMap;
 
 /// A trait's definition with type information.
-pub struct TraitDef<'tcx> {
+pub struct TraitDef {
+    pub def_id: DefId,
+
     pub unsafety: hir::Unsafety,
 
     /// If `true`, then this trait had the `#[rustc_paren_sugar]`
@@ -28,15 +30,6 @@ pub struct TraitDef<'tcx> {
     /// be usable with the sugar (or without it).
     pub paren_sugar: bool,
 
-    /// Generic type definitions. Note that `Self` is listed in here
-    /// as having a single bound, the trait itself (e.g., in the trait
-    /// `Eq`, there is a single bound `Self : Eq`). This is so that
-    /// default methods get to assume that the `Self` parameters
-    /// implements the trait.
-    pub generics: &'tcx ty::Generics<'tcx>,
-
-    pub trait_ref: ty::TraitRef<'tcx>,
-
     // Impls of a trait. To allow for quicker lookup, the impls are indexed by a
     // simplified version of their `Self` type: impls with a simplifiable `Self`
     // are stored in `nonblanket_impls` keyed by it, while all other impls are
@@ -72,18 +65,16 @@ pub struct TraitDef<'tcx> {
     pub def_path_hash: u64,
 }
 
-impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
-    pub fn new(unsafety: hir::Unsafety,
+impl<'a, 'gcx, 'tcx> TraitDef {
+    pub fn new(def_id: DefId,
+               unsafety: hir::Unsafety,
                paren_sugar: bool,
-               generics: &'tcx ty::Generics<'tcx>,
-               trait_ref: ty::TraitRef<'tcx>,
                def_path_hash: u64)
-               -> TraitDef<'tcx> {
+               -> TraitDef {
         TraitDef {
+            def_id: def_id,
             paren_sugar: paren_sugar,
             unsafety: unsafety,
-            generics: generics,
-            trait_ref: trait_ref,
             nonblanket_impls: RefCell::new(FxHashMap()),
             blanket_impls: RefCell::new(vec![]),
             flags: Cell::new(ty::TraitFlags::NO_TRAIT_FLAGS),
@@ -92,10 +83,6 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
         }
     }
 
-    pub fn def_id(&self) -> DefId {
-        self.trait_ref.def_id
-    }
-
     // returns None if not yet calculated
     pub fn object_safety(&self) -> Option<bool> {
         if self.flags.get().intersects(TraitFlags::OBJECT_SAFETY_VALID) {
@@ -117,11 +104,11 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
     }
 
     fn write_trait_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) {
-        tcx.dep_graph.write(DepNode::TraitImpls(self.trait_ref.def_id));
+        tcx.dep_graph.write(DepNode::TraitImpls(self.def_id));
     }
 
     fn read_trait_impls(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) {
-        tcx.dep_graph.read(DepNode::TraitImpls(self.trait_ref.def_id));
+        tcx.dep_graph.read(DepNode::TraitImpls(self.def_id));
     }
 
     /// Records a basic trait-to-implementation mapping.
@@ -203,13 +190,13 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
             .insert(tcx, impl_def_id)
     }
 
-    pub fn ancestors(&'a self, of_impl: DefId) -> specialization_graph::Ancestors<'a, 'tcx> {
+    pub fn ancestors(&'a self, of_impl: DefId) -> specialization_graph::Ancestors<'a> {
         specialization_graph::ancestors(self, of_impl)
     }
 
     pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, mut f: F) {
         self.read_trait_impls(tcx);
-        tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id);
+        tcx.populate_implementations_for_trait_if_necessary(self.def_id);
 
         for &impl_def_id in self.blanket_impls.borrow().iter() {
             f(impl_def_id);
@@ -231,7 +218,7 @@ impl<'a, 'gcx, 'tcx> TraitDef<'tcx> {
     {
         self.read_trait_impls(tcx);
 
-        tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id);
+        tcx.populate_implementations_for_trait_if_necessary(self.def_id);
 
         for &impl_def_id in self.blanket_impls.borrow().iter() {
             f(impl_def_id);
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 6ba4b8d2da7..6bb9d67db6f 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -366,7 +366,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// `adt` that do not strictly outlive the adt value itself.
     /// (This allows programs to make cyclic structures without
     /// resorting to unasfe means; see RFCs 769 and 1238).
-    pub fn is_adt_dtorck(self, adt: ty::AdtDef) -> bool {
+    pub fn is_adt_dtorck(self, adt: &ty::AdtDef) -> bool {
         let dtor_method = match adt.destructor() {
             Some(dtor) => dtor,
             None => return false
@@ -773,7 +773,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
             }
         }
 
-        fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
+        fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool {
             match ty.sty {
                 TyAdt(ty_def, _) => {
                      ty_def == def
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index d839df80a12..b4c87e0ce42 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -388,14 +388,15 @@ impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Debug for ty::TraitDef<'tcx> {
+impl fmt::Debug for ty::TraitDef {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TraitDef(generics={:?}, trait_ref={:?})",
-               self.generics, self.trait_ref)
+        ty::tls::with(|tcx| {
+            write!(f, "{}", tcx.item_path_str(self.def_id))
+        })
     }
 }
 
-impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
+impl fmt::Debug for ty::AdtDef {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         ty::tls::with(|tcx| {
             write!(f, "{}", tcx.item_path_str(self.did))
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
index 49ef5dd7a17..4f49bfc9725 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
@@ -442,7 +442,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     fn move_paths_for_fields(&self,
                              base_lv: &Lvalue<'tcx>,
                              variant_path: MovePathIndex,
-                             variant: ty::VariantDef<'tcx>,
+                             variant: &'tcx ty::VariantDef,
                              substs: &'tcx Substs<'tcx>)
                              -> Vec<(Lvalue<'tcx>, Option<MovePathIndex>)>
     {
@@ -619,7 +619,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     fn open_drop_for_variant<'a>(&mut self,
                                  c: &DropCtxt<'a, 'tcx>,
                                  drop_block: &mut Option<BasicBlock>,
-                                 adt: ty::AdtDef<'tcx>,
+                                 adt: &'tcx ty::AdtDef,
                                  substs: &'tcx Substs<'tcx>,
                                  variant_index: usize)
                                  -> BasicBlock
@@ -652,7 +652,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     }
 
     fn open_drop_for_adt<'a>(&mut self, c: &DropCtxt<'a, 'tcx>,
-                             adt: ty::AdtDef<'tcx>, substs: &'tcx Substs<'tcx>)
+                             adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>)
                              -> BasicBlock {
         debug!("open_drop_for_adt({:?}, {:?}, {:?})", c, adt, substs);
 
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index db24ad0fd67..23771f4bae3 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -223,10 +223,8 @@ pub enum Constructor {
     Slice(usize),
 }
 
-impl Constructor {
-    fn variant_for_adt<'tcx, 'container, 'a>(&self,
-                                             adt: &'a ty::AdtDefData<'tcx, 'container>)
-                                             -> &'a ty::VariantDefData<'tcx, 'container> {
+impl<'tcx> Constructor {
+    fn variant_for_adt(&self, adt: &'tcx ty::AdtDef) -> &'tcx ty::VariantDef {
         match self {
             &Variant(vid) => adt.variant_with_id(vid),
             &Single => {
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index 8e803da98f8..e93178c89c2 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -66,7 +66,7 @@ pub enum PatternKind<'tcx> {
 
     /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
     Variant {
-        adt_def: AdtDef<'tcx>,
+        adt_def: &'tcx AdtDef,
         variant_index: usize,
         subpatterns: Vec<FieldPattern<'tcx>>,
     },
@@ -487,32 +487,22 @@ impl<'tcx, T: PatternFoldable<'tcx>> PatternFoldable<'tcx> for Option<T> {
     }
 }
 
-macro_rules! CopyImpls {
-    ($($ty:ty),+) => {
+macro_rules! CloneImpls {
+    (<$lt_tcx:tt> $($ty:ty),+) => {
         $(
-            impl<'tcx> PatternFoldable<'tcx> for $ty {
-                fn super_fold_with<F: PatternFolder<'tcx>>(&self, _: &mut F) -> Self {
-                    self.clone()
-                }
-            }
-            )+
-    }
-}
-
-macro_rules! TcxCopyImpls {
-    ($($ty:ident),+) => {
-        $(
-            impl<'tcx> PatternFoldable<'tcx> for $ty<'tcx> {
-                fn super_fold_with<F: PatternFolder<'tcx>>(&self, _: &mut F) -> Self {
-                    *self
+            impl<$lt_tcx> PatternFoldable<$lt_tcx> for $ty {
+                fn super_fold_with<F: PatternFolder<$lt_tcx>>(&self, _: &mut F) -> Self {
+                    Clone::clone(self)
                 }
             }
         )+
     }
 }
 
-CopyImpls!{ Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal }
-TcxCopyImpls!{ Ty, BindingMode, AdtDef }
+CloneImpls!{ <'tcx>
+    Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal,
+    Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef
+}
 
 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 6e9467d63dd..bba31c8237d 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -396,7 +396,7 @@ enum FfiResult {
 /// expanded to cover NonZero raw pointers and newtypes.
 /// FIXME: This duplicates code in trans.
 fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  def: ty::AdtDef<'tcx>,
+                                  def: &'tcx ty::AdtDef,
                                   substs: &Substs<'tcx>)
                                   -> bool {
     if def.variants.len() == 2 {
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index c41c3afb83e..3150f74e61e 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -115,13 +115,13 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
     }
 
-    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx>
+    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef
     {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_trait_def(def.index, tcx)
     }
 
-    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
+    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::AdtDef
     {
         self.dep_graph.read(DepNode::MetaData(def));
         self.get_crate_data(def.krate).get_adt_def(def.index, tcx)
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 308cd6a83db..fe536b69c61 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -422,8 +422,8 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::BareFnTy<'tcx>> for DecodeContext<'a
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<ty::AdtDef<'tcx>> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<ty::AdtDef<'tcx>, Self::Error> {
+impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::AdtDef> for DecodeContext<'a, 'tcx> {
+    fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
         let def_id = DefId::decode(self)?;
         Ok(self.tcx().lookup_adt_def(def_id))
     }
@@ -557,23 +557,22 @@ impl<'a, 'tcx> CrateMetadata {
     pub fn get_trait_def(&self,
                          item_id: DefIndex,
                          tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                         -> ty::TraitDef<'tcx> {
+                         -> ty::TraitDef {
         let data = match self.entry(item_id).kind {
             EntryKind::Trait(data) => data.decode(self),
             _ => bug!(),
         };
 
-        ty::TraitDef::new(data.unsafety,
+        ty::TraitDef::new(self.local_def_id(item_id),
+                          data.unsafety,
                           data.paren_sugar,
-                          tcx.item_generics(self.local_def_id(item_id)),
-                          data.trait_ref.decode((self, tcx)),
                           self.def_path(item_id).unwrap().deterministic_hash(tcx))
     }
 
     fn get_variant(&self,
                    item: &Entry<'tcx>,
                    index: DefIndex)
-                   -> (ty::VariantDefData<'tcx, 'tcx>, Option<DefIndex>) {
+                   -> (ty::VariantDef, Option<DefIndex>) {
         let data = match item.kind {
             EntryKind::Variant(data) |
             EntryKind::Struct(data) |
@@ -581,28 +580,26 @@ impl<'a, 'tcx> CrateMetadata {
             _ => bug!(),
         };
 
-        let fields = item.children
-            .decode(self)
-            .map(|index| {
+        (ty::VariantDef {
+            did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
+            name: self.item_name(item),
+            fields: item.children.decode(self).map(|index| {
                 let f = self.entry(index);
-                ty::FieldDefData::new(self.local_def_id(index), self.item_name(&f), f.visibility)
-            })
-            .collect();
-
-        (ty::VariantDefData {
-             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-             name: self.item_name(item),
-             fields: fields,
-             disr_val: ConstInt::Infer(data.disr),
-             ctor_kind: data.ctor_kind,
-         },
-         data.struct_ctor)
+                ty::FieldDef {
+                    did: self.local_def_id(index),
+                    name: self.item_name(&f),
+                    vis: f.visibility
+                }
+            }).collect(),
+            disr_val: ConstInt::Infer(data.disr),
+            ctor_kind: data.ctor_kind,
+        }, data.struct_ctor)
     }
 
     pub fn get_adt_def(&self,
                        item_id: DefIndex,
                        tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                       -> ty::AdtDefMaster<'tcx> {
+                       -> &'tcx ty::AdtDef {
         let item = self.entry(item_id);
         let did = self.local_def_id(item_id);
         let mut ctor_index = None;
@@ -627,26 +624,10 @@ impl<'a, 'tcx> CrateMetadata {
             _ => bug!("get_adt_def called on a non-ADT {:?}", did),
         };
 
-        let adt = tcx.intern_adt_def(did, kind, variants);
+        let adt = tcx.alloc_adt_def(did, kind, variants);
         if let Some(ctor_index) = ctor_index {
             // Make adt definition available through constructor id as well.
-            tcx.insert_adt_def(self.local_def_id(ctor_index), adt);
-        }
-
-        // this needs to be done *after* the variant is interned,
-        // to support recursive structures
-        for variant in &adt.variants {
-            for field in &variant.fields {
-                debug!("evaluating the type of {:?}::{:?}",
-                       variant.name,
-                       field.name);
-                let ty = self.get_type(field.did.index, tcx);
-                field.fulfill_ty(ty);
-                debug!("evaluating the type of {:?}::{:?}: {:?}",
-                       variant.name,
-                       field.name,
-                       ty);
-            }
+            tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt);
         }
 
         adt
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 6abc81d74dc..83904b24de3 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -736,7 +736,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     unsafety: trait_def.unsafety,
                     paren_sugar: trait_def.paren_sugar,
                     has_default_impl: tcx.trait_has_default_impl(def_id),
-                    trait_ref: self.lazy(&trait_def.trait_ref),
                     super_predicates: self.lazy(&tcx.item_super_predicates(def_id)),
                 };
 
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index c2acb2e0d70..00c3709435d 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -276,7 +276,6 @@ pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
     pub paren_sugar: bool,
     pub has_default_impl: bool,
-    pub trait_ref: Lazy<ty::TraitRef<'tcx>>,
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 786299c370d..e06d940de7e 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -301,7 +301,7 @@ pub struct MatchPair<'pat, 'tcx:'pat> {
 enum TestKind<'tcx> {
     // test the branches of enum
     Switch {
-        adt_def: AdtDef<'tcx>,
+        adt_def: &'tcx AdtDef,
         variants: BitVector,
     },
 
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 948ba7338cd..cb449037aeb 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -615,7 +615,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     fn candidate_after_variant_switch<'pat>(&mut self,
                                             match_pair_index: usize,
-                                            adt_def: ty::AdtDef<'tcx>,
+                                            adt_def: &'tcx ty::AdtDef,
                                             variant_index: usize,
                                             subpatterns: &'pat [FieldPattern<'tcx>],
                                             candidate: &Candidate<'pat, 'tcx>)
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 94bf8936fe6..e850f6c4b04 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -1003,7 +1003,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 }
 
 /// Converts a list of named fields (i.e. for struct-like struct/enum ADTs) into FieldExprRef.
-fn field_refs<'tcx>(variant: VariantDef<'tcx>,
+fn field_refs<'tcx>(variant: &'tcx VariantDef,
                     fields: &'tcx [hir::Field])
                     -> Vec<FieldExprRef<'tcx>>
 {
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 32639cc3f86..e7a6b40c830 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -155,11 +155,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
-    pub fn num_variants(&mut self, adt_def: ty::AdtDef) -> usize {
+    pub fn num_variants(&mut self, adt_def: &ty::AdtDef) -> usize {
         adt_def.variants.len()
     }
 
-    pub fn all_fields(&mut self, adt_def: ty::AdtDef, variant_index: usize) -> Vec<Field> {
+    pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: usize) -> Vec<Field> {
         (0..adt_def.variants[variant_index].fields.len())
             .map(Field::new)
             .collect()
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 50eee772396..22c07f1903b 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -221,7 +221,7 @@ pub enum ExprKind<'tcx> {
         fields: Vec<ExprRef<'tcx>>,
     },
     Adt {
-        adt_def: AdtDef<'tcx>,
+        adt_def: &'tcx AdtDef,
         variant_index: usize,
         substs: &'tcx Substs<'tcx>,
         fields: Vec<FieldExprRef<'tcx>>,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 1071203af2b..145b9176f6b 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -405,7 +405,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
     }
 
     // Checks that a field is in scope.
-    fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
+    fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
         if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
             struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
                       field.name, def.variant_descr(), self.tcx.item_path_str(def.did))
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index c3b1649662a..4cd28e0a46d 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -941,7 +941,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                           ex: &ast::Expr,
                           path: &ast::Path,
                           fields: &Vec<ast::Field>,
-                          variant: ty::VariantDef,
+                          variant: &ty::VariantDef,
                           base: &Option<P<ast::Expr>>) {
         self.write_sub_paths_truncated(path, false);
 
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 7a2b74c06db..33b9f8c9034 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -621,7 +621,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     pub fn get_field_ref_data(&self,
                               field_ref: &ast::Field,
-                              variant: ty::VariantDef,
+                              variant: &ty::VariantDef,
                               parent: NodeId)
                               -> Option<VariableRefData> {
         let f = variant.field_named(field_ref.ident.node.name);
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 7416b86bfeb..087fe4decbf 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -803,9 +803,10 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         }
         ty::TyAdt(adt_def, substs) => {
             for field in adt_def.all_fields() {
+                let field_type = scx.tcx().item_type(field.did);
                 let field_type = monomorphize::apply_param_substs(scx,
                                                                   substs,
-                                                                  &field.unsubst_ty());
+                                                                  &field_type);
                 let field_type = glue::get_drop_glue_type(scx.tcx(), field_type);
 
                 if glue::type_needs_drop(scx.tcx(), field_type) {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 8bbe50af065..df0e1f1fc05 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -882,7 +882,7 @@ impl<'tcx> MemberDescriptionFactory<'tcx> {
 
 // Creates MemberDescriptions for the fields of a struct
 struct StructMemberDescriptionFactory<'tcx> {
-    variant: ty::VariantDef<'tcx>,
+    variant: &'tcx ty::VariantDef,
     substs: &'tcx Substs<'tcx>,
     is_simd: bool,
     span: Span,
@@ -1024,7 +1024,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 //=-----------------------------------------------------------------------------
 
 struct UnionMemberDescriptionFactory<'tcx> {
-    variant: ty::VariantDef<'tcx>,
+    variant: &'tcx ty::VariantDef,
     substs: &'tcx Substs<'tcx>,
     span: Span,
 }
@@ -1338,7 +1338,7 @@ enum EnumDiscriminantInfo {
 fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    enum_type: Ty<'tcx>,
                                    struct_def: &layout::Struct,
-                                   variant: ty::VariantDef<'tcx>,
+                                   variant: &'tcx ty::VariantDef,
                                    discriminant_info: EnumDiscriminantInfo,
                                    containing_scope: DIScope,
                                    span: Span)
@@ -1357,7 +1357,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ref l @ _ => bug!("This should be unreachable. Type is {:#?} layout is {:#?}", enum_type, l)
     };
 
-    let mut field_tys = variant.fields.iter().map(|f: ty::FieldDef<'tcx>| {
+    let mut field_tys = variant.fields.iter().map(|f| {
         monomorphize::field_ty(cx.tcx(), &substs, f)
     }).collect::<Vec<_>>();
 
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 06d0b1e1982..90bc29c39e9 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -504,7 +504,7 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     fn iter_variant<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                 t: Ty<'tcx>,
                                 av: adt::MaybeSizedValue,
-                                variant: ty::VariantDef<'tcx>,
+                                variant: &'tcx ty::VariantDef,
                                 substs: &Substs<'tcx>)
                                 -> Block<'blk, 'tcx> {
         let _icx = push_ctxt("iter_variant");
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 270ce79620f..8f05cc793ef 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -60,7 +60,7 @@ pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>,
 /// Returns the normalized type of a struct field
 pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           param_substs: &Substs<'tcx>,
-                          f: ty::FieldDef<'tcx>)
+                          f: &'tcx ty::FieldDef)
                           -> Ty<'tcx>
 {
     tcx.normalize_associated_type(&f.ty(tcx, param_substs))
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 032ad6efe1f..7d2019280e3 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -93,7 +93,7 @@ pub trait AstConv<'gcx, 'tcx> {
     /// Returns the `TraitDef` for a given trait. This allows you to
     /// figure out the set of type parameters defined on the trait.
     fn get_trait_def(&self, span: Span, id: DefId)
-                     -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>;
+                     -> Result<&'tcx ty::TraitDef, ErrorReported>;
 
     /// Ensure that the super-predicates for the trait with the given
     /// id are available and also for the transitive set of
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 6e2b42881a7..15f383c5787 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -626,7 +626,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                adt_ty: Ty<'tcx>,
                                pat_id: ast::NodeId,
                                span: Span,
-                               variant: ty::VariantDef<'tcx>,
+                               variant: &'tcx ty::VariantDef,
                                fields: &'gcx [Spanned<hir::FieldPat>],
                                etc: bool) {
         let tcx = self.tcx;
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 1a5dfc8797e..e13c4ea314f 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -589,7 +589,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 //
 // then revises input: `Foo<'r,i64,&'r i64>` to: `Foo<'static,i64,()>`
 fn revise_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                  adt_def: ty::AdtDef<'tcx>,
+                                  adt_def: &'tcx ty::AdtDef,
                                   impl_def_id: DefId,
                                   substs: &Substs<'tcx>)
                                   -> Ty<'tcx> {
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index f2dcc174d55..2e66f6290a0 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -192,13 +192,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                m_name,
                trait_def_id);
 
-        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() - 1, input_types.len());
-        }
-        assert!(trait_def.generics.regions.is_empty());
-
         // Construct a trait-reference `self_ty : Trait<input_tys>`
         let substs = Substs::for_item(self.tcx,
                                       trait_def_id,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 8d51f52e998..1099d5b060e 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1041,7 +1041,7 @@ fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                           trait_def: &ty::TraitDef<'tcx>,
+                                           trait_def: &ty::TraitDef,
                                            impl_id: DefId,
                                            impl_item: &hir::ImplItem)
 {
@@ -1401,7 +1401,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn get_trait_def(&self, _: Span, id: DefId)
-                     -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
+                     -> Result<&'tcx ty::TraitDef, ErrorReported>
     {
         Ok(self.tcx().lookup_trait_def(id))
     }
@@ -1987,7 +1987,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     // Indifferent to privacy flags
     pub fn field_ty(&self,
                     span: Span,
-                    field: ty::FieldDef<'tcx>,
+                    field: &'tcx ty::FieldDef,
                     substs: &Substs<'tcx>)
                     -> Ty<'tcx>
     {
@@ -3073,7 +3073,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     // Return an hint about the closest match in field names
-    fn suggest_field_name(variant: ty::VariantDef<'tcx>,
+    fn suggest_field_name(variant: &'tcx ty::VariantDef,
                           field: &Spanned<ast::Name>,
                           skip : Vec<InternedString>)
                           -> Option<Symbol> {
@@ -3166,7 +3166,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     fn report_unknown_field(&self,
                             ty: Ty<'tcx>,
-                            variant: ty::VariantDef<'tcx>,
+                            variant: &'tcx ty::VariantDef,
                             field: &hir::Field,
                             skip_fields: &[hir::Field],
                             kind_name: &str) {
@@ -3210,7 +3210,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 adt_ty: Ty<'tcx>,
                                 expr_id: ast::NodeId,
                                 span: Span,
-                                variant: ty::VariantDef<'tcx>,
+                                variant: &'tcx ty::VariantDef,
                                 ast_fields: &'gcx [hir::Field],
                                 check_completeness: bool) {
         let tcx = self.tcx;
@@ -3326,7 +3326,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn check_struct_path(&self,
                              qpath: &hir::QPath,
                              node_id: ast::NodeId)
-                             -> Option<(ty::VariantDef<'tcx>,  Ty<'tcx>)> {
+                             -> Option<(&'tcx ty::VariantDef,  Ty<'tcx>)> {
         let path_span = match *qpath {
             hir::QPath::Resolved(_, ref path) => path.span,
             hir::QPath::TypeRelative(ref qself, _) => qself.span
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index b041fb41abf..7870b3677d0 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -285,12 +285,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
                 }
             });
 
-        let trait_def = self.tcx().lookup_trait_def(trait_def_id);
-
-        let has_ty_params =
-            trait_def.generics
-                      .types
-                      .len() > 1;
+        let has_ty_params = self.tcx().item_generics(trait_def_id).types.len() > 1;
 
         // We use an if-else here, since the generics will also trigger
         // an extraneous error message when we find predicates like
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 30472f85db1..f575d4d8bab 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -395,7 +395,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
                             .filter_map(|(i, f)| {
                                 let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
 
-                                if f.unsubst_ty().is_phantom_data() {
+                                if tcx.item_type(f.did).is_phantom_data() {
                                     // Ignore PhantomData fields
                                     return None;
                                 }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index cbe0a1c4bf3..3bb7d6a77ba 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -329,20 +329,21 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
     }
 
     /// Loads the trait def for a given trait, returning ErrorReported if a cycle arises.
-    fn get_trait_def(&self, trait_id: DefId)
-                     -> &'tcx ty::TraitDef<'tcx>
+    fn get_trait_def(&self, def_id: DefId)
+                     -> &'tcx ty::TraitDef
     {
         let tcx = self.tcx;
 
-        if let Some(trait_id) = tcx.map.as_local_node_id(trait_id) {
+        if let Some(trait_id) = tcx.map.as_local_node_id(def_id) {
             let item = match tcx.map.get(trait_id) {
                 hir_map::NodeItem(item) => item,
                 _ => bug!("get_trait_def({:?}): not an item", trait_id)
             };
 
+            generics_of_def_id(self, def_id);
             trait_def_of_item(self, &item)
         } else {
-            tcx.lookup_trait_def(trait_id)
+            tcx.lookup_trait_def(def_id)
         }
     }
 
@@ -392,7 +393,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
     }
 
     fn get_trait_def(&self, span: Span, id: DefId)
-                     -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
+                     -> Result<&'tcx ty::TraitDef, ErrorReported>
     {
         self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
             Ok(self.ccx.get_trait_def(id))
@@ -616,10 +617,10 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            struct_generics: &'tcx ty::Generics<'tcx>,
                            struct_predicates: &ty::GenericPredicates<'tcx>,
                            field: &hir::StructField,
-                           ty_f: ty::FieldDefMaster<'tcx>)
+                           ty_f: &'tcx ty::FieldDef)
 {
     let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &field.ty);
-    ty_f.fulfill_ty(tt);
+    ccx.tcx.item_types.borrow_mut().insert(ty_f.did, tt);
 
     let def_id = ccx.tcx.map.local_def_id(field.id);
     ccx.tcx.item_types.borrow_mut().insert(def_id, tt);
@@ -716,6 +717,7 @@ fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
 fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
     let tcx = ccx.tcx;
     debug!("convert: item {} with id {}", it.name, it.id);
+    let def_id = ccx.tcx.map.local_def_id(it.id);
     match it.node {
         // These don't define types.
         hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => {
@@ -726,12 +728,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             }
         }
         hir::ItemEnum(ref enum_definition, _) => {
-            let def_id = ccx.tcx.map.local_def_id(it.id);
             let ty = type_of_def_id(ccx, def_id);
             let generics = generics_of_def_id(ccx, def_id);
             let predicates = predicates_of_item(ccx, it);
             convert_enum_variant_types(ccx,
-                                       tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)),
+                                       tcx.lookup_adt_def(ccx.tcx.map.local_def_id(it.id)),
                                        ty,
                                        generics,
                                        predicates,
@@ -756,7 +757,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                       _) => {
             // Create generics from the generics specified in the impl head.
             debug!("convert: ast_generics={:?}", generics);
-            let def_id = ccx.tcx.map.local_def_id(it.id);
             generics_of_def_id(ccx, def_id);
             let mut ty_predicates =
                 ty_generic_predicates(ccx, generics, None, vec![], false);
@@ -786,8 +786,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone());
         },
         hir::ItemTrait(.., ref trait_items) => {
-            let trait_def = trait_def_of_item(ccx, it);
-            let def_id = trait_def.trait_ref.def_id;
+            generics_of_def_id(ccx, def_id);
+            trait_def_of_item(ccx, it);
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
                 ccx.ensure_super_predicates(it.span, def_id);
             convert_trait_predicates(ccx, it);
@@ -838,12 +838,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         },
         hir::ItemStruct(ref struct_def, _) |
         hir::ItemUnion(ref struct_def, _) => {
-            let def_id = ccx.tcx.map.local_def_id(it.id);
             let ty = type_of_def_id(ccx, def_id);
             let generics = generics_of_def_id(ccx, def_id);
             let predicates = predicates_of_item(ccx, it);
 
-            let variant = tcx.lookup_adt_def_master(def_id).struct_variant();
+            let variant = tcx.lookup_adt_def(def_id).struct_variant();
 
             for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) {
                 convert_field(ccx, generics, &predicates, f, ty_f)
@@ -855,13 +854,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         },
         hir::ItemTy(_, ref generics) => {
             ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
-            let def_id = ccx.tcx.map.local_def_id(it.id);
             type_of_def_id(ccx, def_id);
             generics_of_def_id(ccx, def_id);
             predicates_of_item(ccx, it);
         },
         _ => {
-            let def_id = ccx.tcx.map.local_def_id(it.id);
             type_of_def_id(ccx, def_id);
             generics_of_def_id(ccx, def_id);
             predicates_of_item(ccx, it);
@@ -914,7 +911,7 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
 
 fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                   ctor_id: ast::NodeId,
-                                  variant: ty::VariantDef<'tcx>,
+                                  variant: &'tcx ty::VariantDef,
                                   ty: Ty<'tcx>,
                                   predicates: ty::GenericPredicates<'tcx>) {
     let tcx = ccx.tcx;
@@ -926,7 +923,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             let inputs: Vec<_> =
                 variant.fields
                 .iter()
-                .map(|field| field.unsubst_ty())
+                .map(|field| tcx.item_type(field.did))
                 .collect();
             let substs = mk_item_substs(&ccx.icx(&predicates),
                                         ccx.tcx.map.span(ctor_id), def_id);
@@ -946,7 +943,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 }
 
 fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                        def: ty::AdtDefMaster<'tcx>,
+                                        def: &'tcx ty::AdtDef,
                                         ty: Ty<'tcx>,
                                         generics: &'tcx ty::Generics<'tcx>,
                                         predicates: ty::GenericPredicates<'tcx>,
@@ -974,7 +971,7 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     name: ast::Name,
                                     disr_val: ty::Disr,
                                     def: &hir::VariantData)
-                                    -> ty::VariantDefData<'tcx, 'tcx> {
+                                    -> ty::VariantDef {
     let mut seen_fields: FxHashMap<ast::Name, Span> = FxHashMap();
     let node_id = ccx.tcx.map.as_local_node_id(did).unwrap();
     let fields = def.fields().iter().map(|f| {
@@ -991,10 +988,13 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             seen_fields.insert(f.name, f.span);
         }
 
-        ty::FieldDefData::new(fid, f.name,
-            ty::Visibility::from_hir(&f.vis, node_id, ccx.tcx))
+        ty::FieldDef {
+            did: fid,
+            name: f.name,
+            vis: ty::Visibility::from_hir(&f.vis, node_id, ccx.tcx)
+        }
     }).collect();
-    ty::VariantDefData {
+    ty::VariantDef {
         did: did,
         name: name,
         disr_val: disr_val,
@@ -1006,29 +1006,34 @@ fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 it: &hir::Item,
                                 def: &hir::VariantData)
-                                -> ty::AdtDefMaster<'tcx>
+                                -> &'tcx ty::AdtDef
 {
     let did = ccx.tcx.map.local_def_id(it.id);
     // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
     let ctor_id = if !def.is_struct() { Some(ccx.tcx.map.local_def_id(def.id())) } else { None };
     let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
                                                ConstInt::Infer(0), def)];
-    let adt = ccx.tcx.intern_adt_def(did, AdtKind::Struct, variants);
+    let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants);
     if let Some(ctor_id) = ctor_id {
         // Make adt definition available through constructor id as well.
-        ccx.tcx.insert_adt_def(ctor_id, adt);
+        ccx.tcx.adt_defs.borrow_mut().insert(ctor_id, adt);
     }
+
+    ccx.tcx.adt_defs.borrow_mut().insert(did, adt);
     adt
 }
 
 fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 it: &hir::Item,
                                 def: &hir::VariantData)
-                                -> ty::AdtDefMaster<'tcx>
+                                -> &'tcx ty::AdtDef
 {
     let did = ccx.tcx.map.local_def_id(it.id);
     let variants = vec![convert_struct_variant(ccx, did, it.name, ConstInt::Infer(0), def)];
-    ccx.tcx.intern_adt_def(did, AdtKind::Union, variants)
+
+    let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants);
+    ccx.tcx.adt_defs.borrow_mut().insert(did, adt);
+    adt
 }
 
     fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
@@ -1082,7 +1087,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               it: &hir::Item,
                               def: &hir::EnumDef)
-                              -> ty::AdtDefMaster<'tcx>
+                              -> &'tcx ty::AdtDef
 {
     let tcx = ccx.tcx;
     let did = tcx.map.local_def_id(it.id);
@@ -1110,7 +1115,10 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         let did = tcx.map.local_def_id(v.node.data.id());
         convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data)
     }).collect();
-    tcx.intern_adt_def(tcx.map.local_def_id(it.id), AdtKind::Enum, variants)
+
+    let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants);
+    tcx.adt_defs.borrow_mut().insert(did, adt);
+    adt
 }
 
 /// Ensures that the super-predicates of the trait with def-id
@@ -1155,10 +1163,15 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
         // In-scope when converting the superbounds for `Trait` are
         // that `Self:Trait` as well as any bounds that appear on the
         // generic types:
-        let trait_def = trait_def_of_item(ccx, item);
+        generics_of_def_id(ccx, trait_def_id);
+        trait_def_of_item(ccx, item);
+        let trait_ref = ty::TraitRef {
+            def_id: trait_def_id,
+            substs: Substs::identity_for_item(tcx, trait_def_id)
+        };
         let self_predicate = ty::GenericPredicates {
             parent: None,
-            predicates: vec![trait_def.trait_ref.to_predicate()]
+            predicates: vec![trait_ref.to_predicate()]
         };
         let scope = &(generics, &self_predicate);
 
@@ -1203,54 +1216,41 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
     def_ids
 }
 
-fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                               it: &hir::Item)
-                               -> &'tcx ty::TraitDef<'tcx>
-{
+fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef {
     let def_id = ccx.tcx.map.local_def_id(it.id);
     let tcx = ccx.tcx;
 
-    if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
-        return def.clone();
-    }
+    tcx.trait_defs.memoize(def_id, || {
+        let unsafety = match it.node {
+            hir::ItemTrait(unsafety, ..) => unsafety,
+            _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"),
+        };
 
-    let (unsafety, generics) = match it.node {
-        hir::ItemTrait(unsafety, ref generics, _, _) => {
-            (unsafety, generics)
+        let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
+        if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
+            let mut err = ccx.tcx.sess.struct_span_err(
+                it.span,
+                "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
+                which traits can use parenthetical notation");
+            help!(&mut err,
+                "add `#![feature(unboxed_closures)]` to \
+                the crate attributes to use it");
+            err.emit();
         }
-        _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"),
-    };
 
-    let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
-    if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
-        let mut err = ccx.tcx.sess.struct_span_err(
-            it.span,
-            "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \
-             which traits can use parenthetical notation");
-        help!(&mut err,
-            "add `#![feature(unboxed_closures)]` to \
-             the crate attributes to use it");
-        err.emit();
-    }
-
-    let ty_generics = generics_of_def_id(ccx, def_id);
-    let substs = mk_item_substs(&ccx.icx(generics), it.span, def_id);
-
-    let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx);
-
-    let trait_ref = ty::TraitRef::new(def_id, substs);
-    let trait_def = ty::TraitDef::new(unsafety, paren_sugar, ty_generics, trait_ref,
-                                      def_path_hash);
-
-    tcx.intern_trait_def(trait_def)
+        let def_path_hash = tcx.def_path(def_id).deterministic_hash(tcx);
+        tcx.alloc_trait_def(ty::TraitDef::new(def_id, unsafety, paren_sugar, def_path_hash))
+    })
 }
 
 fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) {
     let tcx = ccx.tcx;
-    let trait_def = trait_def_of_item(ccx, it);
 
     let def_id = ccx.tcx.map.local_def_id(it.id);
 
+    generics_of_def_id(ccx, def_id);
+    trait_def_of_item(ccx, it);
+
     let (generics, items) = match it.node {
         hir::ItemTrait(_, ref generics, _, ref items) => (generics, items),
         ref s => {
@@ -1272,7 +1272,11 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
 
     // Add in a predicate that `Self:Trait` (where `Trait` is the
     // current trait).  This is needed for builtin bounds.
-    let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate();
+    let trait_ref = ty::TraitRef {
+        def_id: def_id,
+        substs: Substs::identity_for_item(tcx, def_id)
+    };
+    let self_predicate = trait_ref.to_poly_trait_ref().to_predicate();
     base_predicates.push(self_predicate);
 
     // add in the explicit where-clauses
@@ -1282,7 +1286,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
     let assoc_predicates = predicates_for_associated_types(ccx,
                                                            generics,
                                                            &trait_predicates,
-                                                           trait_def.trait_ref,
+                                                           trait_ref,
                                                            items);
     trait_predicates.predicates.extend(assoc_predicates);
 
@@ -1581,7 +1585,10 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
                 ccx.tcx.mk_closure(def_id, Substs::for_item(
                     ccx.tcx, def_id,
-                    |def, _| ccx.tcx.mk_region(def.to_early_bound_region()),
+                    |def, _| {
+                        let region = def.to_early_bound_region_data();
+                        ccx.tcx.mk_region(ty::ReEarlyBound(region))
+                    },
                     |def, _| ccx.tcx.mk_param_from_def(def)
                 ))
             }
@@ -2096,7 +2103,5 @@ pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
         bug!("ErrorReported returned, but no errors reports?")
     }
 
-    Substs::for_item(tcx, def_id,
-                     |def, _| tcx.mk_region(def.to_early_bound_region()),
-                     |def, _| tcx.mk_param_from_def(def))
+    Substs::identity_for_item(tcx, def_id)
 }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index f34753c227d..ded9df25d5c 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -92,14 +92,18 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
 
                 for field in tcx.lookup_adt_def(did).all_fields() {
                     self.add_constraints_from_ty(generics,
-                                                 field.unsubst_ty(),
+                                                 tcx.item_type(field.did),
                                                  self.covariant);
                 }
             }
             hir::ItemTrait(..) => {
-                let trait_def = tcx.lookup_trait_def(did);
-                self.add_constraints_from_trait_ref(&trait_def.generics,
-                                                    trait_def.trait_ref,
+                let generics = tcx.item_generics(did);
+                let trait_ref = ty::TraitRef {
+                    def_id: did,
+                    substs: Substs::identity_for_item(tcx, did)
+                };
+                self.add_constraints_from_trait_ref(generics,
+                                                    trait_ref,
                                                     self.invariant);
             }
 
@@ -279,7 +283,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                trait_ref,
                variance);
 
-        let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
+        let trait_generics = self.tcx().item_generics(trait_ref.def_id);
 
         // This edge is actually implied by the call to
         // `lookup_trait_def`, but I'm trying to be future-proof. See
@@ -288,8 +292,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
         self.add_constraints_from_substs(generics,
                                          trait_ref.def_id,
-                                         &trait_def.generics.types,
-                                         &trait_def.generics.regions,
+                                         &trait_generics.types,
+                                         &trait_generics.regions,
                                          trait_ref.substs,
                                          variance);
     }
@@ -356,7 +360,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::TyProjection(ref data) => {
                 let trait_ref = &data.trait_ref;
-                let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
+                let trait_generics = self.tcx().item_generics(trait_ref.def_id);
 
                 // This edge is actually implied by the call to
                 // `lookup_trait_def`, but I'm trying to be future-proof. See
@@ -365,8 +369,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
                 self.add_constraints_from_substs(generics,
                                                  trait_ref.def_id,
-                                                 &trait_def.generics.types,
-                                                 &trait_def.generics.regions,
+                                                 &trait_generics.types,
+                                                 &trait_generics.regions,
                                                  trait_ref.substs,
                                                  variance);
             }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index bf739abe3da..94e9fdbfc3e 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -151,14 +151,13 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
 }
 
 pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
-    let def = cx.tcx.lookup_trait_def(did);
     let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect();
     let predicates = cx.tcx.item_predicates(did);
-    let generics = (def.generics, &predicates).clean(cx);
+    let generics = (cx.tcx.item_generics(did), &predicates).clean(cx);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
     clean::Trait {
-        unsafety: def.unsafety,
+        unsafety: cx.tcx.lookup_trait_def(did).unsafety,
         generics: generics,
         items: trait_items,
         bounds: supertrait_bounds,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7f8be4d6331..bc8472bb6b7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1395,9 +1395,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
                     // are actually located on the trait/impl itself, so we need to load
                     // all of the generics from there and then look for bounds that are
                     // applied to this associated type in question.
-                    let def = cx.tcx.lookup_trait_def(did);
                     let predicates = cx.tcx.item_predicates(did);
-                    let generics = (def.generics, &predicates).clean(cx);
+                    let generics = (cx.tcx.item_generics(did), &predicates).clean(cx);
                     generics.where_predicates.iter().filter_map(|pred| {
                         let (name, self_type, trait_, bounds) = match *pred {
                             WherePredicate::BoundPredicate {
@@ -1927,7 +1926,7 @@ impl Clean<Item> for hir::StructField {
     }
 }
 
-impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
+impl<'tcx> Clean<Item> for ty::FieldDef {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
             name: Some(self.name).clean(cx),
@@ -1937,7 +1936,7 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
             stability: get_stability(cx, self.did),
             deprecation: get_deprecation(cx, self.did),
             def_id: self.did,
-            inner: StructFieldItem(self.unsubst_ty().clean(cx)),
+            inner: StructFieldItem(cx.tcx.item_type(self.did).clean(cx)),
         }
     }
 }
@@ -2084,13 +2083,13 @@ impl Clean<Item> for doctree::Variant {
     }
 }
 
-impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
+impl<'tcx> Clean<Item> for ty::VariantDef {
     fn clean(&self, cx: &DocContext) -> Item {
         let kind = match self.ctor_kind {
             CtorKind::Const => VariantKind::CLike,
             CtorKind::Fn => {
                 VariantKind::Tuple(
-                    self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
+                    self.fields.iter().map(|f| cx.tcx.item_type(f.did).clean(cx)).collect()
                 )
             }
             CtorKind::Fictive => {
@@ -2106,7 +2105,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
                             def_id: field.did,
                             stability: get_stability(cx, field.did),
                             deprecation: get_deprecation(cx, field.did),
-                            inner: StructFieldItem(field.unsubst_ty().clean(cx))
+                            inner: StructFieldItem(cx.tcx.item_type(field.did).clean(cx))
                         }
                     }).collect()
                 })