about summary refs log tree commit diff
path: root/src/librustc/metadata
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-09-17 14:29:59 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-10-01 10:43:07 -0400
commit01f32ace0302373fb69ef9e2d0e21cc841981eba (patch)
treeaceffa99e137cb0fa21d75f1a973ab0528a21415 /src/librustc/metadata
parenta6fee0674171fefc25e1a61e01870a654d6862a8 (diff)
Convert DefId to use DefIndex, which is an index into a list of
paths, and construct paths for all definitions. Also, stop rewriting
DefIds for closures, and instead just load the closure data from
the original def-id, which may be in another crate.
Diffstat (limited to 'src/librustc/metadata')
-rw-r--r--src/librustc/metadata/common.rs19
-rw-r--r--src/librustc/metadata/creader.rs7
-rw-r--r--src/librustc/metadata/csearch.rs103
-rw-r--r--src/librustc/metadata/cstore.rs18
-rw-r--r--src/librustc/metadata/decoder.rs222
-rw-r--r--src/librustc/metadata/encoder.rs248
-rw-r--r--src/librustc/metadata/index.rs224
-rw-r--r--src/librustc/metadata/tydecode.rs64
8 files changed, 449 insertions, 456 deletions
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index a6cbb4ec504..7b8ad78da74 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -43,9 +43,15 @@ pub const tag_items_data_parent_item: usize = 0x28;
 
 pub const tag_items_data_item_is_tuple_struct_ctor: usize = 0x29;
 
-pub const tag_index: usize = 0x2a;
+pub const tag_items_closure_kind: usize = 0x2a;
 
-// GAP 0x2b, 0x2c, 0x2d, 0x2e
+pub const tag_items_closure_ty: usize = 0x2b;
+
+pub const tag_index: usize = 0x2c;
+
+pub const tag_def_key: usize = 0x2d;
+
+// GAP 0x2e
 
 pub const tag_meta_item_name_value: usize = 0x2f;
 
@@ -137,8 +143,7 @@ enum_from_u32! {
         tag_table_adjustments = 0x61,
         tag_table_moves_map = 0x62,
         tag_table_capture_map = 0x63,
-        tag_table_closure_tys = 0x64,
-        tag_table_closure_kinds = 0x65,
+            // GAP 0x64, 0x65
         tag_table_upvar_capture_map = 0x66,
         tag_table_capture_modes = 0x67,
         // GAP 0x68
@@ -162,12 +167,12 @@ pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only
 // tag_lang_items
 // - tag_lang_items_item
 //   - tag_lang_items_item_id: u32
-//   - tag_lang_items_item_node_id: u32
+//   - tag_lang_items_item_index: u32
 
 pub const tag_lang_items: usize = 0x107; // top-level only
 pub const tag_lang_items_item: usize = 0x73;
 pub const tag_lang_items_item_id: usize = 0x74;
-pub const tag_lang_items_item_node_id: usize = 0x75;
+pub const tag_lang_items_item_index: usize = 0x75;
 pub const tag_lang_items_missing: usize = 0x76;
 
 pub const tag_item_unnamed_field: usize = 0x77;
@@ -215,7 +220,7 @@ pub struct LinkMeta {
 
 pub const tag_struct_fields: usize = 0x10d; // top-level only
 pub const tag_struct_field: usize = 0x8a;
-pub const tag_struct_field_id: usize = 0x8b;
+// GAP 0x8b
 
 pub const tag_attribute_is_sugared_doc: usize = 0x8c;
 
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 04f164c296d..fe4a909a085 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -325,6 +325,7 @@ impl<'a> CrateReader<'a> {
         let cmeta = Rc::new(cstore::crate_metadata {
             name: name.to_string(),
             local_path: RefCell::new(SmallVector::zero()),
+            local_def_path: RefCell::new(vec![]),
             index: decoder::load_index(metadata.as_slice()),
             data: metadata,
             cnum_map: RefCell::new(cnum_map),
@@ -548,7 +549,8 @@ impl<'a> CrateReader<'a> {
             self.sess.abort_if_errors();
         }
 
-        let registrar = decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice())
+        let registrar =
+            decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice())
             .map(|id| decoder::get_symbol_from_buf(ekrate.metadata.as_slice(), id));
 
         match (ekrate.dylib.as_ref(), registrar) {
@@ -751,6 +753,9 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                                                               i.span,
                                                               PathKind::Crate,
                                                               true);
+                        let def_id = self.ast_map.local_def_id(i.id);
+                        let def_path = self.ast_map.def_path(def_id);
+                        cmeta.update_local_def_path(def_path);
                         self.ast_map.with_path(i.id, |path| {
                             cmeta.update_local_path(path)
                         });
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 70a969e4d82..402aa52612e 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -14,7 +14,7 @@ use front::map as ast_map;
 use metadata::cstore;
 use metadata::decoder;
 use metadata::inline::InlinedItem;
-use middle::def_id::DefId;
+use middle::def_id::{DefId, DefIndex};
 use middle::lang_items;
 use middle::ty;
 use util::nodemap::FnvHashMap;
@@ -33,7 +33,7 @@ pub struct MethodInfo {
 
 pub fn get_symbol(cstore: &cstore::CStore, def: DefId) -> String {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_symbol(&cdata, def.xxx_node)
+    decoder::get_symbol(&cdata, def.index)
 }
 
 /// Iterates over all the language items in the given crate.
@@ -41,7 +41,7 @@ pub fn each_lang_item<F>(cstore: &cstore::CStore,
                          cnum: ast::CrateNum,
                          f: F)
                          -> bool where
-    F: FnMut(ast::NodeId, usize) -> bool,
+    F: FnMut(DefIndex, usize) -> bool,
 {
     let crate_data = cstore.get_crate_data(cnum);
     decoder::each_lang_item(&*crate_data, f)
@@ -59,7 +59,7 @@ pub fn each_child_of_item<F>(cstore: &cstore::CStore,
     };
     decoder::each_child_of_item(cstore.intr.clone(),
                                 &*crate_data,
-                                def_id.xxx_node,
+                                def_id.index,
                                 get_crate_data,
                                 callback)
 }
@@ -83,7 +83,7 @@ pub fn each_top_level_item_of_crate<F>(cstore: &cstore::CStore,
 pub fn get_item_path(tcx: &ty::ctxt, def: DefId) -> Vec<ast_map::PathElem> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    let path = decoder::get_item_path(&*cdata, def.xxx_node);
+    let path = decoder::get_item_path(&*cdata, def.index);
 
     cdata.with_local_path(|cpath| {
         let mut r = Vec::with_capacity(cpath.len() + path.len());
@@ -96,7 +96,7 @@ pub fn get_item_path(tcx: &ty::ctxt, def: DefId) -> Vec<ast_map::PathElem> {
 pub fn get_item_name(tcx: &ty::ctxt, def: DefId) -> ast::Name {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_item_name(&cstore.intr, &cdata, def.xxx_node)
+    decoder::get_item_name(&cstore.intr, &cdata, def.index)
 }
 
 pub enum FoundAst<'ast> {
@@ -113,14 +113,14 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId,
                                 -> FoundAst<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::maybe_get_item_ast(&*cdata, tcx, def.xxx_node, decode_inlined_item)
+    decoder::maybe_get_item_ast(&*cdata, tcx, def.index, decode_inlined_item)
 }
 
 /// Returns information about the given implementation.
 pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: DefId)
                       -> Vec<ty::ImplOrTraitItemId> {
     let cdata = cstore.get_crate_data(impl_def_id.krate);
-    decoder::get_impl_items(&*cdata, impl_def_id.xxx_node)
+    decoder::get_impl_items(&*cdata, impl_def_id.index)
 }
 
 pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
@@ -128,7 +128,7 @@ pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
     let cdata = tcx.sess.cstore.get_crate_data(def.krate);
     decoder::get_impl_or_trait_item(tcx.sess.cstore.intr.clone(),
                                     &*cdata,
-                                    def.xxx_node,
+                                    def.index,
                                     tcx)
 }
 
@@ -136,24 +136,24 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: DefId) -> ast::Name {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_trait_name(cstore.intr.clone(),
                             &*cdata,
-                            def.xxx_node)
+                            def.index)
 }
 
 pub fn is_static_method(cstore: &cstore::CStore, def: DefId) -> bool {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::is_static_method(&*cdata, def.xxx_node)
+    decoder::is_static_method(&*cdata, def.index)
 }
 
 pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: DefId)
                               -> Vec<ty::ImplOrTraitItemId> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_item_def_ids(&*cdata, def.xxx_node)
+    decoder::get_trait_item_def_ids(&*cdata, def.index)
 }
 
 pub fn get_item_variances(cstore: &cstore::CStore,
                           def: DefId) -> ty::ItemVariances {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_item_variances(&*cdata, def.xxx_node)
+    decoder::get_item_variances(&*cdata, def.index)
 }
 
 pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>,
@@ -161,43 +161,43 @@ pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>,
                                         -> Vec<Rc<ty::Method<'tcx>>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.xxx_node, tcx)
+    decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.index, tcx)
 }
 
 pub fn get_associated_consts<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
                                    -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_associated_consts(cstore.intr.clone(), &*cdata, def.xxx_node, tcx)
+    decoder::get_associated_consts(cstore.intr.clone(), &*cdata, def.index, tcx)
 }
 
 pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: DefId)
                           -> Option<ast::Name> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type_name_if_impl(&*cdata, def.xxx_node)
+    decoder::get_type_name_if_impl(&*cdata, def.index)
 }
 
 pub fn get_methods_if_impl(cstore: &cstore::CStore,
                                   def: DefId)
                                -> Option<Vec<MethodInfo> > {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.xxx_node)
+    decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.index)
 }
 
 pub fn get_item_attrs(cstore: &cstore::CStore,
                       def_id: DefId)
                       -> Vec<ast::Attribute> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_item_attrs(&*cdata, def_id.xxx_node)
+    decoder::get_item_attrs(&*cdata, def_id.index)
 }
 
 pub fn get_struct_field_names(cstore: &cstore::CStore, def: DefId) -> Vec<ast::Name> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_struct_field_names(&cstore.intr, &*cdata, def.xxx_node)
