about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-05-26 12:15:30 +0000
committerbors <bors@rust-lang.org>2015-05-26 12:15:30 +0000
commitc654a07d29c77b5a023cb9d36dfc61811349f64e (patch)
tree4faa4a46234225d1a2aa9de818975f334ff3037c
parent8a872943ff0fac763eefa52de1ffb1344e698d98 (diff)
parent0ec3183df8d0cdccc735fa6572d664b43dbb5e31 (diff)
downloadrust-c654a07d29c77b5a023cb9d36dfc61811349f64e.tar.gz
rust-c654a07d29c77b5a023cb9d36dfc61811349f64e.zip
Auto merge of #25785 - arielb1:cleanup-201505, r=eddyb
The caching essentially eliminates "stability checking" time (my attempt to clean-up junk got tangled up with stability, so I added the caching while I was at it).

r? @eddyb
-rw-r--r--src/librustc/metadata/common.rs2
-rw-r--r--src/librustc/metadata/csearch.rs23
-rw-r--r--src/librustc/metadata/decoder.rs29
-rw-r--r--src/librustc/metadata/encoder.rs9
-rw-r--r--src/librustc/middle/astencode.rs104
-rw-r--r--src/librustc/middle/stability.rs130
-rw-r--r--src/librustc/middle/ty.rs245
-rw-r--r--src/librustc/middle/ty_fold.rs21
-rw-r--r--src/librustc_driver/driver.rs2
-rw-r--r--src/librustc_lint/builtin.rs9
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/check/wf.rs3
-rw-r--r--src/librustc_typeck/check/writeback.rs23
-rw-r--r--src/librustc_typeck/coherence/mod.rs53
-rw-r--r--src/librustc_typeck/collect.rs21
-rw-r--r--src/librustdoc/clean/mod.rs15
-rw-r--r--src/librustdoc/visit_ast.rs3
-rw-r--r--src/libsyntax/attr.rs4
18 files changed, 210 insertions, 490 deletions
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 901afc1d190..5f785fefa12 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -146,7 +146,7 @@ enum_from_u32! {
         tag_table_closure_kinds = 0x65,
         tag_table_upvar_capture_map = 0x66,
         tag_table_capture_modes = 0x67,
-        tag_table_object_cast_map = 0x68,
+        // GAP 0x68
         tag_table_const_qualif = 0x69,
         tag_table_cast_kinds = 0x6a,
     }
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index f834076e8ea..47aad257d15 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -297,15 +297,6 @@ pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
     decoder::get_impl_trait(&*cdata, def.node, tcx)
 }
 
-// Given a def_id for an impl, return information about its vtables
-pub fn get_impl_vtables<'tcx>(tcx: &ty::ctxt<'tcx>,
-                              def: ast::DefId)
-                              -> ty::vtable_res<'tcx> {
-    let cstore = &tcx.sess.cstore;
-    let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_vtables(&*cdata, def.node, tcx)
-}
-
 pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
                             -> Vec<(cstore::NativeLibraryKind, String)> {
     let cdata = cstore.get_crate_data(crate_num);
@@ -389,6 +380,11 @@ pub fn is_const_fn(cstore: &cstore::CStore, did: ast::DefId) -> bool {
     decoder::is_const_fn(&*cdata, did.node)
 }
 
+pub fn is_impl(cstore: &cstore::CStore, did: ast::DefId) -> bool {
+    let cdata = cstore.get_crate_data(did.krate);
+    decoder::is_impl(&*cdata, did.node)
+}
+
 pub fn get_stability(cstore: &cstore::CStore,
                      def: ast::DefId)
                      -> Option<attr::Stability> {
@@ -396,8 +392,8 @@ pub fn get_stability(cstore: &cstore::CStore,
     decoder::get_stability(&*cdata, def.node)
 }
 
-pub fn is_staged_api(cstore: &cstore::CStore, def: ast::DefId) -> bool {
-    let cdata = cstore.get_crate_data(def.krate);
+pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
+    let cdata = cstore.get_crate_data(krate);
     let attrs = decoder::get_crate_attributes(cdata.data());
     for attr in &attrs {
         if &attr.name()[..] == "staged_api" {
@@ -414,11 +410,6 @@ pub fn get_repr_attrs(cstore: &cstore::CStore, def: ast::DefId)
     decoder::get_repr_attrs(&*cdata, def.node)
 }
 
-pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
-    let cdata = cstore.get_crate_data(def.krate);
-    decoder::is_associated_type(&*cdata, def.node)
-}
-
 pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: ast::DefId) -> bool {
     let cdata = cstore.get_crate_data(trait_def_id.krate);
     decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index ee5fd0202d6..42dcc9661ca 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -30,7 +30,6 @@ use middle::lang_items;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
 use middle::ty::{self, Ty};
-use middle::astencode::vtable_decoder_helpers;
 use util::nodemap::FnvHashMap;
 
 use std::cell::{Cell, RefCell};
@@ -522,18 +521,6 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
     }
 }
 
-pub fn get_impl_vtables<'tcx>(cdata: Cmd,
-                              id: ast::NodeId,
-                              tcx: &ty::ctxt<'tcx>)
-                              -> ty::vtable_res<'tcx>
-{
-    let item_doc = lookup_item(id, cdata.data());
-    let vtables_doc = reader::get_doc(item_doc, tag_item_impl_vtables);
-    let mut decoder = reader::Decoder::new(vtables_doc);
-    decoder.read_vtable_res(tcx, cdata)
-}
-
-
 pub fn get_symbol(data: &[u8], id: ast::NodeId) -> String {
     return item_symbol(lookup_item(id, data));
 }
@@ -1546,6 +1533,14 @@ pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
     }
 }
 
+pub fn is_impl(cdata: Cmd, id: ast::NodeId) -> bool {
+    let item_doc = lookup_item(id, cdata.data());
+    match item_family(item_doc) {
+        Impl => true,
+        _ => false,
+    }
+}
+
 fn doc_generics<'tcx>(base_doc: rbml::Doc,
                       tcx: &ty::ctxt<'tcx>,
                       cdata: Cmd,
@@ -1623,14 +1618,6 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
     ty::GenericPredicates { predicates: predicates }
 }
 
-pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
-    let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
-    match maybe_find_item(id, items) {
-        None => false,
-        Some(item) => item_sort(item) == Some('t'),
-    }
-}
-
 pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
     let trait_doc = lookup_item(trait_id, cdata.data());
     assert!(item_family(trait_doc) == Family::Trait);
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 88e0b739a0f..0908ffd249f 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -999,7 +999,7 @@ fn encode_extension_implementations(ecx: &EncodeContext,
     });
 }
 
-fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
+fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
     stab_opt.map(|stab| {
         rbml_w.start_tag(tag_items_data_item_stability);
         stab.encode(rbml_w).unwrap();
@@ -1215,11 +1215,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
           encode_name(rbml_w, item.ident.name);
           encode_unsafety(rbml_w, unsafety);
 
-          let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
+          let trait_ref = ty::impl_trait_ref(tcx, local_def(item.id)).unwrap();
           encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
           rbml_w.end_tag();
       }
-      ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
+      ast::ItemImpl(unsafety, polarity, _, _, ref ty, ref ast_items) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
         let impl_items = tcx.impl_items.borrow();
@@ -1269,8 +1269,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             rbml_w.end_tag();
         }
-        if opt_trait.is_some() {
-            let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
+        if let Some(trait_ref) = ty::impl_trait_ref(tcx, local_def(item.id)) {
             encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
         }
         encode_path(rbml_w, path.clone());
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index b7e57819b93..fda57c9dc61 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -696,19 +696,6 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
 pub trait vtable_decoder_helpers<'tcx> {
     fn read_vec_per_param_space<T, F>(&mut self, f: F) -> VecPerParamSpace<T> where
         F: FnMut(&mut Self) -> T;
-    fn read_vtable_res_with_key(&mut self,
-                                tcx: &ty::ctxt<'tcx>,
-                                cdata: &cstore::crate_metadata)
-                                -> (u32, ty::vtable_res<'tcx>);
-    fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                      -> ty::vtable_res<'tcx>;
-    fn read_vtable_param_res(&mut self,
-                       tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                      -> ty::vtable_param_res<'tcx>;
-    fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                          -> ty::vtable_origin<'tcx>;
 }
 
 impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
@@ -720,85 +707,6 @@ impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
         let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
         VecPerParamSpace::new(types, selfs, fns)
     }
-
-    fn read_vtable_res_with_key(&mut self,
-                                tcx: &ty::ctxt<'tcx>,
-                                cdata: &cstore::crate_metadata)
-                                -> (u32, ty::vtable_res<'tcx>) {
-        self.read_struct("VtableWithKey", 2, |this| {
-            let autoderef = this.read_struct_field("autoderef", 0, |this| {
-                Decodable::decode(this)
-            }).unwrap();
-            Ok((autoderef, this.read_struct_field("vtable_res", 1, |this| {
-                Ok(this.read_vtable_res(tcx, cdata))
-            }).unwrap()))
-        }).unwrap()
-    }
-
-    fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt<'tcx>,
-                       cdata: &cstore::crate_metadata)
-                       -> ty::vtable_res<'tcx>
-    {
-        self.read_vec_per_param_space(
-            |this| this.read_vtable_param_res(tcx, cdata))
-    }
-
-    fn read_vtable_param_res(&mut self,
-                             tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-                      -> ty::vtable_param_res<'tcx> {
-        self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
-             .unwrap().into_iter().collect()
-    }
-
-    fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt<'tcx>, cdata: &cstore::crate_metadata)
-        -> ty::vtable_origin<'tcx> {
-        self.read_enum("vtable_origin", |this| {
-            this.read_enum_variant(&["vtable_static",
-                                     "vtable_param",
-                                     "vtable_error",
-                                     "vtable_closure"],
-                                   |this, i| {
-                Ok(match i {
-                  0 => {
-                    ty::vtable_static(
-                        this.read_enum_variant_arg(0, |this| {
-                            Ok(this.read_def_id_nodcx(cdata))
-                        }).unwrap(),
-                        this.read_enum_variant_arg(1, |this| {
-                            Ok(this.read_substs_nodcx(tcx, cdata))
-                        }).unwrap(),
-                        this.read_enum_variant_arg(2, |this| {
-                            Ok(this.read_vtable_res(tcx, cdata))
-                        }).unwrap()
-                    )
-                  }
-                  1 => {
-                    ty::vtable_param(
-                        this.read_enum_variant_arg(0, |this| {
-                            Decodable::decode(this)
-                        }).unwrap(),
-                        this.read_enum_variant_arg(1, |this| {
-                            this.read_uint()
-                        }).unwrap()
-                    )
-                  }
-                  2 => {
-                    ty::vtable_closure(
-                        this.read_enum_variant_arg(0, |this| {
-                            Ok(this.read_def_id_nodcx(cdata))
-                        }).unwrap()
-                    )
-                  }
-                  3 => {
-                    ty::vtable_error
-                  }
-                  _ => panic!("bad enum variant")
-                })
-            })
-        }).unwrap()
-    }
 }
 
 // ___________________________________________________________________________