+    decoder::get_struct_field_names(&cstore.intr, &*cdata, def.index)
 }
 
-pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId) -> FnvHashMap<ast::NodeId,
-        Vec<ast::Attribute>> {
+pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId)
+                              -> FnvHashMap<DefId, Vec<ast::Attribute>> {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_struct_field_attrs(&*cdata)
 }
@@ -207,19 +207,19 @@ pub fn get_type<'tcx>(tcx: &ty::ctxt<'tcx>,
                       -> ty::TypeScheme<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type(&*cdata, def.xxx_node, tcx)
+    decoder::get_type(&*cdata, def.index, tcx)
 }
 
 pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId) -> ty::TraitDef<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_def(&*cdata, def.xxx_node, tcx)
+    decoder::get_trait_def(&*cdata, def.index, tcx)
 }
 
 pub fn get_adt_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_adt_def(&cstore.intr, &*cdata, def.xxx_node, tcx)
+    decoder::get_adt_def(&cstore.intr, &*cdata, def.index, tcx)
 }
 
 pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
@@ -227,7 +227,7 @@ pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_predicates(&*cdata, def.xxx_node, tcx)
+    decoder::get_predicates(&*cdata, def.index, tcx)
 }
 
 pub fn get_super_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
@@ -235,7 +235,7 @@ pub fn get_super_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_super_predicates(&*cdata, def.xxx_node, tcx)
+    decoder::get_super_predicates(&*cdata, def.index, tcx)
 }
 
 pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
@@ -244,7 +244,7 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_polarity(&*cdata, def.xxx_node)
+    decoder::get_impl_polarity(&*cdata, def.index)
 }
 
 pub fn get_custom_coerce_unsized_kind<'tcx>(
@@ -254,7 +254,7 @@ pub fn get_custom_coerce_unsized_kind<'tcx>(
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_custom_coerce_unsized_kind(&*cdata, def.xxx_node)
+    decoder::get_custom_coerce_unsized_kind(&*cdata, def.index)
 }
 
 // Given a def_id for an impl, return the trait it implements,
@@ -264,7 +264,7 @@ pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
                             -> Option<ty::TraitRef<'tcx>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_trait(&*cdata, def.xxx_node, tcx)
+    decoder::get_impl_trait(&*cdata, def.index, tcx)
 }
 
 pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
@@ -279,7 +279,7 @@ pub fn each_inherent_implementation_for_type<F>(cstore: &cstore::CStore,
     F: FnMut(DefId),
 {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::each_inherent_implementation_for_type(&*cdata, def_id.xxx_node, callback)
+    decoder::each_inherent_implementation_for_type(&*cdata, def_id.index, callback)
 }
 
 pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
@@ -300,7 +300,7 @@ pub fn get_trait_of_item(cstore: &cstore::CStore,
                          tcx: &ty::ctxt)
                          -> Option<DefId> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_trait_of_item(&*cdata, def_id.xxx_node, tcx)
+    decoder::get_trait_of_item(&*cdata, def_id.index, tcx)
 }
 
 pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
@@ -308,7 +308,7 @@ pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
     -> Option<DefId>
 {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.xxx_node)
+    decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.index)
 }
 
 pub fn get_dylib_dependency_formats(cstore: &cstore::CStore,
@@ -330,7 +330,7 @@ pub fn get_method_arg_names(cstore: &cstore::CStore, did: DefId)
     -> Vec<String>
 {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::get_method_arg_names(&*cdata, did.xxx_node)
+    decoder::get_method_arg_names(&*cdata, did.index)
 }
 
 pub fn get_reachable_ids(cstore: &cstore::CStore, cnum: ast::CrateNum)
@@ -342,24 +342,24 @@ pub fn get_reachable_ids(cstore: &cstore::CStore, cnum: ast::CrateNum)
 
 pub fn is_typedef(cstore: &cstore::CStore, did: DefId) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_typedef(&*cdata, did.xxx_node)
+    decoder::is_typedef(&*cdata, did.index)
 }
 
 pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_const_fn(&*cdata, did.xxx_node)
+    decoder::is_const_fn(&*cdata, did.index)
 }
 
 pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_impl(&*cdata, did.xxx_node)
+    decoder::is_impl(&*cdata, did.index)
 }
 
 pub fn get_stability(cstore: &cstore::CStore,
                      def: DefId)
                      -> Option<attr::Stability> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_stability(&*cdata, def.xxx_node)
+    decoder::get_stability(&*cdata, def.index)
 }
 
 pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
@@ -369,21 +369,42 @@ pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
 pub fn get_repr_attrs(cstore: &cstore::CStore, def: DefId)
                       -> Vec<attr::ReprAttr> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_repr_attrs(&*cdata, def.xxx_node)
+    decoder::get_repr_attrs(&*cdata, def.index)
 }
 
 pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: DefId) -> bool {
     let cdata = cstore.get_crate_data(trait_def_id.krate);
-    decoder::is_defaulted_trait(&*cdata, trait_def_id.xxx_node)
+    decoder::is_defaulted_trait(&*cdata, trait_def_id.index)
 }
 
 pub fn is_default_impl(cstore: &cstore::CStore, impl_did: DefId) -> bool {
     let cdata = cstore.get_crate_data(impl_did.krate);
-    decoder::is_default_impl(&*cdata, impl_did.xxx_node)
+    decoder::is_default_impl(&*cdata, impl_did.index)
 }
 
 pub fn is_extern_fn(cstore: &cstore::CStore, did: DefId,
                     tcx: &ty::ctxt) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_extern_fn(&*cdata, did.xxx_node, tcx)
+    decoder::is_extern_fn(&*cdata, did.index, tcx)
 }
+
+pub fn closure_kind<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind {
+    assert!(!def_id.is_local());
+    let cdata = tcx.sess.cstore.get_crate_data(def_id.krate);
+    decoder::closure_kind(&*cdata, def_id.index)
+}
+
+pub fn closure_ty<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> {
+    assert!(!def_id.is_local());
+    let cdata = tcx.sess.cstore.get_crate_data(def_id.krate);
+    decoder::closure_ty(&*cdata, def_id.index, tcx)
+}
+
+pub fn def_path(tcx: &ty::ctxt, def: DefId) -> ast_map::DefPath {
+    let cstore = &tcx.sess.cstore;
+    let cdata = cstore.get_crate_data(def.krate);
+    let path = decoder::def_path(&*cdata, def.index);
+    let local_path = cdata.local_def_path();
+    local_path.into_iter().chain(path).collect()
+}
+
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index 915027041bc..48676a2a1b4 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -59,6 +59,7 @@ pub struct ImportedFileMap {
 pub struct crate_metadata {
     pub name: String,
     pub local_path: RefCell<SmallVector<ast_map::PathElem>>,
+    pub local_def_path: RefCell<ast_map::DefPath>,
     pub data: MetadataBlob,
     pub cnum_map: RefCell<cnum_map>,
     pub cnum: ast::CrateNum,
@@ -312,6 +313,23 @@ impl crate_metadata {
         }
     }
 
+    pub fn local_def_path(&self) -> ast_map::DefPath {
+        let local_def_path = self.local_def_path.borrow();
+        if local_def_path.is_empty() {
+            let name = ast_map::DefPathData::DetachedCrate(token::intern(&self.name));
+            vec![ast_map::DisambiguatedDefPathData { data: name, disambiguator: 0 }]
+        } else {
+            local_def_path.clone()
+        }
+    }
+
+    pub fn update_local_def_path(&self, candidate: ast_map::DefPath) {
+        let mut local_def_path = self.local_def_path.borrow_mut();
+        if local_def_path.is_empty() || candidate.len() < local_def_path.len() {
+            *local_def_path = candidate;
+        }
+    }
+
     pub fn is_allocator(&self) -> bool {
         let attrs = decoder::get_crate_attributes(self.data());
         attr::contains_name(&attrs, "allocator")
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 8ce31e533de..58e87f1910a 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -30,7 +30,7 @@ use metadata::index;
 use metadata::inline::InlinedItem;
 use metadata::tydecode::TyDecoder;
 use middle::def;
-use middle::def_id::DefId;
+use middle::def_id::{DefId, DefIndex};
 use middle::lang_items;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
@@ -59,15 +59,15 @@ use syntax::ptr::P;
 pub type Cmd<'a> = &'a crate_metadata;
 
 impl crate_metadata {
-    fn get_item(&self, item_id: ast::NodeId) -> Option<rbml::Doc> {
+    fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
         self.index.lookup_item(self.data(), item_id).map(|pos| {
             reader::doc_at(self.data(), pos as usize).unwrap().doc
         })
     }
 
-    fn lookup_item(&self, item_id: ast::NodeId) -> rbml::Doc {
+    fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc {
         match self.get_item(item_id) {
-            None => panic!("lookup_item: id not found: {}", item_id),
+            None => panic!("lookup_item: id not found: {:?}", item_id),
             Some(d) => d
         }
     }
@@ -75,7 +75,7 @@ impl crate_metadata {
 
 pub fn load_index(data: &[u8]) -> index::Index {
     let index = reader::get_doc(rbml::Doc::new(data), tag_index);
-    index::Index::from_buf(index.data, index.start, index.end)
+    index::Index::from_rbml(index)
 }
 
 pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
@@ -170,7 +170,8 @@ fn item_symbol(item: rbml::Doc) -> String {
 
 fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId {
     let id = reader::doc_as_u64(d);
-    let def_id = DefId { krate: (id >> 32) as u32, xxx_node: id as u32 };
+    let index = DefIndex::new((id & 0xFFFF_FFFF) as usize);
+    let def_id = DefId { krate: (id >> 32) as u32, index: index };
     translate_def_id(cdata, def_id)
 }
 
@@ -203,14 +204,14 @@ fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
 fn doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Ty<'tcx> {
     let tp = reader::get_doc(doc, tag_items_data_item_type);
     TyDecoder::with_doc(tcx, cdata.cnum, tp,
-                        &mut |_, did| translate_def_id(cdata, did))
+                        &mut |did| translate_def_id(cdata, did))
         .parse_ty()
 }
 
 fn maybe_doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Option<Ty<'tcx>> {
     reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| {
         TyDecoder::with_doc(tcx, cdata.cnum, tp,
-                            &mut |_, did| translate_def_id(cdata, did))
+                            &mut |did| translate_def_id(cdata, did))
             .parse_ty()
     })
 }
@@ -219,7 +220,7 @@ fn doc_method_fty<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>,
                         cdata: Cmd) -> ty::BareFnTy<'tcx> {
     let tp = reader::get_doc(doc, tag_item_method_fty);
     TyDecoder::with_doc(tcx, cdata.cnum, tp,
-                        &mut |_, did| translate_def_id(cdata, did))
+                        &mut |did| translate_def_id(cdata, did))
         .parse_bare_fn_ty()
 }
 
@@ -231,7 +232,7 @@ pub fn item_type<'tcx>(_item_id: DefId, item: rbml::Doc,
 fn doc_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
                        -> ty::TraitRef<'tcx> {
     TyDecoder::with_doc(tcx, cdata.cnum, doc,
-                        &mut |_, did| translate_def_id(cdata, did))
+                        &mut |did| translate_def_id(cdata, did))
         .parse_trait_ref()
 }
 
@@ -345,7 +346,7 @@ fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
 }
 
 pub fn get_trait_def<'tcx>(cdata: Cmd,
-                           item_id: ast::NodeId,
+                           item_id: DefIndex,
                            tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
 {
     let item_doc = cdata.lookup_item(item_id);
@@ -368,7 +369,7 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
 
 pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                          cdata: Cmd,
-                         item_id: ast::NodeId,
+                         item_id: DefIndex,
                          tcx: &ty::ctxt<'tcx>) -> ty::AdtDefMaster<'tcx>
 {
     fn get_enum_variants<'tcx>(intr: &IdentInterner,
@@ -378,7 +379,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
         let mut disr_val = 0;
         reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
             let did = translated_def_id(cdata, p);
-            let item = cdata.lookup_item(did.xxx_node);
+            let item = cdata.lookup_item(did.index);
 
             if let Some(disr) = variant_disr_val(item) {
                 disr_val = disr;
@@ -428,7 +429,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
     }
 
     let doc = cdata.lookup_item(item_id);
-    let did = DefId { krate: cdata.cnum, xxx_node: item_id };
+    let did = DefId { krate: cdata.cnum, index: item_id };
     let (kind, variants) = match item_family(doc) {
         Enum => (ty::AdtKind::Enum,
                  get_enum_variants(intr, cdata, doc, tcx)),
@@ -448,7 +449,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
             // from the ctor.
             debug!("evaluating the ctor-type of {:?}",
                    variant.name);
-            let ctor_ty = get_type(cdata, variant.did.xxx_node, tcx).ty;
+            let ctor_ty = get_type(cdata, variant.did.index, tcx).ty;
             debug!("evaluating the ctor-type of {:?}.. {:?}",
                    variant.name,
                    ctor_ty);
@@ -468,7 +469,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
         } else {
             for field in &variant.fields {
                 debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
-                let ty = get_type(cdata, field.did.xxx_node, tcx).ty;
+                let ty = get_type(cdata, field.did.index, tcx).ty;
                 field.fulfill_ty(ty);
                 debug!("evaluating the type of {:?}::{:?}: {:?}",
                        variant.name, field.name, ty);
@@ -480,7 +481,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
 }
 
 pub fn get_predicates<'tcx>(cdata: Cmd,
-                            item_id: ast::NodeId,
+                            item_id: DefIndex,
                             tcx: &ty::ctxt<'tcx>)
                             -> ty::GenericPredicates<'tcx>
 {
@@ -489,7 +490,7 @@ pub fn get_predicates<'tcx>(cdata: Cmd,
 }
 
 pub fn get_super_predicates<'tcx>(cdata: Cmd,
-                                  item_id: ast::NodeId,
+                                  item_id: DefIndex,
                                   tcx: &ty::ctxt<'tcx>)
                                   -> ty::GenericPredicates<'tcx>
 {
@@ -497,11 +498,11 @@ pub fn get_super_predicates<'tcx>(cdata: Cmd,
     doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates)
 }
 
-pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
+pub fn get_type<'tcx>(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt<'tcx>)
                       -> ty::TypeScheme<'tcx>
 {
     let item_doc = cdata.lookup_item(id);
-    let t = item_type(DefId { krate: cdata.cnum, xxx_node: id }, item_doc, tcx,
+    let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx,
                       cdata);
     let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
     ty::TypeScheme {
@@ -510,7 +511,7 @@ pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
     }
 }
 
-pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
+pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
     let item = cdata.lookup_item(id);
     reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| {
         let mut decoder = reader::Decoder::new(doc);
@@ -518,7 +519,7 @@ pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
     })
 }
 
-pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
+pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
     let item = cdata.lookup_item(id);
     match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
         let mut decoder = reader::Decoder::new(doc);
@@ -530,7 +531,7 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
 }
 
 pub fn get_impl_polarity<'tcx>(cdata: Cmd,
-                               id: ast::NodeId)
+                               id: DefIndex)
                                -> Option<hir::ImplPolarity>
 {
     let item_doc = cdata.lookup_item(id);
@@ -545,7 +546,7 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
 
 pub fn get_custom_coerce_unsized_kind<'tcx>(
     cdata: Cmd,
-    id: ast::NodeId)
+    id: DefIndex)
     -> Option<ty::adjustment::CustomCoerceUnsized>
 {
     let item_doc = cdata.lookup_item(id);
@@ -556,7 +557,7 @@ pub fn get_custom_coerce_unsized_kind<'tcx>(
 }
 
 pub fn get_impl_trait<'tcx>(cdata: Cmd,
-                            id: ast::NodeId,
+                            id: DefIndex,
                             tcx: &ty::ctxt<'tcx>)
                             -> Option<ty::TraitRef<'tcx>>
 {
@@ -572,12 +573,12 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
     }
 }
 