@@ -1209,13 +1117,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    if let Some(trait_ref) = tcx.object_cast_map.borrow().get(&id) {
-        rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_trait_ref(ecx, &trait_ref.0);
-        })
-    }
-
     if let Some(adjustment) = tcx.adjustments.borrow().get(&id) {
         match *adjustment {
             ty::AdjustDerefRef(ref adj) => {
@@ -1800,11 +1701,6 @@ fn decode_side_tables(dcx: &DecodeContext,
                         };
                         dcx.tcx.method_map.borrow_mut().insert(method_call, method);
                     }
-                    c::tag_table_object_cast_map => {
-                        let trait_ref = val_dsr.read_poly_trait_ref(dcx);
-                        dcx.tcx.object_cast_map.borrow_mut()
-                                               .insert(id, trait_ref);
-                    }
                     c::tag_table_adjustments => {
                         let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index d75dc861e83..b29e40d2d5e 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -23,46 +23,47 @@ use syntax::{attr, visit};
 use syntax::ast;
 use syntax::ast::{Attribute, Block, Crate, DefId, FnDecl, NodeId, Variant};
 use syntax::ast::{Item, Generics, StructField};
-use syntax::ast_util::is_local;
+use syntax::ast_util::{is_local, local_def};
 use syntax::attr::{Stability, AttrMetaMethods};
 use syntax::visit::{FnKind, Visitor};
 use syntax::feature_gate::emit_feature_err;
-use util::nodemap::{NodeMap, DefIdMap, FnvHashSet, FnvHashMap};
+use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 use util::ppaux::Repr;
 
 use std::mem::replace;
 
 /// A stability index, giving the stability level for items and methods.
-pub struct Index {
-    // Indicates whether this crate has #![feature(staged_api)]
-    staged_api: bool,
-    // stability for crate-local items; unmarked stability == no entry
-    local: NodeMap<Stability>,
-    // cache for extern-crate items; unmarked stability == entry with None
-    extern_cache: DefIdMap<Option<Stability>>
+pub struct Index<'tcx> {
+    /// This is mostly a cache, except the stabilities of local items
+    /// are filled by the annotator.
+    map: DefIdMap<Option<&'tcx Stability>>,
+
+    /// Maps for each crate whether it is part of the staged API.
+    staged_api: FnvHashMap<ast::CrateNum, bool>
 }
 
 // A private tree-walker for producing an Index.
-struct Annotator<'a> {
-    sess: &'a Session,
-    index: &'a mut Index,
-    parent: Option<Stability>,
+struct Annotator<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    index: &'a mut Index<'tcx>,
+    parent: Option<&'tcx Stability>,
     export_map: &'a PublicItems,
 }
 
-impl<'a> Annotator<'a> {
+impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
     // Determine the stability for a node based on its attributes and inherited
     // stability. The stability is recorded in the index and used as the parent.
     fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
                    attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
         F: FnOnce(&mut Annotator),
     {
-        if self.index.staged_api {
+        if self.index.staged_api[&ast::LOCAL_CRATE] {
             debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
-            match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) {
+            match attr::find_stability(self.tcx.sess.diagnostic(), attrs, item_sp) {
                 Some(stab) => {
                     debug!("annotate: found {:?}", stab);
-                    self.index.local.insert(id, stab.clone());
+                    let stab = self.tcx.intern_stability(stab);
+                    self.index.map.insert(local_def(id), Some(stab));
 
                     // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
                     if stab.level != attr::Stable {
@@ -77,13 +78,14 @@ impl<'a> Annotator<'a> {
                     debug!("annotate: not found, use_parent = {:?}, parent = {:?}",
                            use_parent, self.parent);
                     if use_parent {
-                        if let Some(stab) = self.parent.clone() {
-                            self.index.local.insert(id, stab);
-                        } else if self.index.staged_api && required
+                        if let Some(stab) = self.parent {
+                            self.index.map.insert(local_def(id), Some(stab));
+                        } else if self.index.staged_api[&ast::LOCAL_CRATE] && required
                             && self.export_map.contains(&id)
-                            && !self.sess.opts.test {
-                                self.sess.span_err(item_sp,
-                                                   "This node does not have a stability attribute");
+                            && !self.tcx.sess.opts.test {
+                                self.tcx.sess.span_err(item_sp,
+                                                       "This node does not \
+                                                        have a stability attribute");
                             }
                     }
                     f(self);
@@ -95,7 +97,7 @@ impl<'a> Annotator<'a> {
                 let tag = attr.name();
                 if tag == "unstable" || tag == "stable" || tag == "deprecated" {
                     attr::mark_used(attr);
-                    self.sess.span_err(attr.span(),
+                    self.tcx.sess.span_err(attr.span(),
                                        "stability attributes may not be used outside \
                                         of the standard library");
                 }
@@ -105,7 +107,7 @@ impl<'a> Annotator<'a> {
     }
 }
 
-impl<'a, 'v> Visitor<'v> for Annotator<'a> {
+impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
     fn visit_item(&mut self, i: &Item) {
         // FIXME (#18969): the following is a hack around the fact
         // that we cannot currently annotate the stability of
@@ -168,11 +170,11 @@ impl<'a, 'v> Visitor<'v> for Annotator<'a> {
     }
 }
 
-impl Index {
+impl<'tcx> Index<'tcx> {
     /// Construct the stability index for a crate being compiled.
-    pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems) {
+    pub fn build(&mut self, tcx: &ty::ctxt<'tcx>, krate: &Crate, export_map: &PublicItems) {
         let mut annotator = Annotator {
-            sess: sess,
+            tcx: tcx,
             index: self,
             parent: None,
             export_map: export_map,
@@ -182,22 +184,23 @@ impl Index {
     }
 
     pub fn new(krate: &Crate) -> Index {
-        let mut staged_api = false;
+        let mut is_staged_api = false;
         for attr in &krate.attrs {
             if &attr.name()[..] == "staged_api" {
                 match attr.node.value.node {
                     ast::MetaWord(_) => {
                         attr::mark_used(attr);
-                        staged_api = true;
+                        is_staged_api = true;
                     }
                     _ => (/*pass*/)
                 }
             }
         }
+        let mut staged_api = FnvHashMap();
+        staged_api.insert(ast::LOCAL_CRATE, is_staged_api);
         Index {
             staged_api: staged_api,
-            local: NodeMap(),
-            extern_cache: DefIdMap()
+            map: DefIdMap(),
         }
     }
 }
@@ -232,13 +235,13 @@ struct Checker<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> Checker<'a, 'tcx> {
-    fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<Stability>) {
+    fn check(&mut self, id: ast::DefId, span: Span, stab: &Option<&Stability>) {
         // Only the cross-crate scenario matters when checking unstable APIs
         let cross_crate = !is_local(id);
         if !cross_crate { return }
 
         match *stab {
-            Some(Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
+            Some(&Stability { level: attr::Unstable, ref feature, ref reason, .. }) => {
                 self.used_features.insert(feature.clone(), attr::Unstable);
 
                 if !self.active_features.contains(feature) {
@@ -252,7 +255,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                                       &feature, span, &msg);
                 }
             }
-            Some(Stability { level, ref feature, .. }) => {
+            Some(&Stability { level, ref feature, .. }) => {
                 self.used_features.insert(feature.clone(), level);
 
                 // Stable APIs are always ok to call and deprecated APIs are
@@ -312,7 +315,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
 
 /// Helper for discovering nodes to check for stability
 pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
-                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                  cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     match item.node {
         ast::ItemExternCrate(_) => {
             // compiler-generated `extern crate` items have a dummy span.
@@ -349,7 +352,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
 
 /// Helper for discovering nodes to check for stability
 pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
-                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                  cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     let span;
     let id = match e.node {
         ast::ExprMethodCall(i, _, _) => {
@@ -458,7 +461,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
 }
 
 pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
-                  cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                  cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         Some(def::DefPrimTy(..)) => {}
         Some(def) => {
@@ -470,7 +473,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
 }
 
 pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
-                 cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                 cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     debug!("check_pat(pat = {:?})", pat);
     if is_internal(tcx, pat.span) { return; }
 
@@ -511,7 +514,7 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
 }
 
 fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
-                            cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+                            cb: &mut FnMut(ast::DefId, Span, &Option<&Stability>)) {
     if !is_staged_api(tcx, id) { return  }
     if is_internal(tcx, span) { return }
     let ref stability = lookup(tcx, id);
@@ -528,20 +531,27 @@ fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
             if trait_method_id != id => {
                 is_staged_api(tcx, trait_method_id)
             }
-        _ if is_local(id) => {
-            tcx.stability.borrow().staged_api
-        }
         _ => {
-            csearch::is_staged_api(&tcx.sess.cstore, id)
+            *tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with(
+                || csearch::is_staged_api(&tcx.sess.cstore, id.krate))
         }
     }
 }
 
 /// Lookup the stability for a node, loading external crate
 /// metadata as necessary.
-pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
-    debug!("lookup(id={})",
-           id.repr(tcx));
+pub fn lookup<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
+    if let Some(st) = tcx.stability.borrow().map.get(&id) {
+        return *st;
+    }
+
+    let st = lookup_uncached(tcx, id);
+    tcx.stability.borrow_mut().map.insert(id, st);
+    st
+}
+
+fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
+    debug!("lookup(id={})", id.repr(tcx));
 
     // is this definition the implementation of a trait method?
     match ty::trait_item_of_item(tcx, id) {
@@ -553,25 +563,23 @@ pub fn lookup(tcx: &ty::ctxt, id: DefId) -> Option<Stability> {
     }
 
     let item_stab = if is_local(id) {
-        tcx.stability.borrow().local.get(&id.node).cloned()
+        None // The stability cache is filled partially lazily
     } else {
-        let stab = csearch::get_stability(&tcx.sess.cstore, id);
-        let mut index = tcx.stability.borrow_mut();
-        (*index).extern_cache.insert(id, stab.clone());
-        stab
+        csearch::get_stability(&tcx.sess.cstore, id).map(|st| tcx.intern_stability(st))
     };
 
     item_stab.or_else(|| {
-        if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
-            // FIXME (#18969): for the time being, simply use the
-            // stability of the trait to determine the stability of any
-            // unmarked impls for it. See FIXME above for more details.
-
-            debug!("lookup: trait_id={:?}", trait_id);
-            lookup(tcx, trait_id)
-        } else {
-            None
+        if ty::is_impl(tcx, id) {
+            if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
+                // FIXME (#18969): for the time being, simply use the
+                // stability of the trait to determine the stability of any
+                // unmarked impls for it. See FIXME above for more details.
+
+                debug!("lookup: trait_id={:?}", trait_id);
+                return lookup(tcx, trait_id);
+            }
         }
+        None
     })
 }
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 5ff6ee3c8b0..2ccbb0c5c10 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -32,7 +32,6 @@ pub use self::ImplOrTraitItem::*;
 pub use self::BoundRegion::*;
 pub use self::sty::*;
 pub use self::IntVarValue::*;
-pub use self::vtable_origin::*;
 pub use self::MethodOrigin::*;
 pub use self::CopyImplementationError::*;
 
@@ -402,12 +401,6 @@ pub enum CustomCoerceUnsized {
     Struct(usize)
 }
 
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Debug)]
-pub struct param_index {
-    pub space: subst::ParamSpace,
-    pub index: usize
-}
-
 #[derive(Clone, Debug)]
 pub enum MethodOrigin<'tcx> {
     // fully statically resolved method
@@ -510,50 +503,6 @@ impl MethodCall {
 // of the method to be invoked
 pub type MethodMap<'tcx> = RefCell<FnvHashMap<MethodCall, MethodCallee<'tcx>>>;
 
-pub type vtable_param_res<'tcx> = Vec<vtable_origin<'tcx>>;
-
-// Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res<'tcx> = VecPerParamSpace<vtable_param_res<'tcx>>;
-
-#[derive(Clone)]
-pub enum vtable_origin<'tcx> {
-    /*
-      Statically known vtable. def_id gives the impl item
-      from whence comes the vtable, and tys are the type substs.
-      vtable_res is the vtable itself.
-     */
-    vtable_static(ast::DefId, subst::Substs<'tcx>, vtable_res<'tcx>),
-
-    /*
-      Dynamic vtable, comes from a parameter that has a bound on it:
-      fn foo<T:quux,baz,bar>(a: T) -- a's vtable would have a
-      vtable_param origin
-
-      The first argument is the param index (identifying T in the example),
-      and the second is the bound number (identifying baz)
-     */
-    vtable_param(param_index, usize),
-
-    /*
-      Vtable automatically generated for a closure. The def ID is the
-      ID of the closure expression.
-     */
-    vtable_closure(ast::DefId),
-
-    /*
-      Asked to determine the vtable for ty_err. This is the value used
-      for the vtables of `Self` in a virtual call like `foo.bar()`
-      where `foo` is of object type. The same value is also used when
-      type errors occur.
-     */
-    vtable_error,
-}
-
-
-// For every explicit cast into an object type, maps from the cast
-// expr to the associated trait ref.
-pub type ObjectCastMap<'tcx> = RefCell<NodeMap<ty::PolyTraitRef<'tcx>>>;
-
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -601,9 +550,10 @@ pub struct CtxtArenas<'tcx> {
     substs: TypedArena<Substs<'tcx>>,
     bare_fn: TypedArena<BareFnTy<'tcx>>,
     region: TypedArena<Region>,
+    stability: TypedArena<attr::Stability>,
 
     // references
-    trait_defs: TypedArena<TraitDef<'tcx>>
+    trait_defs: TypedArena<TraitDef<'tcx>>,
 }
 
 impl<'tcx> CtxtArenas<'tcx> {
@@ -613,6 +563,7 @@ impl<'tcx> CtxtArenas<'tcx> {
             substs: TypedArena::new(),
             bare_fn: TypedArena::new(),
             region: TypedArena::new(),
+            stability: TypedArena::new(),
 
             trait_defs: TypedArena::new()
         }
@@ -654,6 +605,7 @@ pub struct ctxt<'tcx> {
     substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
     bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
     region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
+    stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
 
     /// Common types, pre-interned for your convenience.
     pub types: CommonTypes<'tcx>,
@@ -692,9 +644,7 @@ pub struct ctxt<'tcx> {
     /// A cache for the trait_items() routine
     pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
 
-    pub impl_trait_cache: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
-
-    pub impl_trait_refs: RefCell<NodeMap<TraitRef<'tcx>>>,
+    pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>,
     pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>,
 
     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
@@ -709,15 +659,10 @@ pub struct ctxt<'tcx> {
     /// additional acyclicity requirements).
     pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>,
 
-    /// Maps from node-id of a trait object cast (like `foo as
-    /// Box<Trait>`) to the trait reference.
-    pub object_cast_map: ObjectCastMap<'tcx>,
-
     pub map: ast_map::Map<'tcx>,
     pub freevars: RefCell<FreevarMap>,
     pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
     pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
-    pub short_names_cache: RefCell<FnvHashMap<Ty<'tcx>, String>>,
     pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
     pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
     pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
@@ -801,10 +746,7 @@ pub struct ctxt<'tcx> {
     pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>,
 
     /// Maps any item's def-id to its stability index.
-    pub stability: RefCell<stability::Index>,
-
-    /// Maps def IDs to true if and only if they're associated types.
-    pub associated_types: RefCell<DefIdMap<bool>>,
+    pub stability: RefCell<stability::Index<'tcx>>,
 
     /// Caches the results of trait selection. This cache is used
     /// for things that do not have to do with the parameters in scope.
@@ -847,6 +789,16 @@ impl<'tcx> ctxt<'tcx> {
         interned
     }
 
+    pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability {
+        if let Some(st) = self.stability_interner.borrow().get(&stab) {
+            return st;
+        }
+
+        let interned = self.arenas.stability.alloc(stab);
+        self.stability_interner.borrow_mut().insert(interned, interned);
+        interned
+    }
+
     pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
         self.free_region_maps.borrow_mut()
                              .insert(id, map);
@@ -948,6 +900,7 @@ impl<'tcx> ctxt<'tcx> {
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
         println!("Region interner: #{}", self.region_interner.borrow().len());
+        println!("Stability interner: #{}", self.stability_interner.borrow().len());
     }
 }
 
@@ -2753,7 +2706,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
                      freevars: RefCell<FreevarMap>,
                      region_maps: RegionMaps,
                      lang_items: middle::lang_items::LanguageItems,
-                     stability: stability::Index) -> ctxt<'tcx>
+                     stability: stability::Index<'tcx>) -> ctxt<'tcx>
 {
     let mut interner = FnvHashMap();
     let common_types = CommonTypes::new(&arenas.type_, &mut interner);
@@ -2764,6 +2717,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         substs_interner: RefCell::new(FnvHashMap()),
         bare_fn_interner: RefCell::new(FnvHashMap()),
         region_interner: RefCell::new(FnvHashMap()),
+        stability_interner: RefCell::new(FnvHashMap()),
         types: common_types,
         named_region_map: named_region_map,
         region_maps: region_maps,
@@ -2774,23 +2728,20 @@ pub fn mk_ctxt<'tcx>(s: Session,
         def_map: def_map,
         node_types: RefCell::new(FnvHashMap()),
         item_substs: RefCell::new(NodeMap()),
-        impl_trait_refs: RefCell::new(NodeMap()),
+        impl_trait_refs: RefCell::new(DefIdMap()),
         trait_defs: RefCell::new(DefIdMap()),
         predicates: RefCell::new(DefIdMap()),
         super_predicates: RefCell::new(DefIdMap()),
-        object_cast_map: RefCell::new(NodeMap()),
         map: map,
         freevars: freevars,
         tcache: RefCell::new(DefIdMap()),
         rcache: RefCell::new(FnvHashMap()),
-        short_names_cache: RefCell::new(FnvHashMap()),
         tc_cache: RefCell::new(FnvHashMap()),
         ast_ty_to_ty_cache: RefCell::new(NodeMap()),
         enum_var_cache: RefCell::new(DefIdMap()),
         impl_or_trait_items: RefCell::new(DefIdMap()),
         trait_item_def_ids: RefCell::new(DefIdMap()),
         trait_items_cache: RefCell::new(DefIdMap()),
-        impl_trait_cache: RefCell::new(DefIdMap()),
         ty_param_defs: RefCell::new(NodeMap()),
         adjustments: RefCell::new(NodeMap()),
         normalized_cache: RefCell::new(FnvHashMap()),
@@ -2816,7 +2767,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
         node_lint_levels: RefCell::new(FnvHashMap()),
         transmute_restrictions: RefCell::new(Vec::new()),
         stability: RefCell::new(stability),
-        associated_types: RefCell::new(DefIdMap()),
         selection_cache: traits::SelectionCache::new(),
         repr_hint_cache: RefCell::new(DefIdMap()),
         type_impls_copy_cache: RefCell::new(HashMap::new()),
@@ -4305,17 +4255,9 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
 }
 
 pub fn type_is_trait(ty: Ty) -> bool {
-    type_trait_info(ty).is_some()
-}
-
-pub fn type_trait_info<'tcx>(ty: Ty<'tcx>) -> Option<&'tcx TyTrait<'tcx>> {
     match ty.sty {
-        ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match ty.sty {
-            ty_trait(ref t) => Some(&**t),
-            _ => None
-        },
-        ty_trait(ref t) => Some(&**t),
-        _ => None
+        ty_trait(..) => true,
+        _ => false
     }
 }
 
@@ -4506,16 +4448,6 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
     }
 }
 
-pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
-                                  -> ty::TraitRef<'tcx> {
-    match cx.impl_trait_refs.borrow().get(&id) {
-        Some(ty) => *ty,
-        None => cx.sess.bug(
-            &format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
-                    cx.map.node_to_string(id)))
-    }
-}
-
 pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
     match node_id_to_type_opt(cx, id) {
        Some(ty) => ty,
@@ -5310,12 +5242,12 @@ pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
 /// the future).
 fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
                                           def_id: ast::DefId,
-                                          map: &mut DefIdMap<V>,
+                                          map: &RefCell<DefIdMap<V>>,
                                           load_external: F) -> V where
     V: Clone,
     F: FnOnce() -> V,
 {
-    match map.get(&def_id).cloned() {
+    match map.borrow().get(&def_id).cloned() {
         Some(v) => { return v; }
         None => { }
     }
@@ -5324,7 +5256,7 @@ fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
         panic!("No def'n found for {:?} in tcx.{}", def_id, descr);
     }
     let v = load_external();
-    map.insert(def_id, v.clone());
+    map.borrow_mut().insert(def_id, v.clone());
     v
 }
 
@@ -5390,33 +5322,9 @@ pub fn custom_coerce_unsized_kind<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
 
 pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                                 -> ImplOrTraitItem<'tcx> {
-    lookup_locally_or_in_crate_store("impl_or_trait_items",
-                                     id,
-                                     &mut *cx.impl_or_trait_items
-                                             .borrow_mut(),
-                                     || {
-        csearch::get_impl_or_trait_item(cx, id)
-    })
-}
-
-/// Returns true if the given ID refers to an associated type and false if it
-/// refers to anything else.
-pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
-    memoized(&cx.associated_types, id, |id: ast::DefId| {
-        if id.krate == ast::LOCAL_CRATE {
-            match cx.impl_or_trait_items.borrow().get(&id) {
-                Some(ref item) => {
-                    match **item {
-                        TypeTraitItem(_) => true,
-                        _ => false,
-                    }
-                }
-                None => false,
-            }
-        } else {
-            csearch::is_associated_type(&cx.sess.cstore, id)
-        }
-    })
+    lookup_locally_or_in_crate_store(
+        "impl_or_trait_items", id, &cx.impl_or_trait_items,
+        || csearch::get_impl_or_trait_item(cx, id))
 }
 
 /// Returns the parameter index that the given associated type corresponds to.
@@ -5434,34 +5342,33 @@ pub fn associated_type_parameter_index(cx: &ctxt,
 
 pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
                           -> Rc<Vec<ImplOrTraitItemId>> {
-    lookup_locally_or_in_crate_store("trait_item_def_ids",
-                                     id,
-                                     &mut *cx.trait_item_def_ids.borrow_mut(),
-                                     || {
-        Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
-    })
+    lookup_locally_or_in_crate_store(
+        "trait_item_def_ids", id, &cx.trait_item_def_ids,
+        || Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id)))
 }
 
+/// Returns the trait-ref corresponding to a given impl, or None if it is
+/// an inherent impl.
 pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                            -> Option<TraitRef<'tcx>> {
-    memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
-        if id.krate == ast::LOCAL_CRATE {
-            debug!("(impl_trait_ref) searching for trait impl {:?}", id);
-            if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
-                match item.node {
-                    ast::ItemImpl(_, _, _, Some(_), _, _) |
-                    ast::ItemDefaultImpl(..) => {
-                        Some(ty::impl_id_to_trait_ref(cx, id.node))
-                    }
-                    _ => None
-                }
-            } else {
-                None
-            }
+                            -> Option<TraitRef<'tcx>>
+{
+    lookup_locally_or_in_crate_store(
+        "impl_trait_refs", id, &cx.impl_trait_refs,
+        || csearch::get_impl_trait(cx, id))
+}
+
+/// Returns whether this DefId refers to an impl
+pub fn is_impl<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> bool {
+    if id.krate == ast::LOCAL_CRATE {
+        if let Some(ast_map::NodeItem(
+            &ast::Item { node: ast::ItemImpl(..), .. })) = cx.map.find(id.node) {
+            true
         } else {
-            csearch::get_impl_trait(cx, id)
+            false
         }
-    })
+    } else {
+        csearch::is_impl(&cx.sess.cstore, id)
+    }
 }
 
 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
@@ -5944,37 +5851,35 @@ pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
                               did: ast::DefId)
                               -> TypeScheme<'tcx> {
     lookup_locally_or_in_crate_store(
-        "tcache", did, &mut *cx.tcache.borrow_mut(),
+        "tcache", did, &cx.tcache,
         || csearch::get_type(cx, did))
 }
 
 /// Given the did of a trait, returns its canonical trait ref.
 pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
                               -> &'tcx TraitDef<'tcx> {
-    memoized(&cx.trait_defs, did, |did: DefId| {
-        assert!(did.krate != ast::LOCAL_CRATE);
-        cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
-    })
+    lookup_locally_or_in_crate_store(
+        "trait_defs", did, &cx.trait_defs,
+        || cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
+    )
 }
 
 /// Given the did of an item, returns its full set of predicates.
 pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
                                 -> GenericPredicates<'tcx>
 {
-    memoized(&cx.predicates, did, |did: DefId| {
-        assert!(did.krate != ast::LOCAL_CRATE);
-        csearch::get_predicates(cx, did)
-    })
+    lookup_locally_or_in_crate_store(
+        "predicates", did, &cx.predicates,
+        || csearch::get_predicates(cx, did))
 }
 
 /// Given the did of a trait, returns its superpredicates.
 pub fn lookup_super_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
                                      -> GenericPredicates<'tcx>
 {
-    memoized(&cx.super_predicates, did, |did: DefId| {
-        assert!(did.krate != ast::LOCAL_CRATE);
-        csearch::get_super_predicates(cx, did)
-    })
+    lookup_locally_or_in_crate_store(
+        "super_predicates", did, &cx.super_predicates,
+        || csearch::get_super_predicates(cx, did))
 }
 
 pub fn predicates<'tcx>(
@@ -6344,7 +6249,7 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
 
 pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
     lookup_locally_or_in_crate_store(
-        "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
+        "item_variance_map", item_id, &tcx.item_variance_map,
         || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
 }
 
@@ -7223,32 +7128,6 @@ impl<'tcx> Repr<'tcx> for ty::Predicate<'tcx> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for vtable_origin<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        match *self {
-            vtable_static(def_id, ref tys, ref vtable_res) => {
-                format!("vtable_static({:?}:{}, {}, {})",
-                        def_id,
-                        ty::item_path_str(tcx, def_id),
-                        tys.repr(tcx),
-                        vtable_res.repr(tcx))
-            }
-
-            vtable_param(x, y) => {
-                format!("vtable_param({:?}, {})", x, y)
-            }
-
-            vtable_closure(def_id) => {
-                format!("vtable_closure({:?})", def_id)
-            }
-
-            vtable_error => {
-                format!("vtable_error")
-            }
-        }
-    }
-}
-
 pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>,
                                             trait_ref: &ty::TraitRef<'tcx>,
                                             method: &ty::Method<'tcx>)
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 19a82e3f354..6f098a53238 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -336,27 +336,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::vtable_origin<'tcx> {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::vtable_origin<'tcx> {
-        match *self {
-            ty::vtable_static(def_id, ref substs, ref origins) => {
-                let r_substs = substs.fold_with(folder);
-                let r_origins = origins.fold_with(folder);
-                ty::vtable_static(def_id, r_substs, r_origins)
-            }
-            ty::vtable_param(n, b) => {
-                ty::vtable_param(n, b)
-            }
-            ty::vtable_closure(def_id) => {
-                ty::vtable_closure(def_id)
-            }
-            ty::vtable_error => {
-                ty::vtable_error
-            }
-        }
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
     fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
         *self
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 7c49f1e01d8..13dec30e0a0 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -653,7 +653,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
 
     // Do not move this check past lint
     time(time_passes, "stability index", (), |_|
-         ty_cx.stability.borrow_mut().build(&ty_cx.sess, krate, &public_items));
+         ty_cx.stability.borrow_mut().build(&ty_cx, krate, &public_items));
 
     time(time_passes, "intrinsic checking", (), |_|
          middle::intrinsicck::check_crate(&ty_cx));
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 50fdeb39105..4678b5335ea 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1798,20 +1798,21 @@ declare_lint! {
 pub struct Stability;
 
 impl Stability {
-    fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
+    fn lint(&self, cx: &Context, _id: ast::DefId,
+            span: Span, stability: &Option<&attr::Stability>) {
         // Deprecated attributes apply in-crate and cross-crate.
         let (lint, label) = match *stability {
-            Some(attr::Stability { deprecated_since: Some(_), .. }) =>
+            Some(&attr::Stability { deprecated_since: Some(_), .. }) =>
                 (DEPRECATED, "deprecated"),
             _ => return
         };
 
         output(cx, span, stability, lint, label);
 
-        fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
+        fn output(cx: &Context, span: Span, stability: &Option<&attr::Stability>,
                   lint: &'static Lint, label: &'static str) {
             let msg = match *stability {
-                Some(attr::Stability { reason: Some(ref s), .. }) => {
+                Some(&attr::Stability { reason: Some(ref s), .. }) => {
                     format!("use of {} item: {}", label, *s)
                 }
                 _ => format!("use of {} item", label)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 24f429a9ca0..eb6e90414e3 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -98,7 +98,7 @@ use middle::ty::{FnSig, GenericPredicates, TypeScheme};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
 use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::liberate_late_bound_regions;
-use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
+use middle::ty::{MethodCall, MethodCallee, MethodMap};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rscope::RegionScope;
 use session::Session;
@@ -164,7 +164,6 @@ pub struct Inherited<'a, 'tcx: 'a> {
     upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
     closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
     closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
-    object_cast_map: ObjectCastMap<'tcx>,
 
     // A mapping from each fn's id to its signature, with all bound
     // regions replaced with free ones. Unlike the other tables, this
@@ -383,7 +382,6 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
             item_substs: RefCell::new(NodeMap()),
             adjustments: RefCell::new(NodeMap()),
             method_map: RefCell::new(FnvHashMap()),
-            object_cast_map: RefCell::new(NodeMap()),
             upvar_capture_map: RefCell::new(FnvHashMap()),
             closure_tys: RefCell::new(DefIdMap()),
             closure_kinds: RefCell::new(DefIdMap()),
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 79736c08f37..8ec406ff41b 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -81,7 +81,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 self.check_impl(item);
             }
             ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
-                let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
+                let trait_ref = ty::impl_trait_ref(ccx.tcx,
+                                                   local_def(item.id)).unwrap();
                 ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 889975f0eb2..7eba4c0375f 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -41,7 +41,6 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) {
     wbcx.visit_expr(e);
     wbcx.visit_upvar_borrow_map();
     wbcx.visit_closures();
-    wbcx.visit_object_cast_map();
 }
 
 pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
@@ -62,7 +61,6 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
     }
     wbcx.visit_upvar_borrow_map();
     wbcx.visit_closures();
-    wbcx.visit_object_cast_map();
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -239,27 +237,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
-    fn visit_object_cast_map(&self) {
-        if self.fcx.writeback_errors.get() {
-            return
-        }
-
-        for (&node_id, trait_ref) in self.fcx
-                                            .inh
-                                            .object_cast_map
-                                            .borrow()
-                                            .iter()
-        {
-            let span = ty::expr_span(self.tcx(), node_id);
-            let reason = ResolvingExpr(span);
-            let closure_ty = self.resolve(trait_ref, reason);
-            self.tcx()
-                .object_cast_map
-                .borrow_mut()
-                .insert(node_id, closure_ty);
-        }
-    }
-
     fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
         // Resolve any borrowings for the node with id `id`
         self.visit_adjustments(reason, id);
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 58ad8ce8628..212423d16d4 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -36,7 +36,7 @@ use std::cell::RefCell;
 use std::rc::Rc;
 use syntax::ast::{Crate, DefId};
 use syntax::ast::{Item, ItemImpl};
-use syntax::ast::{LOCAL_CRATE, TraitRef};
+use syntax::ast::{LOCAL_CRATE};
 use syntax::ast;
 use syntax::ast_map::NodeItem;
 use syntax::ast_map;
@@ -100,11 +100,8 @@ struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
-
-        //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
-
-        if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
-            self.cc.check_implementation(item, opt_trait.as_ref())
+        if let ItemImpl(..) = item.node {
+            self.cc.check_implementation(item)
         }
 
         visit::walk_item(self, item);
@@ -141,7 +138,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         self.check_implementations_of_coerce_unsized();
     }
 
-    fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
+    fn check_implementation(&self, item: &Item) {
         let tcx = self.crate_context.tcx;
         let impl_did = local_def(item.id);
         let self_type = ty::lookup_item_type(tcx, impl_did);
@@ -151,8 +148,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
         let impl_items = self.create_impl_from_item(item);
 
-        if opt_trait.is_some() {
-            let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
+        if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
+                                                    impl_did) {
             debug!("(checking implementation) adding impl for trait '{}', item '{}'",
                    trait_ref.repr(self.crate_context.tcx),
                    token::get_ident(item.ident));
@@ -161,22 +158,13 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                                                  item.span,
                                                  trait_ref.def_id);
             self.add_trait_impl(trait_ref, impl_did);
-        }
-
-        // Add the implementation to the mapping from implementation to base
-        // type def ID, if there is a base type for this implementation and
-        // the implementation does not have any associated traits.
-        match get_base_type_def_id(&self.inference_context,
-                                   item.span,
-                                   self_type.ty) {
-            None => {
-                // Nothing to do.
-            }
-            Some(base_type_def_id) => {
-                // FIXME: Gather up default methods?
-                if opt_trait.is_none() {
-                    self.add_inherent_impl(base_type_def_id, impl_did);
-                }
+        } else {
+            // Add the implementation to the mapping from implementation to base
+            // type def ID, if there is a base type for this implementation and
+            // the implementation does not have any associated traits.
+            if let Some(base_type_def_id) = get_base_type_def_id(
+                    &self.inference_context, item.span, self_type.ty) {
+                self.add_inherent_impl(base_type_def_id, impl_did);
             }
         }
 
@@ -267,7 +255,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     // Converts an implementation in the AST to a vector of items.
     fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
         match item.node {
-            ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
+            ItemImpl(_, _, _, _, _, ref impl_items) => {
                 let mut items: Vec<ImplOrTraitItemId> =
                         impl_items.iter().map(|impl_item| {
                     match impl_item.node {
@@ -287,10 +275,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     }
                 }).collect();
 
-                if opt_trait.is_some() {
-                    let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
-                                                             item.id);
-
+                if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
+                                                            local_def(item.id)) {
                     self.instantiate_default_methods(local_def(item.id),
                                                      &trait_ref,
                                                      &mut items);
@@ -300,7 +286,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
             _ => {
                 self.crate_context.tcx.sess.span_bug(item.span,
-                                                     "can't convert a non-impl to an impl");
+                                                     "can't convert a non-impl \
+                                                      to an impl");
             }
         }
     }
@@ -453,8 +440,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
 
             let source = ty::lookup_item_type(tcx, impl_did).ty;
-            let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
-                                                     impl_did.node);
+            let trait_ref = ty::impl_trait_ref(self.crate_context.tcx,
+                                               impl_did).unwrap();
             let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
             debug!("check_implementations_of_coerce_unsized: {} -> {} (bound)",
                    source.repr(tcx), target.repr(tcx));
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 48876c2a188..2fba967b3b2 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -820,7 +820,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
 
             ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
 
-            tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
+            tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
         }
         ast::ItemImpl(_, _,
                       ref generics,
@@ -828,7 +828,6 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                       ref selfty,
                       ref impl_items) => {
             // Create generics from the generics specified in the impl head.
-
             debug!("convert: ast_generics={:?}", generics);
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
@@ -926,14 +925,16 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 }
             }
 