-pub fn get_symbol(cdata: Cmd, id: ast::NodeId) -> String {
+pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String {
     return item_symbol(cdata.lookup_item(id));
 }
 
 /// If you have a crate_metadata, call get_symbol instead
-pub fn get_symbol_from_buf(data: &[u8], id: ast::NodeId) -> String {
+pub fn get_symbol_from_buf(data: &[u8], id: DefIndex) -> String {
     let index = load_index(data);
     let pos = index.lookup_item(data, id).unwrap();
     let doc = reader::doc_at(data, pos as usize).unwrap().doc;
@@ -594,18 +595,17 @@ pub enum DefLike {
 
 /// Iterates over the language items in the given crate.
 pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
-    F: FnMut(ast::NodeId, usize) -> bool,
+    F: FnMut(DefIndex, usize) -> bool,
 {
     let root = rbml::Doc::new(cdata.data());
     let lang_items = reader::get_doc(root, tag_lang_items);
     reader::tagged_docs(lang_items, tag_lang_items_item).all(|item_doc| {
         let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
         let id = reader::doc_as_u32(id_doc) as usize;
-        let node_id_doc = reader::get_doc(item_doc,
-                                          tag_lang_items_item_node_id);
-        let node_id = reader::doc_as_u32(node_id_doc) as ast::NodeId;
+        let index_doc = reader::get_doc(item_doc, tag_lang_items_item_index);
+        let index = DefIndex::from_u32(reader::doc_as_u32(index_doc));
 
-        f(node_id, id)
+        f(index, id)
     })
 }
 
@@ -634,7 +634,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
         };
 
         // Get the item.
-        match crate_data.get_item(child_def_id.xxx_node) {
+        match crate_data.get_item(child_def_id.index) {
             None => {}
             Some(child_item_doc) => {
                 // Hand off the item to the callback.
@@ -652,12 +652,12 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
     for inherent_impl_def_id_doc in reader::tagged_docs(item_doc,
                                                              tag_items_data_item_inherent_impl) {
         let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc, cdata);
-        if let Some(inherent_impl_doc) = cdata.get_item(inherent_impl_def_id.xxx_node) {
+        if let Some(inherent_impl_doc) = cdata.get_item(inherent_impl_def_id.index) {
             for impl_item_def_id_doc in reader::tagged_docs(inherent_impl_doc,
                                                                  tag_item_impl_item) {
                 let impl_item_def_id = item_def_id(impl_item_def_id_doc,
                                                    cdata);
-                if let Some(impl_method_doc) = cdata.get_item(impl_item_def_id.xxx_node) {
+                if let Some(impl_method_doc) = cdata.get_item(impl_item_def_id.index) {
                     if let StaticMethod = item_family(impl_method_doc) {
                         // Hand off the static method to the callback.
                         let static_method_name = item_name(&*intr, impl_method_doc);
@@ -693,7 +693,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
         };
 
         // Get the item.
-        if let Some(child_item_doc) = crate_data.get_item(child_def_id.xxx_node) {
+        if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) {
             // Hand off the item to the callback.
             let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
             // These items have a public visibility because they're part of
@@ -706,7 +706,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
 /// Iterates over each child of the given item.
 pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
                                cdata: Cmd,
-                               id: ast::NodeId,
+                               id: DefIndex,
                                get_crate_data: G,
                                callback: F) where
     F: FnMut(DefLike, ast::Name, hir::Visibility),
@@ -745,11 +745,11 @@ pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
                                 callback)
 }
 
-pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<hir_map::PathElem> {
+pub fn get_item_path(cdata: Cmd, id: DefIndex) -> Vec<hir_map::PathElem> {
     item_path(cdata.lookup_item(id))
 }
 
-pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId) -> ast::Name {
+pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: DefIndex) -> ast::Name {
     item_name(intr, cdata.lookup_item(id))
 }
 
@@ -757,22 +757,25 @@ pub type DecodeInlinedItem<'a> =
     Box<for<'tcx> FnMut(Cmd,
                         &ty::ctxt<'tcx>,
                         Vec<hir_map::PathElem>,
+                        hir_map::DefPath,
                         rbml::Doc)
-                        -> Result<&'tcx InlinedItem, Vec<hir_map::PathElem>> + 'a>;
+                        -> Result<&'tcx InlinedItem, (Vec<hir_map::PathElem>,
+                                                      hir_map::DefPath)> + 'a>;
 
-pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeId,
+pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: DefIndex,
                                 mut decode_inlined_item: DecodeInlinedItem)
                                 -> csearch::FoundAst<'tcx> {
-    debug!("Looking up item: {}", id);
+    debug!("Looking up item: {:?}", id);
     let item_doc = cdata.lookup_item(id);
     let path = item_path(item_doc).split_last().unwrap().1.to_vec();
-    match decode_inlined_item(cdata, tcx, path, item_doc) {
+    let def_path = def_path(cdata, id);
+    match decode_inlined_item(cdata, tcx, path, def_path, item_doc) {
         Ok(ii) => csearch::FoundAst::Found(ii),
-        Err(path) => {
+        Err((path, def_path)) => {
             match item_parent_item(cdata, item_doc) {
                 Some(did) => {
-                    let parent_item = cdata.lookup_item(did.xxx_node);
-                    match decode_inlined_item(cdata, tcx, path, parent_item) {
+                    let parent_item = cdata.lookup_item(did.index);
+                    match decode_inlined_item(cdata, tcx, path, def_path, parent_item) {
                         Ok(ii) => csearch::FoundAst::FoundParent(did, ii),
                         Err(_) => csearch::FoundAst::NotFound
                     }
@@ -811,7 +814,7 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
 }
 
 /// Returns the def IDs of all the items in the given implementation.
-pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
+pub fn get_impl_items(cdata: Cmd, impl_id: DefIndex)
                       -> Vec<ty::ImplOrTraitItemId> {
     reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| {
         let def_id = item_def_id(doc, cdata);
@@ -826,13 +829,13 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
 
 pub fn get_trait_name(intr: Rc<IdentInterner>,
                       cdata: Cmd,
-                      id: ast::NodeId)
+                      id: DefIndex)
                       -> ast::Name {
     let doc = cdata.lookup_item(id);
     item_name(&*intr, doc)
 }
 
-pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_static_method(cdata: Cmd, id: DefIndex) -> bool {
     let doc = cdata.lookup_item(id);
     match item_sort(doc) {
         Some('r') | Some('p') => {
@@ -844,7 +847,7 @@ pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
 
 pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                     cdata: Cmd,
-                                    id: ast::NodeId,
+                                    id: DefIndex,
                                     tcx: &ty::ctxt<'tcx>)
                                     -> ty::ImplOrTraitItem<'tcx> {
     let item_doc = cdata.lookup_item(id);
@@ -852,7 +855,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     let def_id = item_def_id(item_doc, cdata);
 
     let container_id = item_require_parent_item(cdata, item_doc);
-    let container_doc = cdata.lookup_item(container_id.xxx_node);
+    let container_doc = cdata.lookup_item(container_id.index);
     let container = match item_family(container_doc) {
         Trait => TraitContainer(container_id),
         _ => ImplContainer(container_id),
@@ -902,7 +905,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     }
 }
 
-pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
+pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex)
                               -> Vec<ty::ImplOrTraitItemId> {
     let item = cdata.lookup_item(id);
     reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
@@ -916,7 +919,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
     }).collect()
 }
 
-pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
+pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> ty::ItemVariances {
     let item_doc = cdata.lookup_item(id);
     let variance_doc = reader::get_doc(item_doc, tag_item_variances);
     let mut decoder = reader::Decoder::new(variance_doc);
@@ -925,19 +928,19 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
 
 pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
                                         cdata: Cmd,
-                                        id: ast::NodeId,
+                                        id: DefIndex,
                                         tcx: &ty::ctxt<'tcx>)
                                         -> Vec<Rc<ty::Method<'tcx>>> {
     let item = cdata.lookup_item(id);
 
     reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| {
         let did = item_def_id(mth_id, cdata);
-        let mth = cdata.lookup_item(did.xxx_node);
+        let mth = cdata.lookup_item(did.index);
 
         if item_sort(mth) == Some('p') {
             let trait_item = get_impl_or_trait_item(intr.clone(),
                                                     cdata,
-                                                    did.xxx_node,
+                                                    did.index,
                                                     tcx);
             if let ty::MethodTraitItem(ref method) = trait_item {
                 Some((*method).clone())
@@ -952,7 +955,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
 
 pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
                                    cdata: Cmd,
-                                   id: ast::NodeId,
+                                   id: DefIndex,
                                    tcx: &ty::ctxt<'tcx>)
                                    -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
     let item = cdata.lookup_item(id);
@@ -960,13 +963,13 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
     [tag_item_trait_item, tag_item_impl_item].iter().flat_map(|&tag| {
         reader::tagged_docs(item, tag).filter_map(|ac_id| {
             let did = item_def_id(ac_id, cdata);
-            let ac_doc = cdata.lookup_item(did.xxx_node);
+            let ac_doc = cdata.lookup_item(did.index);
 
             match item_sort(ac_doc) {
                 Some('C') | Some('c') => {
                     let trait_item = get_impl_or_trait_item(intr.clone(),
                                                             cdata,
-                                                            did.xxx_node,
+                                                            did.index,
                                                             tcx);
                     if let ty::ConstTraitItem(ref ac) = trait_item {
                         Some((*ac).clone())
@@ -981,7 +984,7 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
 }
 
 pub fn get_type_name_if_impl(cdata: Cmd,
-                             node_id: ast::NodeId) -> Option<ast::Name> {
+                             node_id: DefIndex) -> Option<ast::Name> {
     let item = cdata.lookup_item(node_id);
     if item_family(item) != Impl {
         return None;
@@ -994,7 +997,7 @@ pub fn get_type_name_if_impl(cdata: Cmd,
 
 pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
                                   cdata: Cmd,
-                                  node_id: ast::NodeId)
+                                  node_id: DefIndex)
                                -> Option<Vec<MethodInfo> > {
     let item = cdata.lookup_item(node_id);
     if item_family(item) != Impl {
@@ -1011,7 +1014,7 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
 
     let mut impl_methods = Vec::new();
     for impl_method_id in impl_method_ids {
-        let impl_method_doc = cdata.lookup_item(impl_method_id.xxx_node);
+        let impl_method_doc = cdata.lookup_item(impl_method_id.index);
         let family = item_family(impl_method_doc);
         match family {
             StaticMethod | Method => {
@@ -1031,7 +1034,7 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
 /// If node_id is the constructor of a tuple struct, retrieve the NodeId of
 /// the actual type definition, otherwise, return None
 pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
-                                           node_id: ast::NodeId)
+                                           node_id: DefIndex)
     -> Option<DefId>
 {
     let item = cdata.lookup_item(node_id);
@@ -1041,24 +1044,24 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
 }
 
 pub fn get_item_attrs(cdata: Cmd,
-                      orig_node_id: ast::NodeId)
+                      orig_node_id: DefIndex)
                       -> Vec<ast::Attribute> {
     // The attributes for a tuple struct are attached to the definition, not the ctor;
     // we assume that someone passing in a tuple struct ctor is actually wanting to
     // look at the definition
     let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
-    let node_id = node_id.map(|x| x.xxx_node).unwrap_or(orig_node_id);
+    let node_id = node_id.map(|x| x.index).unwrap_or(orig_node_id);
     let item = cdata.lookup_item(node_id);
     get_attributes(item)
 }
 
-pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<ast::NodeId, Vec<ast::Attribute>> {
+pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<DefId, Vec<ast::Attribute>> {
     let data = rbml::Doc::new(cdata.data());
     let fields = reader::get_doc(data, tag_struct_fields);
     reader::tagged_docs(fields, tag_struct_field).map(|field| {
-        let id = reader::doc_as_u32(reader::get_doc(field, tag_struct_field_id));
+        let def_id = translated_def_id(cdata, reader::get_doc(field, tag_def_id));
         let attrs = get_attributes(field);
-        (id, attrs)
+        (def_id, attrs)
     }).collect()
 }
 
@@ -1070,7 +1073,7 @@ fn struct_field_family_to_visibility(family: Family) -> hir::Visibility {
     }
 }
 
-pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
+pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: DefIndex)
     -> Vec<ast::Name> {
     let item = cdata.lookup_item(id);
     reader::tagged_docs(item, tag_item_field).map(|an_item| {
@@ -1228,14 +1231,14 @@ pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()>
 // crate to the correct local crate number.
 pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
     if did.is_local() {
-        return DefId { krate: cdata.cnum, xxx_node: did.xxx_node };
+        return DefId { krate: cdata.cnum, index: did.index };
     }
 
     match cdata.cnum_map.borrow().get(&did.krate) {
         Some(&n) => {
             DefId {
                 krate: n,
-                xxx_node: did.xxx_node,
+                index: did.index,
             }
         }
         None => panic!("didn't find a crate in the cnum_map")
@@ -1246,12 +1249,12 @@ pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
 // for an external crate.
 fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
     if did.krate == cdata.cnum {
-        return Some(DefId { krate: LOCAL_CRATE, xxx_node: did.xxx_node });
+        return Some(DefId { krate: LOCAL_CRATE, index: did.index });
     }
 
     for (&local, &global) in cdata.cnum_map.borrow().iter() {
         if global == did.krate {
-            return Some(DefId { krate: local, xxx_node: did.xxx_node });
+            return Some(DefId { krate: local, index: did.index });
         }
     }
 
@@ -1259,7 +1262,7 @@ fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
 }
 
 pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
-                                                id: ast::NodeId,
+                                                id: DefIndex,
                                                 mut callback: F)
     where F: FnMut(DefId),
 {
@@ -1277,7 +1280,7 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
     F: FnMut(DefId),
 {
     if cdata.cnum == def_id.krate {
-        let item_doc = cdata.lookup_item(def_id.xxx_node);
+        let item_doc = cdata.lookup_item(def_id.index);
         for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_extension_impl) {
             callback(item_def_id(impl_doc, cdata));
         }
@@ -1299,14 +1302,14 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
     }
 }
 
-pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
+pub fn get_trait_of_item(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt)
                          -> Option<DefId> {
     let item_doc = cdata.lookup_item(id);
     let parent_item_id = match item_parent_item(cdata, item_doc) {
         None => return None,
         Some(item_id) => item_id,
     };
-    let parent_item_doc = cdata.lookup_item(parent_item_id.xxx_node);
+    let parent_item_doc = cdata.lookup_item(parent_item_id.index);
     match item_family(parent_item_doc) {
         Trait => Some(item_def_id(parent_item_doc, cdata)),
         Impl | DefaultImpl => {
@@ -1332,9 +1335,9 @@ pub fn get_native_libraries(cdata: Cmd)
     }).collect()
 }
 
-pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
+pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> {
     reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
-        .map(|doc| reader::doc_as_u32(doc))
+        .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc)))
 }
 
 pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
@@ -1386,7 +1389,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
     }).collect()
 }
 
-pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<String> {
+pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec<String> {
     let method_doc = cdata.lookup_item(id);
     match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
         Some(args_doc) => {
@@ -1404,12 +1407,12 @@ pub fn get_reachable_ids(cdata: Cmd) -> Vec<DefId> {
     reader::tagged_docs(items, tag_reachable_id).map(|doc| {
         DefId {
             krate: cdata.cnum,
-            xxx_node: reader::doc_as_u32(doc),
+            index: DefIndex::from_u32(reader::doc_as_u32(doc)),
         }
     }).collect()
 }
 
-pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_typedef(cdata: Cmd, id: DefIndex) -> bool {
     let item_doc = cdata.lookup_item(id);
     match item_family(item_doc) {
         Type => true,
@@ -1417,7 +1420,7 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
     }
 }
 
-pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
     let item_doc = cdata.lookup_item(id);
     match fn_constness(item_doc) {
         hir::Constness::Const => true,
@@ -1425,7 +1428,7 @@ pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
     }
 }
 
-pub fn is_impl(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
     let item_doc = cdata.lookup_item(id);
     match item_family(item_doc) {
         Impl => true,
@@ -1445,7 +1448,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
     for p in reader::tagged_docs(doc, tag_type_param_def) {
         let bd =
             TyDecoder::with_doc(tcx, cdata.cnum, p,
-                                &mut |_, did| translate_def_id(cdata, did))
+                                &mut |did| translate_def_id(cdata, did))
             .parse_type_param_def();
         types.push(bd.space, bd);
     }
@@ -1467,7 +1470,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
 
         let bounds = reader::tagged_docs(rp_doc, tag_items_data_region).map(|p| {
             TyDecoder::with_doc(tcx, cdata.cnum, p,
-                                &mut |_, did| translate_def_id(cdata, did))
+                                &mut |did| translate_def_id(cdata, did))
             .parse_region()
         }).collect();
 
@@ -1497,7 +1500,7 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
         let data_doc = reader::get_doc(predicate_doc, tag_predicate_data);
         let data =
             TyDecoder::with_doc(tcx, cdata.cnum, data_doc,
-                                &mut |_, did| translate_def_id(cdata, did))
+                                &mut |did| translate_def_id(cdata, did))
             .parse_predicate();
 
         predicates.push(space, data);
@@ -1506,14 +1509,14 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
     ty::GenericPredicates { predicates: predicates }
 }
 
-pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
+pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool {
     let trait_doc = cdata.lookup_item(trait_id);
     assert!(item_family(trait_doc) == Family::Trait);
     let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
     reader::doc_as_u8(defaulted_doc) != 0
 }
 
-pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool {
+pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool {
     let impl_doc = cdata.lookup_item(impl_id);
     item_family(impl_doc) == Family::DefaultImpl
 }
@@ -1528,7 +1531,7 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
     }).collect()
 }
 
-pub fn is_extern_fn(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> bool {
+pub fn is_extern_fn(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt) -> bool {
     let item_doc = match cdata.get_item(id) {
         Some(doc) => doc,
         None => return false,
@@ -1543,3 +1546,42 @@ pub fn is_extern_fn(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> bool {
         false
     }
 }
+
+pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind {
+    let closure_doc = cdata.lookup_item(closure_id);
+    let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind);
+    let mut decoder = reader::Decoder::new(closure_kind_doc);
+    ty::ClosureKind::decode(&mut decoder).unwrap()
+}
+
+pub fn closure_ty<'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: &ty::ctxt<'tcx>)
+                        -> ty::ClosureTy<'tcx> {
+    let closure_doc = cdata.lookup_item(closure_id);
+    let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty);
+    TyDecoder::with_doc(tcx, cdata.cnum, closure_ty_doc, &mut |did| translate_def_id(cdata, did))
+        .parse_closure_ty()
+}
+
+fn def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
+    match reader::maybe_get_doc(item_doc, tag_def_key) {
+        Some(def_key_doc) => {
+            let mut decoder = reader::Decoder::new(def_key_doc);
+            hir_map::DefKey::decode(&mut decoder).unwrap()
+        }
+        None => {
+            panic!("failed to find block with tag {:?} for item with family {:?}",
+                   tag_def_key,
+                   item_family(item_doc))
+        }
+    }
+}
+
+pub fn def_path(cdata: Cmd, id: DefIndex) -> hir_map::DefPath {
+    debug!("def_path(id={:?})", id);
+    hir_map::definitions::make_def_path(id, |parent| {
+        debug!("def_path: parent={:?}", parent);
+        let parent_doc = cdata.lookup_item(parent);
+        def_key(parent_doc)
+    })
+}
+
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 14e5e8b41ff..f637545e2e9 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -20,10 +20,10 @@ use metadata::cstore;
 use metadata::cstore::LOCAL_CRATE;
 use metadata::decoder;
 use metadata::tyencode;
-use metadata::index::{self, IndexEntry};
+use metadata::index::IndexData;
 use metadata::inline::InlinedItemRef;
 use middle::def;
-use middle::def_id::DefId;
+use middle::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::dependency_format::Linkage;
 use middle::stability;
 use middle::ty::{self, Ty};
@@ -34,6 +34,7 @@ use std::cell::RefCell;
 use std::io::prelude::*;
 use std::io::{Cursor, SeekFrom};
 use std::rc::Rc;
+use std::u32;
 use syntax::abi;
 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
 use syntax::attr;
@@ -93,6 +94,26 @@ fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
     rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
 }
 
+/// For every DefId that we create a metadata item for, we include a
+/// serialized copy of its DefKey, which allows us to recreate a path.
+fn encode_def_id_and_key(ecx: &EncodeContext,
+                         rbml_w: &mut Encoder,
+                         def_id: DefId)
+{
+    encode_def_id(rbml_w, def_id);
+    encode_def_key(ecx, rbml_w, def_id);
+}
+
+fn encode_def_key(ecx: &EncodeContext,
+                  rbml_w: &mut Encoder,
+                  def_id: DefId)
+{
+    rbml_w.start_tag(tag_def_key);
+    let def_key = ecx.tcx.map.def_key(def_id);
+    def_key.encode(rbml_w);
+    rbml_w.end_tag();
+}
+
 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
                               ecx: &EncodeContext<'a, 'tcx>,
                               trait_ref: ty::TraitRef<'tcx>,
@@ -115,11 +136,12 @@ fn encode_family(rbml_w: &mut Encoder, c: char) {
 }
 
 pub fn def_to_u64(did: DefId) -> u64 {
-    (did.krate as u64) << 32 | (did.xxx_node as u64)
+    assert!(did.index.as_u32() < u32::MAX);
+    (did.krate as u64) << 32 | (did.index.as_usize() as u64)
 }
 
 pub fn def_to_string(did: DefId) -> String {
-    format!("{}:{}", did.krate, did.xxx_node)
+    format!("{}:{}", did.krate, did.index.as_usize())
 }
 
 fn encode_item_variances(rbml_w: &mut Encoder,
@@ -280,7 +302,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             rbml_w: &mut Encoder,
                             id: NodeId,
                             vis: hir::Visibility,
-                            index: &mut Vec<IndexEntry>) {
+                            index: &mut IndexData) {
     debug!("encode_enum_variant_info(id={})", id);
 
     let mut disr_val = 0;
@@ -297,12 +319,9 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
             }
         }
 
-        index.push(IndexEntry {
-            node: vid.xxx_node,
-            pos: rbml_w.mark_stable_position(),
-        });
+        index.record(vid, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, vid);
+        encode_def_id_and_key(ecx, rbml_w, vid);
         encode_family(rbml_w, match variant.kind() {
             ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
             ty::VariantKind::Dict => 'V'
@@ -522,7 +541,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
                        name: Name,
                        vis: hir::Visibility) {
     rbml_w.start_tag(tag_items_data_item);
-    encode_def_id(rbml_w, ecx.tcx.map.local_def_id(id));
+    encode_def_id_and_key(ecx, rbml_w, ecx.tcx.map.local_def_id(id));
     encode_family(rbml_w, 'm');
     encode_name(rbml_w, name);
     debug!("(encoding info for module) encoding info for module ID {}", id);
@@ -631,21 +650,17 @@ fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
 fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                           rbml_w: &mut Encoder,
                           field: ty::FieldDef<'tcx>,
-                          global_index: &mut Vec<IndexEntry>) {
+                          global_index: &mut IndexData) {
     let nm = field.name;
     let id = ecx.local_id(field.did);
 
-    let pos = rbml_w.mark_stable_position();
-    global_index.push(IndexEntry {
-        node: id,
-        pos: pos,
-    });
+    global_index.record(field.did, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
     debug!("encode_field: encoding {} {}", nm, id);
     encode_struct_field_family(rbml_w, field.vis);
     encode_name(rbml_w, nm);
     encode_bounds_and_type_for_item(rbml_w, ecx, id);
-    encode_def_id(rbml_w, ecx.tcx.map.local_def_id(id));
+    encode_def_id_and_key(ecx, rbml_w, field.did);
 
     let stab = stability::lookup(ecx.tcx, field.did);
     encode_stability(rbml_w, stab);
@@ -657,15 +672,14 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                rbml_w: &mut Encoder,
                                name: Name,
                                ctor_id: NodeId,
-                               index: &mut Vec<IndexEntry>,
+                               index: &mut IndexData,
                                struct_id: NodeId) {
-    index.push(IndexEntry {
-        node: ctor_id,
-        pos: rbml_w.mark_stable_position(),
-    });
+    let ctor_def_id = ecx.tcx.map.local_def_id(ctor_id);
+
+    index.record(ctor_def_id, rbml_w);
 
     rbml_w.start_tag(tag_items_data_item);
-    encode_def_id(rbml_w, ecx.tcx.map.local_def_id(ctor_id));
+    encode_def_id_and_key(ecx, rbml_w, ctor_def_id);
     encode_family(rbml_w, 'o');
     encode_bounds_and_type_for_item(rbml_w, ecx, ctor_id);
     encode_name(rbml_w, name);
@@ -775,7 +789,7 @@ fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                      rbml_w: &mut Encoder,
                                      method_ty: &ty::Method<'tcx>) {
-    encode_def_id(rbml_w, method_ty.def_id);
+    encode_def_id_and_key(ecx, rbml_w, method_ty.def_id);
     encode_name(rbml_w, method_ty.name);
     encode_generics(rbml_w, ecx, &method_ty.generics, &method_ty.predicates,
                     tag_method_ty_generics);
@@ -802,7 +816,7 @@ fn encode_info_for_associated_const(ecx: &EncodeContext,
 
     rbml_w.start_tag(tag_items_data_item);
 
-    encode_def_id(rbml_w, associated_const.def_id);
+    encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
     encode_name(rbml_w, associated_const.name);
     encode_visibility(rbml_w, associated_const.vis);
     encode_family(rbml_w, 'C');
@@ -891,7 +905,7 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
     rbml_w.start_tag(tag_items_data_item);
 
-    encode_def_id(rbml_w, associated_type.def_id);
+    encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
     encode_name(rbml_w, associated_type.name);
     encode_visibility(rbml_w, associated_type.vis);
     encode_family(rbml_w, 'y');
@@ -1000,19 +1014,11 @@ fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
 fn encode_info_for_item(ecx: &EncodeContext,
                         rbml_w: &mut Encoder,
                         item: &hir::Item,
-                        index: &mut Vec<IndexEntry>,
+                        index: &mut IndexData,
                         path: PathElems,
                         vis: hir::Visibility) {
     let tcx = ecx.tcx;
 
-    fn add_to_index(item: &hir::Item, rbml_w: &mut Encoder,
-                    index: &mut Vec<IndexEntry>) {
-        index.push(IndexEntry {
-            node: item.id,
-            pos: rbml_w.mark_stable_position(),
-        });
-    }
-
     debug!("encoding info for item at {}",
            tcx.sess.codemap().span_to_string(item.span));
 
@@ -1021,9 +1027,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
     match item.node {
       hir::ItemStatic(_, m, _) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         if m == hir::MutMutable {
             encode_family(rbml_w, 'b');
         } else {
@@ -1039,9 +1045,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         rbml_w.end_tag();
       }
       hir::ItemConst(_, _) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'C');
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.name);
@@ -1053,9 +1059,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         rbml_w.end_tag();
       }
       hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, FN_FAMILY);
         let tps_len = generics.ty_params.len();
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
@@ -1076,7 +1082,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         rbml_w.end_tag();
       }
       hir::ItemMod(ref m) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         encode_info_for_mod(ecx,
                             rbml_w,
                             m,
@@ -1087,9 +1093,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
                             item.vis);
       }
       hir::ItemForeignMod(ref fm) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'n');
         encode_name(rbml_w, item.name);
         encode_path(rbml_w, path);
@@ -1104,9 +1110,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         rbml_w.end_tag();
       }
       hir::ItemTy(..) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'y');
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.name);
@@ -1116,10 +1122,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
         rbml_w.end_tag();
       }
       hir::ItemEnum(ref enum_definition, _) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
 
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 't');
         encode_item_variances(rbml_w, ecx, item.id);
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
@@ -1154,11 +1160,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
         }
 
         /* Index the class*/
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
 
         /* Now, make an item for the class itself */
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'S');
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
 
@@ -1192,9 +1198,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         }
       }
       hir::ItemDefaultImpl(unsafety, _) => {
-          add_to_index(item, rbml_w, index);
+          index.record(def_id, rbml_w);
           rbml_w.start_tag(tag_items_data_item);
-          encode_def_id(rbml_w, def_id);
+          encode_def_id_and_key(ecx, rbml_w, def_id);
           encode_family(rbml_w, 'd');
           encode_name(rbml_w, item.name);
           encode_unsafety(rbml_w, unsafety);
@@ -1209,9 +1215,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         let impl_items = tcx.impl_items.borrow();
         let items = impl_items.get(&def_id).unwrap();
 
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'i');
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.name);
@@ -1272,10 +1278,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 None
             };
 
-            index.push(IndexEntry {
-                node: trait_item_def_id.def_id().xxx_node,
-                pos: rbml_w.mark_stable_position(),
-            });
+            index.record(trait_item_def_id.def_id(), rbml_w);
 
             match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
                 ty::ConstTraitItem(ref associated_const) => {
@@ -1307,9 +1310,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         }
       }
       hir::ItemTrait(_, _, _, ref ms) => {
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'I');
         encode_item_variances(rbml_w, ecx, item.id);
         let trait_def = tcx.lookup_trait_def(def_id);
@@ -1363,10 +1366,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         for (i, &item_def_id) in r.iter().enumerate() {
             assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
 
-            index.push(IndexEntry {
-                node: item_def_id.def_id().xxx_node,
-                pos: rbml_w.mark_stable_position(),
-            });
+            index.record(item_def_id.def_id(), rbml_w);
 
             rbml_w.start_tag(tag_items_data_item);
 
@@ -1381,7 +1381,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             match trait_item_type {
                 ty::ConstTraitItem(associated_const) => {
                     encode_name(rbml_w, associated_const.name);
-                    encode_def_id(rbml_w, associated_const.def_id);
+                    encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
                     encode_visibility(rbml_w, associated_const.vis);
 
                     let elem = ast_map::PathName(associated_const.name);
@@ -1422,7 +1422,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 }
                 ty::TypeTraitItem(associated_type) => {
                     encode_name(rbml_w, associated_type.name);
-                    encode_def_id(rbml_w, associated_type.def_id);
+                    encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
 
                     let elem = ast_map::PathName(associated_type.name);
                     encode_path(rbml_w,
@@ -1491,16 +1491,15 @@ fn encode_info_for_item(ecx: &EncodeContext,
 fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 rbml_w: &mut Encoder,
                                 nitem: &hir::ForeignItem,
-                                index: &mut Vec<IndexEntry>,
+                                index: &mut IndexData,
                                 path: PathElems,
                                 abi: abi::Abi) {
-    index.push(IndexEntry {
-        node: nitem.id,
-        pos: rbml_w.mark_stable_position(),
-    });
+    let def_id = ecx.tcx.map.local_def_id(nitem.id);
+
+    index.record(def_id, rbml_w);
 
     rbml_w.start_tag(tag_items_data_item);
-    encode_def_id(rbml_w, ecx.tcx.map.local_def_id(nitem.id));
+    encode_def_id_and_key(ecx, rbml_w, def_id);
     encode_visibility(rbml_w, nitem.vis);
     match nitem.node {
       hir::ForeignItemFn(ref fndecl, _) => {
@@ -1534,12 +1533,39 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
     rbml_w.end_tag();
 }
 
-fn my_visit_expr(_e: &hir::Expr) { }
+fn my_visit_expr(expr: &hir::Expr,
+                 rbml_w: &mut Encoder,
+                 ecx: &EncodeContext,
+                 index: &mut IndexData) {
+    match expr.node {
+        hir::ExprClosure(..) => {
+            let def_id = ecx.tcx.map.local_def_id(expr.id);
+
+            index.record(def_id, rbml_w);
+
+            rbml_w.start_tag(tag_items_data_item);
+            encode_def_id_and_key(ecx, rbml_w, def_id);
+
+            rbml_w.start_tag(tag_items_closure_ty);
+            write_closure_type(ecx, rbml_w, &ecx.tcx.tables.borrow().closure_tys[&def_id]);
+            rbml_w.end_tag();
+
+            rbml_w.start_tag(tag_items_closure_kind);
+            ecx.tcx.closure_kind(def_id).encode(rbml_w).unwrap();
+            rbml_w.end_tag();
+
+            ecx.tcx.map.with_path(expr.id, |path| encode_path(rbml_w, path));
+
+            rbml_w.end_tag();
+        }
+        _ => { }
+    }
+}
 
 fn my_visit_item(i: &hir::Item,
                  rbml_w: &mut Encoder,
                  ecx: &EncodeContext,
-                 index: &mut Vec<IndexEntry>) {
+                 index: &mut IndexData) {
     ecx.tcx.map.with_path(i.id, |path| {
         encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
     });
@@ -1548,7 +1574,7 @@ fn my_visit_item(i: &hir::Item,
 fn my_visit_foreign_item(ni: &hir::ForeignItem,
                          rbml_w: &mut Encoder,
                          ecx: &EncodeContext,
-                         index: &mut Vec<IndexEntry>) {
+                         index: &mut IndexData) {
     debug!("writing foreign item {}::{}",
             ecx.tcx.map.path_to_string(ni.id),
             ni.name);
@@ -1564,40 +1590,32 @@ fn my_visit_foreign_item(ni: &hir::ForeignItem,
 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
     rbml_w_for_visit_item: &'a mut Encoder<'b>,
     ecx: &'a EncodeContext<'c,'tcx>,
-    index: &'a mut Vec<IndexEntry>,
+    index: &'a mut IndexData,
 }
 
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_expr(&mut self, ex: &hir::Expr) {
         visit::walk_expr(self, ex);
-        my_visit_expr(ex);
+        my_visit_expr(ex, self.rbml_w_for_visit_item, self.ecx, self.index);
     }
     fn visit_item(&mut self, i: &hir::Item) {
         visit::walk_item(self, i);
-        my_visit_item(i,
-                      self.rbml_w_for_visit_item,
-                      self.ecx,
-                      self.index);
+        my_visit_item(i, self.rbml_w_for_visit_item, self.ecx, self.index);
     }
     fn visit_foreign_item(&mut self, ni: &hir::ForeignItem) {
         visit::walk_foreign_item(self, ni);
-        my_visit_foreign_item(ni,
-                              self.rbml_w_for_visit_item,
-                              self.ecx,
-                              self.index);
+        my_visit_foreign_item(ni, self.rbml_w_for_visit_item, self.ecx, self.index);
     }
 }
 
 fn encode_info_for_items(ecx: &EncodeContext,
                          rbml_w: &mut Encoder,
                          krate: &hir::Crate)
-                         -> Vec<IndexEntry> {
-    let mut index = Vec::new();
+                         -> IndexData {
+    let mut index = IndexData::new(ecx.tcx.map.num_local_def_ids());
+
     rbml_w.start_tag(tag_items_data);
-    index.push(IndexEntry {
-        node: CRATE_NODE_ID,
-        pos: rbml_w.mark_stable_position(),
-    });
+    index.record_index(CRATE_DEF_INDEX, rbml_w);
     encode_info_for_mod(ecx,
                         rbml_w,
                         &krate.module,
@@ -1617,13 +1635,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
     index
 }
 
-
-
-
-fn encode_index(rbml_w: &mut Encoder, index: Vec<IndexEntry>)
-{
+fn encode_index(rbml_w: &mut Encoder, index: IndexData) {
     rbml_w.start_tag(tag_index);
-    index::write_index(index, rbml_w.writer);
+    index.write_index(rbml_w.writer);
     rbml_w.end_tag();
 }
 
@@ -1737,12 +1751,12 @@ fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_lang_items);
 
-    for (i, &def_id) in ecx.tcx.lang_items.items() {
-        if let Some(id) = def_id {
-            if let Some(id) = ecx.tcx.map.as_local_node_id(id) {
+    for (i, &opt_def_id) in ecx.tcx.lang_items.items() {
+        if let Some(def_id) = opt_def_id {
+            if def_id.is_local() {
                 rbml_w.start_tag(tag_lang_items_item);
                 rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
-                rbml_w.wr_tagged_u32(tag_lang_items_item_node_id, id as u32);
+                rbml_w.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32());
                 rbml_w.end_tag();
             }
         }
@@ -1776,7 +1790,10 @@ fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
 
 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     match ecx.tcx.sess.plugin_registrar_fn.get() {
-        Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
+        Some(id) => {
+            let def_id = ecx.tcx.map.local_def_id(id);
+            rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32());
+        }
         None => {}
     }
 }
@@ -1821,24 +1838,26 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
     rbml_w.end_tag();
 }
 
-fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &hir::Crate) {
-    struct StructFieldVisitor<'a, 'b:'a> {
-        rbml_w: &'a mut Encoder<'b>,
+fn encode_struct_field_attrs(ecx: &EncodeContext,
+                             rbml_w: &mut Encoder,
+                             krate: &hir::Crate) {
+    struct StructFieldVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
+        ecx: &'a EncodeContext<'b, 'tcx>,
+        rbml_w: &'a mut Encoder<'c>,
     }
 
-    impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
+    impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'c, 'tcx> {
         fn visit_struct_field(&mut self, field: &hir::StructField) {
             self.rbml_w.start_tag(tag_struct_field);
-            self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
+            let def_id = self.ecx.tcx.map.local_def_id(field.node.id);
+            encode_def_id(self.rbml_w, def_id);
             encode_attributes(self.rbml_w, &field.node.attrs);
             self.rbml_w.end_tag();
         }
     }
 
     rbml_w.start_tag(tag_struct_fields);
-    visit::walk_crate(&mut StructFieldVisitor {
-        rbml_w: rbml_w
-    }, krate);
+    visit::walk_crate(&mut StructFieldVisitor { ecx: ecx, rbml_w: rbml_w }, krate);
     rbml_w.end_tag();
 }
 
@@ -1925,8 +1944,9 @@ fn encode_misc_info(ecx: &EncodeContext,
 // definition (as that's not defined in this crate).
 fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_reachable_ids);
-    for id in ecx.reachable {
-        rbml_w.wr_tagged_u32(tag_reachable_id, *id);
+    for &id in ecx.reachable {
+        let def_id = ecx.tcx.map.local_def_id(id);
+        rbml_w.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32());
     }
     rbml_w.end_tag();
 }
@@ -2139,7 +2159,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
     encode_index(&mut rbml_w, items_index);
     stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
 
-    encode_struct_field_attrs(&mut rbml_w, krate);
+    encode_struct_field_attrs(&ecx, &mut rbml_w, krate);
 
     stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
 
diff --git a/src/librustc/metadata/index.rs b/src/librustc/metadata/index.rs
index b02a9022a7a..c60b789a2f1 100644
--- a/src/librustc/metadata/index.rs
+++ b/src/librustc/metadata/index.rs
@@ -8,143 +8,95 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::def_id::{DefId, DefIndex};
+use rbml;
+use rbml::writer::Encoder;
 use std::io::{Cursor, Write};
 use std::slice;
 use std::u32;
-use syntax::ast::NodeId;
 
-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub struct IndexEntry {
-    pub node: NodeId,
-    pub pos: u64
-}
-
-#[derive(Debug)]
-pub struct IndexArrayEntry {
-    bits: u32,
-    first_pos: u32
+/// As part of the metadata, we generate an index that stores, for
+/// each DefIndex, the position of the corresponding RBML document (if
+/// any).  This is just a big `[u32]` slice, where an entry of
+/// `u32::MAX` indicates that there is no RBML document. This little
+/// struct just stores the offsets within the metadata of the start
+/// and end of this slice. These are actually part of an RBML
+/// document, but for looking things up in the metadata, we just
+/// discard the RBML positioning and jump directly to the data.
+pub struct Index {
+    data_start: usize,
+    data_end: usize,
 }
 
-impl IndexArrayEntry {
-    fn encode_to<W: Write>(&self, b: &mut W) {
-        write_be_u32(b, self.bits);
-        write_be_u32(b, self.first_pos);
+impl Index {
+    /// Given the RBML doc representing the index, save the offests
+    /// for later.
+    pub fn from_rbml(index: rbml::Doc) -> Index {
+        Index { data_start: index.start, data_end: index.end }
     }
 
-    fn decode_from(b: &[u32]) -> Self {
-        IndexArrayEntry {
-            bits: b[0].to_be(),
-            first_pos: b[1].to_be()
+    /// Given the metadata, extract out the offset of a particular
+    /// DefIndex (if any).
+    #[inline(never)]
+    pub fn lookup_item(&self, bytes: &[u8], def_index: DefIndex) -> Option<u32> {
+        let words = bytes_to_words(&bytes[self.data_start..self.data_end]);
+        let index = def_index.as_usize();
+
+        debug!("lookup_item: index={:?} words.len={:?}",
+               index, words.len());
+
+        let position = u32::from_be(words[index]);
+        if position == u32::MAX {
+            debug!("lookup_item: position=u32::MAX");
+            None
+        } else {
+            debug!("lookup_item: position={:?}", position);
+            Some(position)
         }
     }
 }
 
-/// The Item Index
-///
-/// This index maps the NodeId of each item to its location in the
-/// metadata.
-///
-/// The index is a sparse bit-vector consisting of a index-array
-/// and a position-array. Each entry in the index-array handles 32 nodes.
-/// The first word is a bit-array consisting of the nodes that hold items,
-/// the second is the index of the first of the items in the position-array.
-/// If there is a large set of non-item trailing nodes, they can be omitted
-/// from the index-array.
-///
-/// The index is serialized as an array of big-endian 32-bit words.
-/// The first word is the number of items in the position-array.
-/// Then, for each item, its position in the metadata follows.
-/// After that the index-array is stored.
-///
-/// struct index {
-///     u32 item_count;
-///     u32 items[self.item_count];
-///     struct { u32 bits; u32 offset; } positions[..];
-/// }
-pub struct Index {
-    position_start: usize,
-    index_start: usize,
-    index_end: usize,
+/// While we are generating the metadata, we also track the position
+/// of each DefIndex. It is not required that all definitions appear
+/// in the metadata, nor that they are serialized in order, and
+/// therefore we first allocate the vector here and fill it with
+/// `u32::MAX`. Whenever an index is visited, we fill in the
+/// appropriate spot by calling `record_position`. We should never
+/// visit the same index twice.
+pub struct IndexData {
+    positions: Vec<u32>,
 }
 
-pub fn write_index(mut entries: Vec<IndexEntry>, buf: &mut Cursor<Vec<u8>>) {
-    assert!(entries.len() < u32::MAX as usize);
-    entries.sort();
-
-    let mut last_entry = IndexArrayEntry { bits: 0, first_pos: 0 };
-
-    write_be_u32(buf, entries.len() as u32);
-    for &IndexEntry { pos, .. } in &entries {
-        assert!(pos < u32::MAX as u64);
-        write_be_u32(buf, pos as u32);
+impl IndexData {
+    pub fn new(max_index: usize) -> IndexData {
+        IndexData {
+            positions: vec![u32::MAX; max_index]
+        }
     }
 
-    let mut pos_in_index_array = 0;
-    for (i, &IndexEntry { node, .. }) in entries.iter().enumerate() {
-        let (x, s) = (node / 32 as u32, node % 32 as u32);
-        while x > pos_in_index_array {
-            pos_in_index_array += 1;
-            last_entry.encode_to(buf);
-            last_entry = IndexArrayEntry { bits: 0, first_pos: i as u32 };
-        }
-        last_entry.bits |= 1<<s;
+    pub fn record(&mut self, def_id: DefId, encoder: &mut Encoder) {
+        assert!(def_id.is_local());
+        self.record_index(def_id.index, encoder)
     }
-    last_entry.encode_to(buf);
 
-    info!("write_index: {} items, {} array entries",
-          entries.len(), pos_in_index_array);
-}
+    pub fn record_index(&mut self, item: DefIndex, encoder: &mut Encoder) {
+        let item = item.as_usize();
 
-impl Index {
-    fn lookup_index(&self, index: &[u32], i: u32) -> Option<IndexArrayEntry> {
-        let ix = (i as usize)*2;
-        if ix >= index.len() {
-            None
-        } else {
-            Some(IndexArrayEntry::decode_from(&index[ix..ix+2]))
-        }
-    }
+        let position = encoder.mark_stable_position();
 
-    fn item_from_pos(&self, positions: &[u32], pos: u32) -> u32 {
-        positions[pos as usize].to_be()
-    }
+        assert!(position < (u32::MAX as u64));
+        let position = position as u32;
 
-    #[inline(never)]
-    pub fn lookup_item(&self, buf: &[u8], node: NodeId) -> Option<u32> {
-        let index = bytes_to_words(&buf[self.index_start..self.index_end]);
-        let positions = bytes_to_words(&buf[self.position_start..self.index_start]);
-        let (x, s) = (node / 32 as u32, node % 32 as u32);
-        let result = match self.lookup_index(index, x) {
-            Some(IndexArrayEntry { bits, first_pos }) => {
-                let bit = 1<<s;
-                if bits & bit == 0 {
-                    None
-                } else {
-                    let prev_nodes_for_entry = (bits&(bit-1)).count_ones();
-                    Some(self.item_from_pos(
-                        positions,
-                        first_pos+prev_nodes_for_entry))
-                }
-            }
-            None => None // trailing zero
-        };
-        debug!("lookup_item({:?}) = {:?}", node, result);
-        result
+        assert!(self.positions[item] == u32::MAX,
+                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
+                item, self.positions[item], position);
+
+        self.positions[item] = position;
     }
 
-    pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self {
-        let buf = bytes_to_words(&buf[start..end]);
-        let position_count = buf[0].to_be() as usize;
-        let position_len = position_count*4;
-        info!("loaded index - position: {}-{}-{}", start, start+position_len, end);
-        debug!("index contents are {:?}",
-               buf.iter().map(|b| format!("{:08x}", b)).collect::<Vec<_>>().concat());
-        assert!(end-4-start >= position_len);
-        assert_eq!((end-4-start-position_len)%8, 0);
-        Index {
-            position_start: start+4,
-            index_start: start+position_len+4,
-            index_end: end
+    pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) {
+        for &position in &self.positions {
+            write_be_u32(buf, position);
         }
     }
 }
@@ -162,47 +114,3 @@ fn bytes_to_words(b: &[u8]) -> &[u32] {
     assert!(b.len() % 4 == 0);
     unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) }
 }
-
-#[test]
-fn test_index() {
-    let entries = vec![
-        IndexEntry { node: 0, pos: 17 },
-        IndexEntry { node: 31, pos: 29 },
-        IndexEntry { node: 32, pos: 1175 },
-        IndexEntry { node: 191, pos: 21 },
-        IndexEntry { node: 128, pos: 34 },
-        IndexEntry { node: 145, pos: 70 },
-        IndexEntry { node: 305, pos: 93214 },
-        IndexEntry { node: 138, pos: 64 },
-        IndexEntry { node: 129, pos: 53 },
-        IndexEntry { node: 192, pos: 33334 },
-        IndexEntry { node: 200, pos: 80123 },
-    ];
-    let mut c = Cursor::new(vec![]);
-    write_index(entries.clone(), &mut c);
-    let mut buf = c.into_inner();
-    let expected: &[u8] = &[
-        0, 0, 0, 11, // # entries
-        // values:
-        0,0,0,17, 0,0,0,29, 0,0,4,151, 0,0,0,34,
-        0,0,0,53, 0,0,0,64, 0,0,0,70, 0,0,0,21,
-        0,0,130,54, 0,1,56,251, 0,1,108,30,
-        // index:
-        128,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,2,
-        0,0,0,0,0,0,0,3,   0,0,0,0,0,0,0,3,
-        0,2,4,3,0,0,0,3,   128,0,0,0,0,0,0,7,
-        0,0,1,1,0,0,0,8,   0,0,0,0,0,0,0,10,
-        0,0,0,0,0,0,0,10,  0,2,0,0,0,0,0,10
-    ];
-    assert_eq!(buf, expected);
-
-    // insert some junk padding
-    for i in 0..17 { buf.insert(0, i); buf.push(i) }
-    let index = Index::from_buf(&buf, 17, buf.len()-17);
-
-    // test round-trip
-    for i in 0..4096 {
-        assert_eq!(index.lookup_item(&buf, i),
-                   entries.iter().find(|e| e.node == i).map(|n| n.pos as u32));
-    }
-}
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index f023049d78f..4657323c172 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -16,11 +16,9 @@
 
 #![allow(non_camel_case_types)]
 
-pub use self::DefIdSource::*;
-
 use rustc_front::hir;
 
-use middle::def_id::DefId;
+use middle::def_id::{DefId, DefIndex};
 use middle::region;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
@@ -36,32 +34,7 @@ use syntax::parse::token;
 // parse_from_str. Extra parameters are for converting to/from def_ids in the
 // data buffer. Whatever format you choose should not contain pipe characters.
 
-// Def id conversion: when we encounter def-ids, they have to be translated.
-// For example, the crate number must be converted from the crate number used
-// in the library we are reading from into the local crate numbers in use
-// here.  To perform this translation, the type decoder is supplied with a
-// conversion function of type `conv_did`.
-//
-// Sometimes, particularly when inlining, the correct translation of the
-// def-id will depend on where it originated from.  Therefore, the conversion
-// function is given an indicator of the source of the def-id.  See
-// astencode.rs for more information.
-#[derive(Copy, Clone, Debug)]
-pub enum DefIdSource {
-    // Identifies a struct, trait, enum, etc.
-    NominalType,
-
-    // Identifies a type alias (`type X = ...`).
-    TypeWithId,
-
-    // Identifies a region parameter (`fn foo<'X>() { ... }`).
-    RegionParameter,
-
-    // Identifies a closure
-    ClosureSource
-}
-
-pub type DefIdConvert<'a> = &'a mut FnMut(DefIdSource, DefId) -> DefId;
+pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId;
 
 pub struct TyDecoder<'a, 'tcx: 'a> {
     data: &'a [u8],
@@ -183,7 +156,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 ty::BrAnon(id)
             }
             '[' => {
-                let def = self.parse_def(RegionParameter);
+                let def = self.parse_def();
                 let name = token::intern(&self.parse_str(']'));
                 ty::BrNamed(def, name)
             }
@@ -209,7 +182,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             }
             'B' => {
                 assert_eq!(self.next(), '[');
-                let def_id = self.parse_def(NominalType);
+                let def_id = self.parse_def();
                 let space = self.parse_param_space();
                 assert_eq!(self.next(), '|');
                 let index = self.parse_u32();
@@ -309,7 +282,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
     }
 
     pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
-        let def = self.parse_def(NominalType);
+        let def = self.parse_def();
         let substs = self.tcx.mk_substs(self.parse_substs());
         ty::TraitRef {def_id: def, substs: substs}
     }
@@ -338,7 +311,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             'c' => return tcx.types.char,
             't' => {
                 assert_eq!(self.next(), '[');
-                let did = self.parse_def(NominalType);
+                let did = self.parse_def();
                 let substs = self.parse_substs();
                 assert_eq!(self.next(), ']');
                 let def = self.tcx.lookup_adt_def(did);
@@ -385,7 +358,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 return tcx.mk_tup(params);
             }
             'F' => {
-                let def_id = self.parse_def(NominalType);
+                let def_id = self.parse_def();
                 return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(self.parse_bare_fn_ty()));
             }
             'G' => {
@@ -427,13 +400,13 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 return tt;
             }
             '\"' => {
-                let _ = self.parse_def(TypeWithId);
+                let _ = self.parse_def();
                 let inner = self.parse_ty();
                 inner
             }
             'a' => {
                 assert_eq!(self.next(), '[');
-                let did = self.parse_def(NominalType);
+                let did = self.parse_def();
                 let substs = self.parse_substs();
                 assert_eq!(self.next(), ']');
                 let def = self.tcx.lookup_adt_def(did);
@@ -441,7 +414,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             }
             'k' => {
                 assert_eq!(self.next(), '[');
-                let did = self.parse_def(ClosureSource);
+                let did = self.parse_def();
                 let substs = self.parse_substs();
                 let mut tys = vec![];
                 while self.peek() != '.' {
@@ -476,9 +449,9 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
     }
 
-    fn parse_def(&mut self, source: DefIdSource) -> DefId {
+    fn parse_def(&mut self) -> DefId {
         let def_id = parse_defid(self.scan(|c| c == '|'));
-        return (self.conv_def_id)(source, def_id);
+        return (self.conv_def_id)(def_id);
     }
 
     fn parse_uint(&mut self) -> usize {
@@ -581,7 +554,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
             'w' => ty::Predicate::WellFormed(self.parse_ty()),
             'O' => {
-                let def_id = self.parse_def(NominalType);
+                let def_id = self.parse_def();
                 assert_eq!(self.next(), '|');
                 ty::Predicate::ObjectSafe(def_id)
             }
@@ -601,12 +574,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
 
     pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
         let name = self.parse_name(':');
-        let def_id = self.parse_def(NominalType);
+        let def_id = self.parse_def();
         let space = self.parse_param_space();
         assert_eq!(self.next(), '|');
         let index = self.parse_u32();
         assert_eq!(self.next(), '|');
-        let default_def_id = self.parse_def(NominalType);
+        let default_def_id = self.parse_def();
         let default = self.parse_opt(|this| this.parse_ty());
         let object_lifetime_default = self.parse_object_lifetime_default();
 
@@ -623,7 +596,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
 
     pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
         let name = self.parse_name(':');
-        let def_id = self.parse_def(NominalType);
+        let def_id = self.parse_def();
         let space = self.parse_param_space();
         assert_eq!(self.next(), '|');
         let index = self.parse_u32();
@@ -731,11 +704,12 @@ fn parse_defid(buf: &[u8]) -> DefId {
     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
         s.parse::<usize>().ok()
     }) {
-        Some(dn) => dn as ast::NodeId,
+        Some(dn) => dn,
         None => panic!("internal error: parse_defid: id expected, found {:?}",
                        def_part)
     };
-    DefId { krate: crate_num, xxx_node: def_num }
+    let index = DefIndex::new(def_num);
+    DefId { krate: crate_num, index: index }
 }
 
 fn parse_unsafety(c: char) -> hir::Unsafety {