-            if let Some(ref ast_trait_ref) = *opt_trait_ref {
-                let trait_ref =
-                    astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
-                                                        &ExplicitRscope,
-                                                        ast_trait_ref,
-                                                        Some(selfty));
-
-                tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
+            if let &Some(ref ast_trait_ref) = opt_trait_ref {
+                tcx.impl_trait_refs.borrow_mut().insert(
+                    local_def(it.id),
+                    Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
+                                                             &ExplicitRscope,
+                                                             ast_trait_ref,
+                                                             Some(selfty)))
+                        );
+            } else {
+                tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None);
             }
 
             enforce_impl_params_are_constrained(tcx,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 045a38228c6..95444bb9158 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2695,6 +2695,21 @@ impl Clean<Stability> for attr::Stability {
     }
 }
 
+impl<'a> Clean<Stability> for &'a attr::Stability {
+    fn clean(&self, _: &DocContext) -> Stability {
+        Stability {
+            level: self.level,
+            feature: self.feature.to_string(),
+            since: self.since.as_ref().map_or("".to_string(),
+                                              |interned| interned.to_string()),
+            deprecated_since: self.deprecated_since.as_ref().map_or("".to_string(),
+                                                                    |istr| istr.to_string()),
+            reason: self.reason.as_ref().map_or("".to_string(),
+                                                |interned| interned.to_string()),
+        }
+    }
+}
+
 impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         Item {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index e86d77a3be0..e0a462dd437 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -61,7 +61,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
-        self.cx.tcx_opt().and_then(|tcx| stability::lookup(tcx, ast_util::local_def(id)))
+        self.cx.tcx_opt().and_then(
+            |tcx| stability::lookup(tcx, ast_util::local_def(id)).map(|x| x.clone()))
     }
 
     pub fn visit(&mut self, krate: &ast::Crate) {
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 755dd3bb458..3c4c4d70343 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -366,7 +366,7 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me
 }
 
 /// Represents the #[deprecated] and friends attributes.
-#[derive(RustcEncodable,RustcDecodable,Clone,Debug)]
+#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: InternedString,
@@ -378,7 +378,7 @@ pub struct Stability {
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable,RustcDecodable,PartialEq,PartialOrd,Clone,Debug,Copy)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Copy, Eq, Hash)]
 pub enum StabilityLevel {
     Unstable,
     Stable,