]> git.lizzy.rs Git - rust.git/commitdiff
rustc_metadata: move more RBML tags to auto-serialization.
authorEduard Burtescu <edy.burt@gmail.com>
Mon, 19 Sep 2016 20:49:01 +0000 (23:49 +0300)
committerEduard Burtescu <edy.burt@gmail.com>
Tue, 20 Sep 2016 17:08:02 +0000 (20:08 +0300)
40 files changed:
src/librustc/dep_graph/dep_node.rs
src/librustc/hir/def.rs
src/librustc/hir/map/mod.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/lang_items.rs
src/librustc/session/config.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/ty/context.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc_const_eval/eval.rs
src/librustc_metadata/common.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/csearch.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/index_builder.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/rbml/reader.rs
src/librustc_metadata/rbml/writer.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/collector.rs
src/librustc_trans/meth.rs
src/librustc_trans/mir/constant.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/test.rs
src/librustdoc/visit_lib.rs

index 18179027c25de9a6ef68d5746e73d6b8dace658a..3cf7548e3209a5f209a114150b8ece6f13a80bd6 100644 (file)
@@ -103,18 +103,13 @@ pub enum DepNode<D: Clone + Debug> {
     // table in the tcx (or elsewhere) maps to one of these
     // nodes. Often we map multiple tables to the same node if there
     // is no point in distinguishing them (e.g., both the type and
-    // predicates for an item wind up in `ItemSignature`). Other
-    // times, such as `ImplItems` vs `TraitItemDefIds`, tables which
-    // might be mergable are kept distinct because the sets of def-ids
-    // to which they apply are disjoint, and hence we might as well
-    // have distinct labels for easier debugging.
+    // predicates for an item wind up in `ItemSignature`).
     ImplOrTraitItems(D),
     ItemSignature(D),
     FieldTy(D),
     SizedConstraint(D),
-    TraitItemDefIds(D),
+    ImplOrTraitItemIds(D),
     InherentImpls(D),
-    ImplItems(D),
 
     // The set of impls for a given trait. Ultimately, it would be
     // nice to get more fine-grained here (e.g., to include a
@@ -162,9 +157,8 @@ macro_rules! check {
             ImplOrTraitItems,
             ItemSignature,
             FieldTy,
-            TraitItemDefIds,
+            ImplOrTraitItemIds,
             InherentImpls,
-            ImplItems,
             TraitImpls,
             ReprHints,
         }
@@ -231,9 +225,8 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             ItemSignature(ref d) => op(d).map(ItemSignature),
             FieldTy(ref d) => op(d).map(FieldTy),
             SizedConstraint(ref d) => op(d).map(SizedConstraint),
-            TraitItemDefIds(ref d) => op(d).map(TraitItemDefIds),
+            ImplOrTraitItemIds(ref d) => op(d).map(ImplOrTraitItemIds),
             InherentImpls(ref d) => op(d).map(InherentImpls),
-            ImplItems(ref d) => op(d).map(ImplItems),
             TraitImpls(ref d) => op(d).map(TraitImpls),
             TraitItems(ref d) => op(d).map(TraitItems),
             ReprHints(ref d) => op(d).map(ReprHints),
index b4418ed424ea360ec8f4b5ab185c7f45a701728d..fddf09c990566ab8f8d1e8b92021e19c5e7f3f3e 100644 (file)
@@ -92,7 +92,7 @@ pub fn kind_name(&self) -> &'static str {
 // within.
 pub type ExportMap = NodeMap<Vec<Export>>;
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub struct Export {
     pub name: ast::Name,    // The name of the target.
     pub def_id: DefId, // The definition of the target.
index b728f1cbca097ccf4c605a19b036e52a7f3f6fa8..b351bd427acbc26de10d8a477d7b10473b09ac9a 100644 (file)
@@ -580,22 +580,24 @@ pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem {
         }
     }
 
-    pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData {
+    pub fn expect_variant_data(&self, id: NodeId) -> &'ast VariantData {
         match self.find(id) {
             Some(NodeItem(i)) => {
                 match i.node {
-                    ItemStruct(ref struct_def, _) => struct_def,
-                    _ => bug!("struct ID bound to non-struct")
+                    ItemStruct(ref struct_def, _) |
+                    ItemUnion(ref struct_def, _) => struct_def,
+                    _ => {
+                        bug!("struct ID bound to non-struct {}",
+                             self.node_to_string(id));
+                    }
                 }
             }
-            Some(NodeVariant(variant)) => {
-                if variant.node.data.is_struct() {
-                    &variant.node.data
-                } else {
-                    bug!("struct ID bound to enum variant that isn't struct-like")
-                }
+            Some(NodeStructCtor(data)) => data,
+            Some(NodeVariant(variant)) => &variant.node.data,
+            _ => {
+                bug!("expected struct or variant, found {}",
+                     self.node_to_string(id));
             }
-            _ => bug!("expected struct, found {}", self.node_to_string(id)),
         }
     }
 
index 1d6047579f6cfad9d970dfd974408e4bb7a086d7..52cadd76c64cbeeeb68a66229200185c1509ce6a 100644 (file)
 use hir::map::definitions::DefKey;
 use hir::svh::Svh;
 use middle::lang_items;
-use ty::{self, Ty, TyCtxt, VariantKind};
+use ty::{self, Ty, TyCtxt};
 use mir::repr::Mir;
 use mir::mir_map::MirMap;
 use session::Session;
 use session::config::PanicStrategy;
 use session::search_paths::PathKind;
-use util::nodemap::{FnvHashMap, NodeSet, DefIdMap};
-use std::rc::Rc;
+use util::nodemap::{NodeSet, DefIdMap};
 use std::path::PathBuf;
 use syntax::ast;
 use syntax::attr;
@@ -47,7 +46,6 @@
 use hir;
 use hir::intravisit::Visitor;
 
-pub use self::DefLike::{DlDef, DlField, DlImpl};
 pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown};
 
 // lonely orphan structs and enums looking for a better home
@@ -67,27 +65,17 @@ pub struct CrateSource {
     pub cnum: CrateNum,
 }
 
-#[derive(Copy, Debug, PartialEq, Clone)]
+#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)]
 pub enum LinkagePreference {
     RequireDynamic,
     RequireStatic,
 }
 
-enum_from_u32! {
-    #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-    pub enum NativeLibraryKind {
-        NativeStatic,    // native static library (.a archive)
-        NativeFramework, // OSX-specific
-        NativeUnknown,   // default way to specify a dynamic library
-    }
-}
-
-// Something that a name can resolve to.
-#[derive(Copy, Clone, Debug)]
-pub enum DefLike {
-    DlDef(Def),
-    DlImpl(DefId),
-    DlField
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub enum NativeLibraryKind {
+    NativeStatic,    // native static library (.a archive)
+    NativeFramework, // OSX-specific
+    NativeUnknown,   // default way to specify a dynamic library
 }
 
 /// The data we save and restore about an inlined item or method.  This is not
@@ -110,7 +98,7 @@ pub enum InlinedItemRef<'a> {
 
 #[derive(Copy, Clone)]
 pub struct ChildItem {
-    pub def: DefLike,
+    pub def: Def,
     pub name: ast::Name,
     pub vis: ty::Visibility,
 }
@@ -166,21 +154,15 @@ fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;
 
     // trait info
-    fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId>;
-    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                                  -> Vec<Rc<ty::Method<'tcx>>>;
-    fn trait_item_def_ids(&self, def: DefId)
-                          -> Vec<ty::ImplOrTraitItemId>;
+    fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
 
     // impl info
-    fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>;
+    fn impl_or_trait_items(&self, def_id: DefId) -> Vec<ty::ImplOrTraitItemId>;
     fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                           -> Option<ty::TraitRef<'tcx>>;
-    fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity>;
+    fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity;
     fn custom_coerce_unsized_kind(&self, def: DefId)
                                   -> Option<ty::adjustment::CustomCoerceUnsized>;
-    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                             -> Vec<Rc<ty::AssociatedConst<'tcx>>>;
     fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
 
     // trait/impl-item info
@@ -191,12 +173,10 @@ fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     // flags
     fn is_const_fn(&self, did: DefId) -> bool;
     fn is_defaulted_trait(&self, did: DefId) -> bool;
-    fn is_impl(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
     fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool;
     fn is_foreign_item(&self, did: DefId) -> bool;
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool;
-    fn is_typedef(&self, did: DefId) -> bool;
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: CrateNum)
@@ -218,8 +198,6 @@ fn dylib_dependency_formats(&self, cnum: CrateNum)
     fn original_crate_name(&self, cnum: CrateNum) -> InternedString;
     fn crate_hash(&self, cnum: CrateNum) -> Svh;
     fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString;
-    fn crate_struct_field_attrs(&self, cnum: CrateNum)
-                                -> FnvHashMap<DefId, Vec<ast::Attribute>>;
     fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>;
     fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>;
     fn reachable_ids(&self, cnum: CrateNum) -> Vec<DefId>;
@@ -232,12 +210,10 @@ fn def_index_for_def_key(&self,
                              -> Option<DefIndex>;
     fn def_key(&self, def: DefId) -> hir_map::DefKey;
     fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath>;
-    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind>;
     fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>;
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>;
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
     fn item_children(&self, did: DefId) -> Vec<ChildItem>;
-    fn crate_top_level_items(&self, cnum: CrateNum) -> Vec<ChildItem>;
 
     // misc. metadata
     fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
@@ -344,11 +320,7 @@ fn method_arg_names(&self, did: DefId) -> Vec<String> { bug!("method_arg_names")
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
 
     // trait info
-    fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId> { vec![] }
-    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                                  -> Vec<Rc<ty::Method<'tcx>>> { bug!("provided_trait_methods") }
-    fn trait_item_def_ids(&self, def: DefId)
-                          -> Vec<ty::ImplOrTraitItemId> { bug!("trait_item_def_ids") }
+    fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
     fn def_index_for_def_key(&self,
                              cnum: CrateNum,
                              def: DefKey)
@@ -357,16 +329,14 @@ fn def_index_for_def_key(&self,
     }
 
     // impl info
-    fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
-        { bug!("impl_items") }
+    fn impl_or_trait_items(&self, def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
+        { bug!("impl_or_trait_items") }
     fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                           -> Option<ty::TraitRef<'tcx>> { bug!("impl_trait_ref") }
-    fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity> { bug!("impl_polarity") }
+    fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") }
     fn custom_coerce_unsized_kind(&self, def: DefId)
                                   -> Option<ty::adjustment::CustomCoerceUnsized>
         { bug!("custom_coerce_unsized_kind") }
-    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                             -> Vec<Rc<ty::AssociatedConst<'tcx>>> { bug!("associated_consts") }
     fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
 
     // trait/impl-item info
@@ -377,13 +347,11 @@ fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     // flags
     fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
     fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") }
-    fn is_impl(&self, did: DefId) -> bool { bug!("is_impl") }
     fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
     fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool
         { bug!("is_extern_item") }
     fn is_foreign_item(&self, did: DefId) -> bool { bug!("is_foreign_item") }
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
-    fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") }
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: CrateNum)
@@ -411,9 +379,6 @@ fn original_crate_name(&self, cnum: CrateNum) -> InternedString {
     fn crate_hash(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") }
     fn crate_disambiguator(&self, cnum: CrateNum)
                            -> InternedString { bug!("crate_disambiguator") }
-    fn crate_struct_field_attrs(&self, cnum: CrateNum)
-                                -> FnvHashMap<DefId, Vec<ast::Attribute>>
-        { bug!("crate_struct_field_attrs") }
     fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
         { bug!("plugin_registrar_fn") }
     fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)>
@@ -426,15 +391,12 @@ fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") }
     fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath> {
         bug!("relative_def_path")
     }
-    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { bug!("variant_kind") }
     fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
         { bug!("struct_ctor_def_id") }
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
         { bug!("tuple_struct_definition_if_ctor") }
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
     fn item_children(&self, did: DefId) -> Vec<ChildItem> { bug!("item_children") }
-    fn crate_top_level_items(&self, cnum: CrateNum) -> Vec<ChildItem>
-        { bug!("crate_top_level_items") }
 
     // misc. metadata
     fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
index 9db6ac1dcefd00bb6ff70d314ca4014d53b4cbfb..2c952e9f8634964a0d5ba9ce0307e22495c77a1d 100644 (file)
@@ -470,7 +470,7 @@ fn symbol_is_live(&mut self,
         // This is done to handle the case where, for example, the static
         // method of a private type is used, but the type itself is never
         // called directly.
-        let impl_items = self.tcx.impl_items.borrow();
+        let impl_items = self.tcx.impl_or_trait_item_ids.borrow();
         if let Some(impl_list) =
                 self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) {
             for impl_did in impl_list.iter() {
index d1769d5cbc51bd90011c529b4ba845840014d704..078cce9c49ff4410121b4893e48f31f0eb308fa3 100644 (file)
@@ -43,7 +43,7 @@ macro_rules! language_item_table {
 
 
 enum_from_u32! {
-    #[derive(Copy, Clone, PartialEq, Eq, Hash)]
+    #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
     pub enum LangItem {
         $($variant,)*
     }
index 2009e18f6ee2016c8a404d776d393693fb729ecf..8dd5d4d45f7a40e263319849fdd5f9c80de235f4 100644 (file)
@@ -493,7 +493,7 @@ pub fn is_empty(&self) -> bool {
     }
 }
 
-#[derive(Clone, PartialEq, Hash)]
+#[derive(Clone, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub enum PanicStrategy {
     Unwind,
     Abort,
index 94dba7d12a8c762abd4016416b4600d3911f7cfd..9d7131dc96cc5c31bedf67f55e5e4548288b4b01 100644 (file)
@@ -814,7 +814,7 @@ fn candidate_from_obligation<'o>(&mut self,
     fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
                              -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         if let ImplCandidate(def_id) = candidate {
-            if self.tcx().trait_impl_polarity(def_id) == Some(hir::ImplPolarity::Negative) {
+            if self.tcx().trait_impl_polarity(def_id) == hir::ImplPolarity::Negative {
                 return Err(Unimplemented)
             }
         }
index 13193e1b2d71be0ace5fb78560cce06f5563a110..4339b1a254f2046566e925e7ef0b19cac09994e3 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::cell;
 use std::rc::Rc;
 
 use super::{OverlapError, specializes};
@@ -287,21 +286,10 @@ pub fn is_from_trait(&self) -> bool {
 
     /// Iterate over the items defined directly by the given (impl or trait) node.
     pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeItems<'a, 'gcx> {
-        match *self {
-            Node::Impl(impl_def_id) => {
-                NodeItems::Impl {
-                    tcx: tcx.global_tcx(),
-                    items: cell::Ref::map(tcx.impl_items.borrow(),
-                                          |impl_items| &impl_items[&impl_def_id]),
-                    idx: 0,
-                }
-            }
-            Node::Trait(trait_def_id) => {
-                NodeItems::Trait {
-                    items: tcx.trait_items(trait_def_id).clone(),
-                    idx: 0,
-                }
-            }
+        NodeItems {
+            tcx: tcx.global_tcx(),
+            items: tcx.impl_or_trait_items(self.def_id()),
+            idx: 0,
         }
     }
 
@@ -314,42 +302,23 @@ pub fn def_id(&self) -> DefId {
 }
 
 /// An iterator over the items defined within a trait or impl.
-pub enum NodeItems<'a, 'tcx: 'a> {
-    Impl {
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        items: cell::Ref<'a, Vec<ty::ImplOrTraitItemId>>,
-        idx: usize,
-    },
-    Trait {
-        items: Rc<Vec<ImplOrTraitItem<'tcx>>>,
-        idx: usize,
-    },
+pub struct NodeItems<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    items: Rc<Vec<ty::ImplOrTraitItemId>>,
+    idx: usize
 }
 
 impl<'a, 'tcx> Iterator for NodeItems<'a, 'tcx> {
     type Item = ImplOrTraitItem<'tcx>;
     fn next(&mut self) -> Option<ImplOrTraitItem<'tcx>> {
-        match *self {
-            NodeItems::Impl { tcx, ref items, ref mut idx } => {
-                let items_table = tcx.impl_or_trait_items.borrow();
-                if *idx < items.len() {
-                    let item_def_id = items[*idx].def_id();
-                    let item = items_table[&item_def_id].clone();
-                    *idx += 1;
-                    Some(item)
-                } else {
-                    None
-                }
-            }
-            NodeItems::Trait { ref items, ref mut idx } => {
-                if *idx < items.len() {
-                    let item = items[*idx].clone();
-                    *idx += 1;
-                    Some(item)
-                } else {
-                    None
-                }
-            }
+        if self.idx < self.items.len() {
+            let item_def_id = self.items[self.idx].def_id();
+            let items_table = self.tcx.impl_or_trait_items.borrow();
+            let item = items_table[&item_def_id].clone();
+            self.idx += 1;
+            Some(item)
+        } else {
+            None
         }
     }
 }
index 338ea6b0dd6d4a686105abe40c55db91d83afdbb..0d6beb34c69023944dcc64a8fda12d49455da8a9 100644 (file)
@@ -330,8 +330,8 @@ pub struct GlobalCtxt<'tcx> {
     /// Maps from a trait item to the trait item "descriptor"
     pub impl_or_trait_items: RefCell<DepTrackingMap<maps::ImplOrTraitItems<'tcx>>>,
 
-    /// Maps from a trait def-id to a list of the def-ids of its trait items
-    pub trait_item_def_ids: RefCell<DepTrackingMap<maps::TraitItemDefIds<'tcx>>>,
+    /// Maps from an impl/trait def-id to a list of the def-ids of its items
+    pub impl_or_trait_item_ids: RefCell<DepTrackingMap<maps::ImplOrTraitItemIds<'tcx>>>,
 
     /// A cache for the trait_items() routine; note that the routine
     /// itself pushes the `TraitItems` dependency node.
@@ -392,12 +392,6 @@ pub struct GlobalCtxt<'tcx> {
     /// Methods in these implementations don't need to be exported.
     pub inherent_impls: RefCell<DepTrackingMap<maps::InherentImpls<'tcx>>>,
 
-    /// Maps a DefId of an impl to a list of its items.
-    /// Note that this contains all of the impls that we know about,
-    /// including ones in other crates. It's not clear that this is the best
-    /// way to do it.
-    pub impl_items: RefCell<DepTrackingMap<maps::ImplItems<'tcx>>>,
-
     /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
     /// present in this set can be warned about.
     pub used_unsafe: RefCell<NodeSet>,
@@ -734,13 +728,12 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             rcache: RefCell::new(FnvHashMap()),
             tc_cache: RefCell::new(FnvHashMap()),
             impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
-            trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
+            impl_or_trait_item_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             ty_param_defs: RefCell::new(NodeMap()),
             normalized_cache: RefCell::new(FnvHashMap()),
             lang_items: lang_items,
             inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
-            impl_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             used_unsafe: RefCell::new(NodeSet()),
             used_mut_nodes: RefCell::new(NodeSet()),
             used_trait_imports: RefCell::new(NodeSet()),
@@ -1401,7 +1394,7 @@ pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
 
     pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
         self.trait_items_cache.memoize(trait_did, || {
-            let def_ids = self.trait_item_def_ids(trait_did);
+            let def_ids = self.impl_or_trait_items(trait_did);
             Rc::new(def_ids.iter()
                            .map(|d| self.impl_or_trait_item(d.def_id()))
                            .collect())
index 5772d16c6d43d9abe0359b0e258cf567f960211b..5e029cf98dc6260a8dd02ff325c26c28e6fa2733 100644 (file)
@@ -34,13 +34,13 @@ fn to_dep_node(key: &$key) -> DepNode<DefId> { DepNode::$node_name(*key) }
 dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> }
 dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
 dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> }
-dep_map_ty! { TraitItemDefIds: TraitItemDefIds(DefId) -> Rc<Vec<ty::ImplOrTraitItemId>> }
+dep_map_ty! { ImplOrTraitItemIds: ImplOrTraitItemIds(DefId)
+                                    -> Rc<Vec<ty::ImplOrTraitItemId>> }
 dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option<ty::TraitRef<'tcx>> }
 dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> }
 dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> }
 dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>> }
 dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
-dep_map_ty! { ImplItems: ImplItems(DefId) -> Vec<ty::ImplOrTraitItemId> }
 dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc<Vec<ty::ImplOrTraitItem<'tcx>>> }
 dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
 dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId }
index 59475b4222635f692f6bbf10b8817214df6700e4..3eb9f8593e3af8e9eab9703d76f6a310889f7472 100644 (file)
@@ -50,7 +50,6 @@
 use rustc_const_math::ConstInt;
 
 use hir;
-use hir::{ItemImpl, ItemTrait, PatKind};
 use hir::intravisit::Visitor;
 
 pub use self::sty::{Binder, DebruijnIndex};
@@ -251,7 +250,7 @@ pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
     }
 }
 
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable)]
 pub enum ImplOrTraitItemId {
     ConstTraitItemId(DefId),
     MethodTraitItemId(DefId),
@@ -268,7 +267,7 @@ pub fn def_id(&self) -> DefId {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Copy)]
+#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable)]
 pub enum Visibility {
     /// Visible everywhere (including in other crates).
     Public,
@@ -346,34 +345,12 @@ pub struct Method<'tcx> {
     pub explicit_self: ExplicitSelfCategory<'tcx>,
     pub vis: Visibility,
     pub defaultness: hir::Defaultness,
+    pub has_body: bool,
     pub def_id: DefId,
     pub container: ImplOrTraitItemContainer,
 }
 
 impl<'tcx> Method<'tcx> {
-    pub fn new(name: Name,
-               generics: &'tcx ty::Generics<'tcx>,
-               predicates: GenericPredicates<'tcx>,
-               fty: &'tcx BareFnTy<'tcx>,
-               explicit_self: ExplicitSelfCategory<'tcx>,
-               vis: Visibility,
-               defaultness: hir::Defaultness,
-               def_id: DefId,
-               container: ImplOrTraitItemContainer)
-               -> Method<'tcx> {
-        Method {
-            name: name,
-            generics: generics,
-            predicates: predicates,
-            fty: fty,
-            explicit_self: explicit_self,
-            vis: vis,
-            defaultness: defaultness,
-            def_id: def_id,
-            container: container,
-        }
-    }
-
     pub fn container_id(&self) -> DefId {
         match self.container {
             TraitContainer(id) => id,
@@ -2236,7 +2213,7 @@ pub fn local_var_name_str(self, id: NodeId) -> InternedString {
         match self.map.find(id) {
             Some(ast_map::NodeLocal(pat)) => {
                 match pat.node {
-                    PatKind::Binding(_, ref path1, _) => path1.node.as_str(),
+                    hir::PatKind::Binding(_, ref path1, _) => path1.node.as_str(),
                     _ => {
                         bug!("Variable id {} maps to {:?}, not local", id, pat);
                     },
@@ -2299,84 +2276,19 @@ pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
     }
 
     pub fn provided_trait_methods(self, id: DefId) -> Vec<Rc<Method<'gcx>>> {
-        if let Some(id) = self.map.as_local_node_id(id) {
-            if let ItemTrait(.., ref ms) = self.map.expect_item(id).node {
-                ms.iter().filter_map(|ti| {
-                    if let hir::MethodTraitItem(_, Some(_)) = ti.node {
-                        match self.impl_or_trait_item(self.map.local_def_id(ti.id)) {
-                            MethodTraitItem(m) => Some(m),
-                            _ => {
-                                bug!("provided_trait_methods(): \
-                                      non-method item found from \
-                                      looking up provided method?!")
-                            }
-                        }
-                    } else {
-                        None
-                    }
-                }).collect()
-            } else {
-                bug!("provided_trait_methods: `{:?}` is not a trait", id)
+        self.impl_or_trait_items(id).iter().filter_map(|id| {
+            match self.impl_or_trait_item(id.def_id()) {
+                MethodTraitItem(ref m) if m.has_body => Some(m.clone()),
+                _ => None
             }
-        } else {
-            self.sess.cstore.provided_trait_methods(self.global_tcx(), id)
-        }
+        }).collect()
     }
 
-    pub fn associated_consts(self, id: DefId) -> Vec<Rc<AssociatedConst<'gcx>>> {
+    pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
         if let Some(id) = self.map.as_local_node_id(id) {
             match self.map.expect_item(id).node {
-                ItemTrait(.., ref tis) => {
-                    tis.iter().filter_map(|ti| {
-                        if let hir::ConstTraitItem(..) = ti.node {
-                            match self.impl_or_trait_item(self.map.local_def_id(ti.id)) {
-                                ConstTraitItem(ac) => Some(ac),
-                                _ => {
-                                    bug!("associated_consts(): \
-                                          non-const item found from \
-                                          looking up a constant?!")
-                                }
-                            }
-                        } else {
-                            None
-                        }
-                    }).collect()
-                }
-                ItemImpl(.., ref iis) => {
-                    iis.iter().filter_map(|ii| {
-                        if let hir::ImplItemKind::Const(..) = ii.node {
-                            match self.impl_or_trait_item(self.map.local_def_id(ii.id)) {
-                                ConstTraitItem(ac) => Some(ac),
-                                _ => {
-                                    bug!("associated_consts(): \
-                                          non-const item found from \
-                                          looking up a constant?!")
-                                }
-                            }
-                        } else {
-                            None
-                        }
-                    }).collect()
-                }
-                _ => {
-                    bug!("associated_consts: `{:?}` is not a trait or impl", id)
-                }
-            }
-        } else {
-            self.sess.cstore.associated_consts(self.global_tcx(), id)
-        }
-    }
-
-    pub fn trait_impl_polarity(self, id: DefId) -> Option<hir::ImplPolarity> {
-        if let Some(id) = self.map.as_local_node_id(id) {
-            match self.map.find(id) {
-                Some(ast_map::NodeItem(item)) => {
-                    match item.node {
-                        hir::ItemImpl(_, polarity, ..) => Some(polarity),
-                        _ => None
-                    }
-                }
-                _ => None
+                hir::ItemImpl(_, polarity, ..) => polarity,
+                ref item => bug!("trait_impl_polarity: {:?} not an impl", item)
             }
         } else {
             self.sess.cstore.impl_polarity(id)
@@ -2409,10 +2321,10 @@ pub fn impl_or_trait_item(self, id: DefId) -> ImplOrTraitItem<'gcx> {
                    .expect("missing ImplOrTraitItem in metadata"))
     }
 
-    pub fn trait_item_def_ids(self, id: DefId) -> Rc<Vec<ImplOrTraitItemId>> {
+    pub fn impl_or_trait_items(self, id: DefId) -> Rc<Vec<ImplOrTraitItemId>> {
         lookup_locally_or_in_crate_store(
-            "trait_item_def_ids", id, &self.trait_item_def_ids,
-            || Rc::new(self.sess.cstore.trait_item_def_ids(id)))
+            "impl_or_trait_items", id, &self.impl_or_trait_item_ids,
+            || Rc::new(self.sess.cstore.impl_or_trait_items(id)))
     }
 
     /// Returns the trait-ref corresponding to a given impl, or None if it is
@@ -2423,20 +2335,6 @@ pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
             || self.sess.cstore.impl_trait_ref(self.global_tcx(), id))
     }
 
-    /// Returns whether this DefId refers to an impl
-    pub fn is_impl(self, id: DefId) -> bool {
-        if let Some(id) = self.map.as_local_node_id(id) {
-            if let Some(ast_map::NodeItem(
-                &hir::Item { node: hir::ItemImpl(..), .. })) = self.map.find(id) {
-                true
-            } else {
-                false
-            }
-        } else {
-            self.sess.cstore.is_impl(id)
-        }
-    }
-
     /// Returns a path resolution for node id if it exists, panics otherwise.
     pub fn expect_resolution(self, id: NodeId) -> PathResolution {
         *self.def_map.borrow().get(&id).expect("no def-map entry for node id")
@@ -2699,10 +2597,10 @@ pub fn populate_implementations_for_primitive_if_necessary(self,
         debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
                primitive_def_id);
 
-        let impl_items = self.sess.cstore.impl_items(primitive_def_id);
+        let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id);
 
         // Store the implementation info.
-        self.impl_items.borrow_mut().insert(primitive_def_id, impl_items);
+        self.impl_or_trait_item_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items));
         self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
     }
 
@@ -2728,8 +2626,8 @@ pub fn populate_inherent_implementations_for_type_if_necessary(self,
         let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
         for &impl_def_id in &inherent_impls {
             // Store the implementation info.
-            let impl_items = self.sess.cstore.impl_items(impl_def_id);
-            self.impl_items.borrow_mut().insert(impl_def_id, impl_items);
+            let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
+            self.impl_or_trait_item_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
         }
 
         self.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
@@ -2758,8 +2656,8 @@ pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
             self.record_trait_has_default_impl(trait_id);
         }
 
-        for impl_def_id in self.sess.cstore.implementations_of_trait(trait_id) {
-            let impl_items = self.sess.cstore.impl_items(impl_def_id);
+        for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
+            let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
             let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
 
             // Record the trait->implementation mapping.
@@ -2779,7 +2677,7 @@ pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
             }
 
             // Store the implementation info.
-            self.impl_items.borrow_mut().insert(impl_def_id, impl_items);
+            self.impl_or_trait_item_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
         }
 
         def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
@@ -3012,7 +2910,7 @@ pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, InternedString> {
 }
 
 /// The category of explicit self.
-#[derive(Clone, Copy, Eq, PartialEq, Debug)]
+#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
 pub enum ExplicitSelfCategory<'tcx> {
     Static,
     ByValue,
index ede13aa4dc8b261c3dc8cb8e5c3b9ebed4a2a31b..fe3c498d184bebf0e746a19ef6cd40a5e82ae33a 100644 (file)
@@ -1080,9 +1080,17 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // when constructing the inference context above.
         match selection {
             traits::VtableImpl(ref impl_data) => {
-                match tcx.associated_consts(impl_data.impl_def_id)
-                        .iter().find(|ic| ic.name == ti.name) {
-                    Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
+                let ac = tcx.impl_or_trait_items(impl_data.impl_def_id)
+                    .iter().filter_map(|id| {
+                        match *id {
+                            ty::ConstTraitItemId(def_id) => {
+                                Some(tcx.impl_or_trait_item(def_id))
+                            }
+                            _ => None
+                        }
+                    }).find(|ic| ic.name() == ti.name);
+                match ac {
+                    Some(ic) => lookup_const_by_id(tcx, ic.def_id(), None),
                     None => match ti.node {
                         hir::ConstTraitItem(ref ty, Some(ref expr)) => {
                             Some((&*expr, tcx.ast_ty_to_prim_ty(ty)))
index 123ed11a7a513d9e8ea7dc0d1a1f62b698599f79..94581a3fc89768f6ba02ac695c13c12f391eacb0 100644 (file)
 
 #![allow(non_camel_case_types, non_upper_case_globals)]
 
+use rustc::ty;
+
+#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+pub enum Family {
+    ImmStatic,
+    MutStatic,
+    Fn,
+    Method,
+    AssociatedType,
+    Type,
+    Mod,
+    ForeignMod,
+    Enum,
+    Variant(ty::VariantKind),
+    Impl,
+    DefaultImpl,
+    Trait,
+    Struct(ty::VariantKind),
+    Union,
+    PublicField,
+    InheritedField,
+    Const,
+    AssociatedConst,
+}
+
 // GAP 0x00...0x19
 
 pub const tag_items: usize = 0x100; // top-level only
 
 pub const tag_paths_data_name: usize = 0x20;
 
-pub const tag_def_id: usize = 0x21;
+pub const tag_def_index: usize = 0x21;
 
 pub const tag_items_data: usize = 0x22;
 
@@ -26,9 +51,7 @@
 
 pub const tag_items_data_item_type: usize = 0x25;
 
-// GAP 0x26
-
-pub const tag_items_data_item_variant: usize = 0x27;
+// GAP 0x26, 0x27
 
 pub const tag_items_data_parent_item: usize = 0x28;
 
 
 // The list of crates that this crate depends on
 pub const tag_crate_deps: usize = 0x102; // top-level only
-
-// A single crate dependency
-pub const tag_crate_dep: usize = 0x35;
-
 pub const tag_crate_hash: usize = 0x103; // top-level only
 pub const tag_crate_crate_name: usize = 0x104; // top-level only
 pub const tag_crate_disambiguator: usize = 0x113; // top-level only
 
-pub const tag_crate_dep_crate_name: usize = 0x36;
-pub const tag_crate_dep_hash: usize = 0x37;
-pub const tag_crate_dep_explicitly_linked: usize = 0x38; // top-level only
-
-pub const tag_item_trait_item: usize = 0x3a;
+// GAP 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a
 
 pub const tag_item_trait_ref: usize = 0x3b;
 
 
 // GAP 0x3d, 0x3e, 0x3f, 0x40
 
-pub const tag_item_field: usize = 0x41;
+pub const tag_item_fields: usize = 0x41;
 // GAP 0x42
 pub const tag_item_variances: usize = 0x43;
-/*
-  trait items contain tag_item_trait_item elements,
-  impl items contain tag_item_impl_item elements, and classes
-  have both. That's because some code treats classes like traits,
-  and other code treats them like impls. Because classes can contain
-  both, tag_item_trait_item and tag_item_impl_item have to be two
-  different tags.
- */
-pub const tag_item_impl_item: usize = 0x44;
+// GAP 0x44
 pub const tag_item_trait_method_explicit_self: usize = 0x45;
 
-
-// Reexports are found within module tags. Each reexport contains def_ids
-// and names.
-pub const tag_items_data_item_reexport: usize = 0x46;
-pub const tag_items_data_item_reexport_def_id: usize = 0x47;
-pub const tag_items_data_item_reexport_name: usize = 0x48;
+// GAP 0x46, 0x47, 0x48
 
 // used to encode crate_ctxt side tables
 pub const tag_ast: usize = 0x50;
@@ -98,58 +100,58 @@ impl items contain tag_item_impl_item elements, and classes
 
 // GAP 0x53...0x6a
 
-pub const tag_item_trait_item_sort: usize = 0x70;
+pub const tag_item_trait_item_has_body: usize = 0x70;
 
 pub const tag_crate_triple: usize = 0x105; // top-level only
 
 pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only
 
-// Language items are a top-level directory (for speed). Hierarchy:
-//
-// tag_lang_items
-// - tag_lang_items_item
-//   - tag_lang_items_item_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_index: usize = 0x75;
-pub const tag_lang_items_missing: usize = 0x76;
 
-pub const tag_item_unnamed_field: usize = 0x77;
+// GAP 0x73, 0x74, 0x75
+
+pub const tag_lang_items_missing: usize = 0x76; // top-level only
+
+// GAP 0x77
+
 pub const tag_items_data_item_visibility: usize = 0x78;
-pub const tag_items_data_item_inherent_impl: usize = 0x79;
+pub const tag_items_data_item_inherent_impls: usize = 0x79;
+
 // GAP 0x7a
-pub const tag_mod_child: usize = 0x7b;
+
+// GAP 0x7c
+pub const tag_mod_children: usize = 0x7b;
+
+// GAP 0x108 // top-level only
+
 // GAP 0x7c
 
 // GAP 0x108
 pub const tag_impls: usize = 0x109; // top-level only
-pub const tag_impls_trait: usize = 0x7d;
-pub const tag_impls_trait_impl: usize = 0x7e;
 
-// GAP 0x7f, 0x80, 0x81
+// GAP 0x7d, 0x7e, 0x7f, 0x80, 0x81
 
 pub const tag_native_libraries: usize = 0x10a; // top-level only
-pub const tag_native_libraries_lib: usize = 0x82;
-pub const tag_native_libraries_name: usize = 0x83;
-pub const tag_native_libraries_kind: usize = 0x84;
+
+// GAP 0x82, 0x83, 0x84
 
 pub const tag_plugin_registrar_fn: usize = 0x10b; // top-level only
 
 pub const tag_method_argument_names: usize = 0x85;
-pub const tag_method_argument_name: usize = 0x86;
+
+// GAP 0x86
 
 pub const tag_reachable_ids: usize = 0x10c; // top-level only
-pub const tag_reachable_id: usize = 0x87;
+
+// GAP 0x87
 
 pub const tag_items_data_item_stability: usize = 0x88;
 
 pub const tag_items_data_item_repr: usize = 0x89;
 
-pub const tag_struct_fields: usize = 0x10d; // top-level only
-pub const tag_struct_field: usize = 0x8a;
+// GAP 0x10d // top-level only
+
+// GAP 0x8a
 
 pub const tag_items_data_item_struct_ctor: usize = 0x8b;
 pub const tag_attribute_is_sugared_doc: usize = 0x8c;
@@ -160,10 +162,7 @@ impl items contain tag_item_impl_item elements, and classes
 // GAP 0x90, 0x91, 0x92, 0x93, 0x94
 
 pub const tag_item_predicates: usize = 0x95;
-// GAP 0x96
-
-pub const tag_predicate: usize = 0x97;
-// GAP 0x98, 0x99
+// GAP 0x96, 0x97, 0x98, 0x99
 
 pub const tag_unsafety: usize = 0x9a;
 
@@ -173,15 +172,14 @@ impl items contain tag_item_impl_item elements, and classes
 pub const tag_polarity: usize = 0x9d;
 
 pub const tag_macro_defs: usize = 0x10e; // top-level only
-pub const tag_macro_def: usize = 0x9e;
-pub const tag_macro_def_body: usize = 0x9f;
-pub const tag_macro_def_span_lo: usize = 0xa8;
-pub const tag_macro_def_span_hi: usize = 0xa9;
+
+// GAP 0x9e, 0x9f
 
 pub const tag_paren_sugar: usize = 0xa0;
 
 pub const tag_codemap: usize = 0xa1;
-pub const tag_codemap_filemap: usize = 0xa2;
+
+// GAP 0xa2
 
 pub const tag_item_super_predicates: usize = 0xa3;
 
index 2774ffdf6c77255e2ee3a4f1a4e6a42b1f751258..7b6ed4e6b76489c59a1fe00d2db8af47f712e4bd 100644 (file)
@@ -264,7 +264,7 @@ fn verify_no_symbol_conflicts(&self,
 
         // Check for (potential) conflicts with the local crate
         if self.local_crate_name == crate_name &&
-           self.sess.local_crate_disambiguator() == disambiguator {
+           self.sess.local_crate_disambiguator() == &disambiguator[..] {
             span_fatal!(self.sess, span, E0519,
                         "the current crate is indistinguishable from one of its \
                          dependencies: it has the same crate-name `{}` and was \
@@ -320,7 +320,6 @@ fn register_crate(&mut self,
         let loader::Library { dylib, rlib, metadata } = lib;
 
         let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span);
-        let staged_api = self.is_staged_api(metadata.as_slice());
 
         let cmeta = Rc::new(cstore::CrateMetadata {
             name: name.to_string(),
@@ -332,7 +331,6 @@ fn register_crate(&mut self,
             cnum_map: RefCell::new(cnum_map),
             cnum: cnum,
             codemap_import_info: RefCell::new(vec![]),
-            staged_api: staged_api,
             explicitly_linked: Cell::new(explicitly_linked),
         });
 
@@ -352,16 +350,6 @@ fn register_crate(&mut self,
         (cnum, cmeta, source)
     }
 
-    fn is_staged_api(&self, data: &[u8]) -> bool {
-        let attrs = decoder::get_crate_attributes(data);
-        for attr in &attrs {
-            if attr.name() == "stable" || attr.name() == "unstable" {
-                return true
-            }
-        }
-        false
-    }
-
     fn resolve_crate(&mut self,
                      root: &Option<CratePaths>,
                      ident: &str,
index b291c4927aa3f12e544714ce67f0cef10a56bfff..38b18fa63e3eb40ff0703e56d36974ecf232362b 100644 (file)
 use encoder;
 use loader;
 
-use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate, DefLike};
+use middle::cstore::{InlinedItem, CrateStore, CrateSource, ChildItem, ExternCrate};
 use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
 use rustc::hir::def;
 use middle::lang_items;
-use rustc::ty::{self, Ty, TyCtxt, VariantKind};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 
 use rustc::dep_graph::DepNode;
 use rustc::hir::map::DefKey;
 use rustc::mir::repr::Mir;
 use rustc::mir::mir_map::MirMap;
-use rustc::util::nodemap::{FnvHashMap, NodeSet, DefIdMap};
+use rustc::util::nodemap::{NodeSet, DefIdMap};
 use rustc::session::config::PanicStrategy;
 
-use std::rc::Rc;
 use std::path::PathBuf;
 use syntax::ast;
 use syntax::attr;
@@ -166,42 +165,27 @@ fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>
         result
     }
 
-    fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId>
+    fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
     {
-        self.dep_graph.read(DepNode::MetaData(def_id));
+        if let Some(def_id) = filter {
+            self.dep_graph.read(DepNode::MetaData(def_id));
+        }
         let mut result = vec![];
         self.iter_crate_data(|_, cdata| {
-            decoder::each_implementation_for_trait(cdata, def_id, &mut |iid| {
+            decoder::each_implementation_for_trait(cdata, filter, &mut |iid| {
                 result.push(iid)
             })
         });
         result
     }
 
-    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                                  -> Vec<Rc<ty::Method<'tcx>>>
-    {
-        self.dep_graph.read(DepNode::MetaData(def));
-        let cdata = self.get_crate_data(def.krate);
-        decoder::get_provided_trait_methods(&cdata, def.index, tcx)
-    }
-
-    fn trait_item_def_ids(&self, def: DefId)
-                          -> Vec<ty::ImplOrTraitItemId>
-    {
-        self.dep_graph.read(DepNode::MetaData(def));
-        let cdata = self.get_crate_data(def.krate);
-        decoder::get_trait_item_def_ids(&cdata, def.index)
-    }
-
-    fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
-    {
-        self.dep_graph.read(DepNode::MetaData(impl_def_id));
-        let cdata = self.get_crate_data(impl_def_id.krate);
-        decoder::get_impl_items(&cdata, impl_def_id.index)
+    fn impl_or_trait_items(&self, def_id: DefId) -> Vec<ty::ImplOrTraitItemId> {
+        self.dep_graph.read(DepNode::MetaData(def_id));
+        let cdata = self.get_crate_data(def_id.krate);
+        decoder::get_impl_or_trait_items(&cdata, def_id.index)
     }
 
-    fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity>
+    fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity
     {
         self.dep_graph.read(DepNode::MetaData(def));
         let cdata = self.get_crate_data(def.krate);
@@ -224,14 +208,6 @@ fn custom_coerce_unsized_kind(&self, def: DefId)
         decoder::get_custom_coerce_unsized_kind(&cdata, def.index)
     }
 
-    // FIXME: killme
-    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                             -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
-        self.dep_graph.read(DepNode::MetaData(def));
-        let cdata = self.get_crate_data(def.krate);
-        decoder::get_associated_consts(&cdata, def.index, tcx)
-    }
-
     fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
         self.dep_graph.read(DepNode::MetaData(impl_def));
         let cdata = self.get_crate_data(impl_def.krate);
@@ -266,13 +242,6 @@ fn is_defaulted_trait(&self, trait_def_id: DefId) -> bool
         decoder::is_defaulted_trait(&cdata, trait_def_id.index)
     }
 
-    fn is_impl(&self, did: DefId) -> bool
-    {
-        self.dep_graph.read(DepNode::MetaData(did));
-        let cdata = self.get_crate_data(did.krate);
-        decoder::is_impl(&cdata, did.index)
-    }
-
     fn is_default_impl(&self, impl_did: DefId) -> bool {
         self.dep_graph.read(DepNode::MetaData(impl_did));
         let cdata = self.get_crate_data(impl_did.krate);
@@ -295,12 +264,6 @@ fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool
         self.do_is_statically_included_foreign_item(id)
     }
 
-    fn is_typedef(&self, did: DefId) -> bool {
-        self.dep_graph.read(DepNode::MetaData(did));
-        let cdata = self.get_crate_data(did.krate);
-        decoder::is_typedef(&cdata, did.index)
-    }
-
     fn dylib_dependency_formats(&self, cnum: CrateNum)
                                 -> Vec<(CrateNum, LinkagePreference)>
     {
@@ -310,12 +273,8 @@ fn dylib_dependency_formats(&self, cnum: CrateNum)
 
     fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
     {
-        let mut result = vec![];
         let crate_data = self.get_crate_data(cnum);
-        decoder::each_lang_item(&crate_data, |did, lid| {
-            result.push((did, lid)); true
-        });
-        result
+        decoder::get_lang_items(&crate_data)
     }
 
     fn missing_lang_items(&self, cnum: CrateNum)
@@ -327,7 +286,7 @@ fn missing_lang_items(&self, cnum: CrateNum)
 
     fn is_staged_api(&self, cnum: CrateNum) -> bool
     {
-        self.get_crate_data(cnum).staged_api
+        self.get_crate_data(cnum).is_staged_api()
     }
 
     fn is_explicitly_linked(&self, cnum: CrateNum) -> bool
@@ -355,7 +314,7 @@ fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
 
     fn crate_attrs(&self, cnum: CrateNum) -> Vec<ast::Attribute>
     {
-        decoder::get_crate_attributes(self.get_crate_data(cnum).data())
+        decoder::get_item_attrs(&self.get_crate_data(cnum), CRATE_DEF_INDEX)
     }
 
     fn crate_name(&self, cnum: CrateNum) -> token::InternedString
@@ -382,13 +341,7 @@ fn crate_hash(&self, cnum: CrateNum) -> Svh
     fn crate_disambiguator(&self, cnum: CrateNum) -> token::InternedString
     {
         let cdata = self.get_crate_data(cnum);
-        token::intern_and_get_ident(decoder::get_crate_disambiguator(cdata.data()))
-    }
-
-    fn crate_struct_field_attrs(&self, cnum: CrateNum)
-                                -> FnvHashMap<DefId, Vec<ast::Attribute>>
-    {
-        decoder::get_struct_field_attrs(&self.get_crate_data(cnum))
+        token::intern_and_get_ident(&decoder::get_crate_disambiguator(cdata.data()))
     }
 
     fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
@@ -447,12 +400,6 @@ fn relative_def_path(&self, def: DefId) -> Option<hir_map::DefPath> {
         decoder::def_path(&cdata, def.index)
     }
 
-    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> {
-        self.dep_graph.read(DepNode::MetaData(def_id));
-        let cdata = self.get_crate_data(def_id.krate);
-        decoder::get_variant_kind(&cdata, def_id.index)
-    }
-
     fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
     {
         self.dep_graph.read(DepNode::MetaData(struct_def_id));
@@ -486,17 +433,6 @@ fn item_children(&self, def_id: DefId) -> Vec<ChildItem>
         result
     }
 
-    fn crate_top_level_items(&self, cnum: CrateNum) -> Vec<ChildItem>
-    {
-        let mut result = vec![];
-        let crate_data = self.get_crate_data(cnum);
-        let get_crate_data = |cnum| self.get_crate_data(cnum);
-        decoder::each_top_level_item_of_crate(&crate_data, get_crate_data, |def, name, vis| {
-            result.push(ChildItem { def: def, name: name, vis: vis });
-        });
-        result
-    }
-
     fn maybe_get_item_ast<'a>(&'tcx self,
                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               def_id: DefId)
@@ -726,9 +662,10 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>
 
             let mut bfs_queue = &mut VecDeque::new();
             let mut add_child = |bfs_queue: &mut VecDeque<_>, child: ChildItem, parent: DefId| {
-                let child = match child.def {
-                    DefLike::DlDef(def) if child.vis == ty::Visibility::Public => def.def_id(),
-                    _ => return,
+                let child = if child.vis == ty::Visibility::Public {
+                    child.def.def_id()
+                } else {
+                    return;
                 };
 
                 match visible_parent_map.entry(child) {
@@ -746,10 +683,10 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>
                 }
             };
 
-            let croot = DefId { krate: cnum, index: CRATE_DEF_INDEX };
-            for child in self.crate_top_level_items(cnum) {
-                add_child(bfs_queue, child, croot);
-            }
+            bfs_queue.push_back(DefId {
+                krate: cnum,
+                index: CRATE_DEF_INDEX
+            });
             while let Some(def) = bfs_queue.pop_front() {
                 for child in self.item_children(def) {
                     add_child(bfs_queue, child, def);
@@ -760,4 +697,3 @@ fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>
         visible_parent_map
     }
 }
-
index 388620a2dafd3549057e9f99ed79e7aa4f85c534..7aa4677353bb2260d2bee04087465a32fe382e0e 100644 (file)
@@ -22,7 +22,7 @@
 use loader;
 
 use rustc::dep_graph::DepGraph;
-use rustc::hir::def_id::{CrateNum, DefIndex, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId};
 use rustc::hir::map::DefKey;
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::ExternCrate;
@@ -77,7 +77,6 @@ pub struct CrateMetadata {
     pub cnum_map: RefCell<CrateNumMap>,
     pub cnum: CrateNum,
     pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
-    pub staged_api: bool,
 
     pub index: index::Index,
     pub xref_index: index::DenseIndex,
@@ -300,9 +299,9 @@ pub fn add_used_for_derive_macros(&self, i: &ast::Item) {
 
 impl CrateMetadata {
     pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
-    pub fn name(&self) -> &str { decoder::get_crate_name(self.data()) }
+    pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
     pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
-    pub fn disambiguator(&self) -> &str {
+    pub fn disambiguator(&self) -> String {
         decoder::get_crate_disambiguator(self.data())
     }
     pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
@@ -320,23 +319,30 @@ pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
         }
     }
 
+    pub fn is_staged_api(&self) -> bool {
+        let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX);
+        attrs.iter().any(|attr| {
+            attr.name() == "stable" || attr.name() == "unstable"
+        })
+    }
+
     pub fn is_allocator(&self) -> bool {
-        let attrs = decoder::get_crate_attributes(self.data());
+        let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX);
         attr::contains_name(&attrs, "allocator")
     }
 
     pub fn needs_allocator(&self) -> bool {
-        let attrs = decoder::get_crate_attributes(self.data());
+        let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX);
         attr::contains_name(&attrs, "needs_allocator")
     }
 
     pub fn is_panic_runtime(&self) -> bool {
-        let attrs = decoder::get_crate_attributes(self.data());
+        let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX);
         attr::contains_name(&attrs, "panic_runtime")
     }
 
     pub fn needs_panic_runtime(&self) -> bool {
-        let attrs = decoder::get_crate_attributes(self.data());
+        let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX);
         attr::contains_name(&attrs, "needs_panic_runtime")
     }
 
index 0118cacad182eccacc896b0c686b2605e5c80807..507e6414181b81bedeecde01cdd7ea21b1f58c9d 100644 (file)
 
 #![allow(non_camel_case_types)]
 
-use self::Family::*;
-
 use astencode::decode_inlined_item;
 use cstore::{self, CrateMetadata};
 use common::*;
+use common::Family::*;
 use def_key;
-use encoder::def_to_u64;
 use index;
 
 use rustc::hir::def_id::CRATE_DEF_INDEX;
 use rustc::session::config::PanicStrategy;
 
 use middle::cstore::{InlinedItem, LinkagePreference};
-use middle::cstore::{DefLike, DlDef, DlField, DlImpl};
-use rustc::hir::def::Def;
+use rustc::hir::def::{self, Def};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use middle::lang_items;
 use rustc::ty::{ImplContainer, TraitContainer};
-use rustc::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, VariantKind};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst::Substs;
 
 use rustc_const_math::ConstInt;
 use rbml::reader;
 use rbml;
 use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
-use rustc_serialize as serialize;
 use syntax::attr;
-use syntax::parse::token;
 use syntax::ast::{self, NodeId};
-use syntax::print::pprust;
-use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
+use syntax_pos::{self, Span, BytePos};
 
 pub struct DecodeContext<'a, 'tcx: 'a> {
     pub opaque: opaque::Decoder<'a>,
@@ -94,6 +88,25 @@ pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn cdata(&self) -> &'a cstore::CrateMetadata {
         self.cdata.expect("missing CrateMetadata in DecodeContext")
     }
+
+    pub fn decode<T: Decodable>(&mut self) -> T {
+        T::decode(self).unwrap()
+    }
+
+    /// Iterate over the indices of a sequence.
+    /// This will work solely because of `serialize::opaque`'s
+    /// simple encoding of `n: usize` followed by `n` elements.
+    pub fn seq<T: Decodable>(mut self) -> impl Iterator<Item=T> {
+        (0..self.read_usize().unwrap()).map(move |_| {
+            self.decode()
+        })
+    }
+
+    pub fn seq_mut<'b, T: Decodable>(&'b mut self) -> impl Iterator<Item=T> + 'b {
+        (0..self.read_usize().unwrap()).map(move |_| {
+            self.decode()
+        })
+    }
 }
 
 macro_rules! decoder_methods {
@@ -104,8 +117,8 @@ macro_rules! decoder_methods {
     }
 }
 
-impl<'doc, 'tcx> serialize::Decoder for ::decoder::DecodeContext<'doc, 'tcx> {
-    type Error = <opaque::Decoder<'doc> as serialize::Decoder>::Error;
+impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
+    type Error = <opaque::Decoder<'doc> as Decoder>::Error;
 
     decoder_methods! {
         read_nil -> ();
@@ -311,175 +324,70 @@ fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc {
 }
 
 pub fn load_index(data: &[u8]) -> index::Index {
-    let index = reader::get_doc(rbml::Doc::new(data), tag_index);
-    index::Index::from_rbml(index)
+    index::Index::from_rbml(rbml::Doc::new(data).get(tag_index))
 }
 
 pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
     let doc = rbml::Doc::new(data);
-    reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.to_string())
+    reader::maybe_get_doc(doc, tag_rustc_version).map(|s| {
+        str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string()
+    })
 }
 
 pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
-    let index = reader::get_doc(rbml::Doc::new(data), tag_xref_index);
+    let index = rbml::Doc::new(data).get(tag_xref_index);
     index::DenseIndex::from_buf(index.data, index.start, index.end)
 }
 
 // Go through each item in the metadata and create a map from that
 // item's def-key to the item's DefIndex.
 pub fn load_key_map(data: &[u8]) -> FnvHashMap<DefKey, DefIndex> {
-    let root_doc = rbml::Doc::new(data);
-    let items_doc = reader::get_doc(root_doc, tag_items);
-    let items_data_doc = reader::get_doc(items_doc, tag_items_data);
-    reader::docs(items_data_doc)
-        .filter(|&(tag, _)| tag == tag_items_data_item)
-        .map(|(_, item_doc)| {
-            // load def-key from item
-            let key = item_def_key(item_doc);
-
-            // load def-index from item; we only encode the full def-id,
-            // so just pull out the index
-            let def_id_doc = reader::get_doc(item_doc, tag_def_id);
-            let def_id = untranslated_def_id(def_id_doc);
-            assert!(def_id.is_local()); // local to the crate we are decoding, that is
-
-            (key, def_id.index)
-        })
-        .collect()
-}
-
-#[derive(Clone, Copy, Debug, PartialEq)]
-enum Family {
-    ImmStatic,             // c
-    MutStatic,             // b
-    Fn,                    // f
-    StaticMethod,          // F
-    Method,                // h
-    Type,                  // y
-    Mod,                   // m
-    ForeignMod,            // n
-    Enum,                  // t
-    Variant(VariantKind),  // V, v, w
-    Impl,                  // i
-    DefaultImpl,           // d
-    Trait,                 // I
-    Struct(VariantKind),   // S, s, u
-    Union,                 // U
-    PublicField,           // g
-    InheritedField,        // N
-    Constant,              // C
+    rbml::Doc::new(data).get(tag_items).get(tag_items_data).children().map(|item_doc| {
+        // load def-key from item
+        let key = item_def_key(item_doc);
+
+        // load def-index from item
+        (key, item_doc.get(tag_def_index).decoder().decode())
+    }).collect()
 }
 
 fn item_family(item: rbml::Doc) -> Family {
-    let fam = reader::get_doc(item, tag_items_data_item_family);
-    match reader::doc_as_u8(fam) as char {
-      'C' => Constant,
-      'c' => ImmStatic,
-      'b' => MutStatic,
-      'f' => Fn,
-      'F' => StaticMethod,
-      'h' => Method,
-      'y' => Type,
-      'm' => Mod,
-      'n' => ForeignMod,
-      't' => Enum,
-      'V' => Variant(VariantKind::Struct),
-      'v' => Variant(VariantKind::Tuple),
-      'w' => Variant(VariantKind::Unit),
-      'i' => Impl,
-      'd' => DefaultImpl,
-      'I' => Trait,
-      'S' => Struct(VariantKind::Struct),
-      's' => Struct(VariantKind::Tuple),
-      'u' => Struct(VariantKind::Unit),
-      'U' => Union,
-      'g' => PublicField,
-      'N' => InheritedField,
-       c => bug!("unexpected family char: {}", c)
-    }
+    item.get(tag_items_data_item_family).decoder().decode()
 }
 
 fn item_visibility(item: rbml::Doc) -> ty::Visibility {
     match reader::maybe_get_doc(item, tag_items_data_item_visibility) {
         None => ty::Visibility::Public,
-        Some(visibility_doc) => {
-            match reader::doc_as_u8(visibility_doc) as char {
-                'y' => ty::Visibility::Public,
-                'i' => ty::Visibility::PrivateExternal,
-                _ => bug!("unknown visibility character")
-            }
-        }
-    }
-}
-
-fn fn_constness(item: rbml::Doc) -> hir::Constness {
-    match reader::maybe_get_doc(item, tag_items_data_item_constness) {
-        None => hir::Constness::NotConst,
-        Some(constness_doc) => {
-            match reader::doc_as_u8(constness_doc) as char {
-                'c' => hir::Constness::Const,
-                'n' => hir::Constness::NotConst,
-                _ => bug!("unknown constness character")
-            }
-        }
+        Some(visibility_doc) => visibility_doc.decoder().decode()
     }
 }
 
 fn item_defaultness(item: rbml::Doc) -> hir::Defaultness {
     match reader::maybe_get_doc(item, tag_items_data_item_defaultness) {
         None => hir::Defaultness::Default, // should occur only for default impls on traits
-        Some(defaultness_doc) => {
-            match reader::doc_as_u8(defaultness_doc) as char {
-                'd' => hir::Defaultness::Default,
-                'f' => hir::Defaultness::Final,
-                _ => bug!("unknown defaultness character")
-            }
-        }
-    }
-}
-
-fn item_sort(item: rbml::Doc) -> Option<char> {
-    reader::tagged_docs(item, tag_item_trait_item_sort).nth(0).map(|doc| {
-        doc.as_str().as_bytes()[0] as char
-    })
-}
-
-fn untranslated_def_id(d: rbml::Doc) -> DefId {
-    let id = reader::doc_as_u64(d);
-    DefId {
-        krate: CrateNum::from_u32((id >> 32) as u32),
-        index: DefIndex::from_u32((id & 0xFFFF_FFFF) as u32)
+        Some(defaultness_doc) => defaultness_doc.decoder().decode()
     }
 }
 
-fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId {
-    let def_id = untranslated_def_id(d);
-    translate_def_id(cdata, def_id)
-}
-
 fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option<DefId> {
-    reader::tagged_docs(d, tag_items_data_parent_item).nth(0).map(|did| {
-        translated_def_id(cdata, did)
+    reader::maybe_get_doc(d, tag_items_data_parent_item).map(|did| {
+        let mut dcx = did.decoder();
+        dcx.cdata = Some(cdata);
+        dcx.decode()
     })
 }
 
 fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId {
-    translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item))
+    let mut dcx = d.get(tag_items_data_parent_item).decoder();
+    dcx.cdata = Some(cdata);
+    dcx.decode()
 }
 
 fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId {
-    translated_def_id(cdata, reader::get_doc(d, tag_def_id))
-}
-
-fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> {
-    reader::tagged_docs(d, tag_items_data_item_reexport)
-}
-
-fn variant_disr_val(d: rbml::Doc) -> u64 {
-    let val_doc = reader::get_doc(d, tag_disr_val);
-    reader::with_doc_data(val_doc, |data| {
-        str::from_utf8(data).unwrap().parse().unwrap()
-    })
+    DefId {
+        krate: cdata.cnum,
+        index: d.get(tag_def_index).decoder().decode()
+    }
 }
 
 fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
@@ -492,7 +400,7 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata:
         let mut dcx = tp.decoder();
         dcx.tcx = Some(tcx);
         dcx.cdata = Some(cdata);
-        Decodable::decode(&mut dcx).unwrap()
+        dcx.decode()
     })
 }
 
@@ -501,13 +409,7 @@ fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: C
     let mut dcx = doc.decoder();
     dcx.tcx = Some(tcx);
     dcx.cdata = Some(cdata);
-    Decodable::decode(&mut dcx).unwrap()
-}
-
-fn item_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
-                            -> ty::TraitRef<'tcx> {
-    let tp = reader::get_doc(doc, tag_item_trait_ref);
-    doc_trait_ref(tp, tcx, cdata)
+    dcx.decode()
 }
 
 fn item_name(item: rbml::Doc) -> ast::Name {
@@ -516,95 +418,43 @@ fn item_name(item: rbml::Doc) -> ast::Name {
 
 fn maybe_item_name(item: rbml::Doc) -> Option<ast::Name> {
     reader::maybe_get_doc(item, tag_paths_data_name).map(|name| {
-        let string = name.as_str();
-        token::intern(string)
+        name.decoder().decode()
     })
 }
 
-fn family_to_variant_kind<'tcx>(family: Family) -> Option<ty::VariantKind> {
-    match family {
-        Struct(VariantKind::Struct) | Variant(VariantKind::Struct) | Union =>
-            Some(ty::VariantKind::Struct),
-        Struct(VariantKind::Tuple) | Variant(VariantKind::Tuple) =>
-            Some(ty::VariantKind::Tuple),
-        Struct(VariantKind::Unit) | Variant(VariantKind::Unit) =>
-            Some(ty::VariantKind::Unit),
-        _ => None,
-    }
-}
-
-fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
-    let fam = item_family(item);
-    match fam {
-        Constant  => {
-            // Check whether we have an associated const item.
-            match item_sort(item) {
-                Some('C') | Some('c') => {
-                    DlDef(Def::AssociatedConst(did))
-                }
-                _ => {
-                    // Regular const item.
-                    DlDef(Def::Const(did))
-                }
-            }
-        }
-        ImmStatic => DlDef(Def::Static(did, false)),
-        MutStatic => DlDef(Def::Static(did, true)),
-        Struct(..) => DlDef(Def::Struct(did)),
-        Union => DlDef(Def::Union(did)),
-        Fn        => DlDef(Def::Fn(did)),
-        Method | StaticMethod => {
-            DlDef(Def::Method(did))
+fn item_to_def(cdata: Cmd, item: rbml::Doc, did: DefId) -> Option<Def> {
+    Some(match item_family(item) {
+        Family::Const  => Def::Const(did),
+        Family::AssociatedConst => Def::AssociatedConst(did),
+        Family::ImmStatic => Def::Static(did, false),
+        Family::MutStatic => Def::Static(did, true),
+        Family::Struct(..) => Def::Struct(did),
+        Family::Union => Def::Union(did),
+        Family::Fn  => Def::Fn(did),
+        Family::Method => Def::Method(did),
+        Family::Type => Def::TyAlias(did),
+        Family::AssociatedType => {
+            Def::AssociatedTy(item_require_parent_item(cdata, item), did)
         }
-        Type => {
-            if item_sort(item) == Some('t') {
-                let trait_did = item_require_parent_item(cdata, item);
-                DlDef(Def::AssociatedTy(trait_did, did))
-            } else {
-                DlDef(Def::TyAlias(did))
-            }
+        Family::Mod => Def::Mod(did),
+        Family::ForeignMod => Def::ForeignMod(did),
+        Family::Variant(..) => {
+            Def::Variant(item_require_parent_item(cdata, item), did)
         }
-        Mod => DlDef(Def::Mod(did)),
-        ForeignMod => DlDef(Def::ForeignMod(did)),
-        Variant(..) => {
-            let enum_did = item_require_parent_item(cdata, item);
-            DlDef(Def::Variant(enum_did, did))
+        Family::Trait => Def::Trait(did),
+        Family::Enum => Def::Enum(did),
+
+        Family::Impl |
+        Family::DefaultImpl |
+        Family::PublicField |
+        Family::InheritedField => {
+            return None
         }
-        Trait => DlDef(Def::Trait(did)),
-        Enum => DlDef(Def::Enum(did)),
-        Impl | DefaultImpl => DlImpl(did),
-        PublicField | InheritedField => DlField,
-    }
-}
-
-fn parse_unsafety(item_doc: rbml::Doc) -> hir::Unsafety {
-    let unsafety_doc = reader::get_doc(item_doc, tag_unsafety);
-    if reader::doc_as_u8(unsafety_doc) != 0 {
-        hir::Unsafety::Unsafe
-    } else {
-        hir::Unsafety::Normal
-    }
-}
-
-fn parse_paren_sugar(item_doc: rbml::Doc) -> bool {
-    let paren_sugar_doc = reader::get_doc(item_doc, tag_paren_sugar);
-    reader::doc_as_u8(paren_sugar_doc) != 0
-}
-
-fn parse_polarity(item_doc: rbml::Doc) -> hir::ImplPolarity {
-    let polarity_doc = reader::get_doc(item_doc, tag_polarity);
-    if reader::doc_as_u8(polarity_doc) != 0 {
-        hir::ImplPolarity::Negative
-    } else {
-        hir::ImplPolarity::Positive
-    }
+    })
 }
 
 fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
-    let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
-    reader::tagged_docs(names_doc, tag_associated_type_name)
-        .map(|name_doc| token::intern(name_doc.as_str()))
-        .collect()
+    item_doc.get(tag_associated_type_names).decoder().decode()
 }
 
 pub fn get_trait_def<'a, 'tcx>(cdata: Cmd,
@@ -613,15 +463,16 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd,
 {
     let item_doc = cdata.lookup_item(item_id);
     let generics = doc_generics(item_doc, tcx, cdata);
-    let unsafety = parse_unsafety(item_doc);
+    let unsafety = item_doc.get(tag_unsafety).decoder().decode();
     let associated_type_names = parse_associated_type_names(item_doc);
-    let paren_sugar = parse_paren_sugar(item_doc);
+    let paren_sugar = item_doc.get(tag_paren_sugar).decoder().decode();
+    let trait_ref = doc_trait_ref(item_doc.get(tag_item_trait_ref), tcx, cdata);
     let def_path = def_path(cdata, item_id).unwrap();
 
     ty::TraitDef::new(unsafety,
                       paren_sugar,
                       generics,
-                      item_trait_ref(item_doc, tcx, cdata),
+                      trait_ref,
                       associated_type_names,
                       def_path.deterministic_hash(tcx))
 }
@@ -632,16 +483,19 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd,
                              -> ty::AdtDefMaster<'tcx>
 {
     fn expect_variant_kind(family: Family) -> ty::VariantKind {
-        match family_to_variant_kind(family) {
-            Some(kind) => kind,
+        match family {
+            Struct(kind) | Variant(kind) => kind,
+            Union => ty::VariantKind::Struct,
             _ => bug!("unexpected family: {:?}", family),
         }
     }
     fn get_enum_variants<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec<ty::VariantDefData<'tcx, 'tcx>> {
-        reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
-            let did = translated_def_id(cdata, p);
+        let mut dcx = doc.get(tag_mod_children).decoder();
+        dcx.cdata = Some(cdata);
+
+        dcx.seq().map(|did: DefId| {
             let item = cdata.lookup_item(did.index);
-            let disr = variant_disr_val(item);
+            let disr = item.get(tag_disr_val).decoder().decode();
             ty::VariantDefData {
                 did: did,
                 name: item_name(item),
@@ -652,23 +506,18 @@ fn get_enum_variants<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec<ty::VariantDefData
         }).collect()
     }
     fn get_variant_fields<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec<ty::FieldDefData<'tcx, 'tcx>> {
-        let mut index = 0;
-        reader::tagged_docs(doc, tag_item_field).map(|f| {
-            let ff = item_family(f);
-            match ff {
-                PublicField | InheritedField => {},
-                _ => bug!("expected field, found {:?}", ff)
+        let mut dcx = doc.get(tag_item_fields).decoder();
+        dcx.cdata = Some(cdata);
+
+        dcx.seq().map(|did: DefId| {
+            let f = cdata.lookup_item(did.index);
+            let vis = match item_family(f) {
+                PublicField => ty::Visibility::Public,
+                InheritedField => ty::Visibility::PrivateExternal,
+                _ => bug!()
             };
-            ty::FieldDefData::new(item_def_id(f, cdata),
-                                  item_name(f),
-                                  struct_field_family_to_visibility(ff))
-        }).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| {
-            let ff = item_family(f);
-            let name = token::with_ident_interner(|interner| interner.intern(index.to_string()));
-            index += 1;
-            ty::FieldDefData::new(item_def_id(f, cdata), name,
-                                  struct_field_family_to_visibility(ff))
-        })).collect()
+            ty::FieldDefData::new(did, item_name(f), vis)
+        }).collect()
     }
     fn get_struct_variant<'tcx>(cdata: Cmd,
                                 doc: rbml::Doc,
@@ -692,7 +541,9 @@ fn get_struct_variant<'tcx>(cdata: Cmd,
         Struct(..) => {
             // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
             ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| {
-                translated_def_id(cdata, ctor_doc)
+                let mut dcx = ctor_doc.decoder();
+                dcx.cdata = Some(cdata);
+                dcx.decode()
             });
             (AdtKind::Struct, vec![get_struct_variant(cdata, doc, ctor_did.unwrap_or(did))])
         }
@@ -784,14 +635,14 @@ pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
 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| {
-        Decodable::decode(&mut doc.decoder()).unwrap()
+        doc.decoder().decode()
     })
 }
 
 pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option<attr::Deprecation> {
     let item = cdata.lookup_item(id);
     reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| {
-        Decodable::decode(&mut doc.decoder()).unwrap()
+        doc.decoder().decode()
     })
 }
 
@@ -802,26 +653,21 @@ pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility {
 pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option<DefId> {
     let item = cdata.lookup_item(id);
     reader::maybe_get_doc(item, tag_items_data_parent_impl).map(|doc| {
-        translated_def_id(cdata, doc)
+        let mut dcx = doc.decoder();
+        dcx.cdata = Some(cdata);
+        dcx.decode()
     })
 }
 
 pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
     let item = cdata.lookup_item(id);
     reader::maybe_get_doc(item, tag_items_data_item_repr).map_or(vec![], |doc| {
-        Decodable::decode(&mut doc.decoder()).unwrap()
+        doc.decoder().decode()
     })
 }
 
-pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> Option<hir::ImplPolarity> {
-    let item_doc = cdata.lookup_item(id);
-    let fam = item_family(item_doc);
-    match fam {
-        Family::Impl => {
-            Some(parse_polarity(item_doc))
-        }
-        _ => None
-    }
+pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> hir::ImplPolarity {
+    cdata.lookup_item(id).get(tag_polarity).decoder().decode()
 }
 
 pub fn get_custom_coerce_unsized_kind(
@@ -831,7 +677,7 @@ pub fn get_custom_coerce_unsized_kind(
 {
     let item_doc = cdata.lookup_item(id);
     reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
-        Decodable::decode(&mut kind_doc.decoder()).unwrap()
+        kind_doc.decoder().decode()
     })
 }
 
@@ -841,44 +687,38 @@ pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd,
                                 -> Option<ty::TraitRef<'tcx>>
 {
     let item_doc = cdata.lookup_item(id);
-    let fam = item_family(item_doc);
-    match fam {
-        Family::Impl | Family::DefaultImpl => {
-            reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
-                doc_trait_ref(tp, tcx, cdata)
-            })
-        }
-        _ => None
-    }
+    reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
+        doc_trait_ref(tp, tcx, cdata)
+    })
 }
 
 /// Iterates over the language items in the given crate.
-pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
-    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 index_doc = reader::get_doc(item_doc, tag_lang_items_item_index);
-        let index = DefIndex::from_u32(reader::doc_as_u32(index_doc));
-
-        f(index, id)
-    })
+pub fn get_lang_items(cdata: Cmd) -> Vec<(DefIndex, usize)> {
+    rbml::Doc::new(cdata.data()).get(tag_lang_items).decoder().decode()
 }
 
-fn each_child_of_item_or_crate<F, G>(cdata: Cmd,
-                                     item_doc: rbml::Doc,
-                                     mut get_crate_data: G,
-                                     mut callback: F) where
-    F: FnMut(DefLike, ast::Name, ty::Visibility),
-    G: FnMut(CrateNum) -> Rc<CrateMetadata>,
+
+/// Iterates over each child of the given item.
+pub fn each_child_of_item<F, G>(cdata: Cmd, id: DefIndex,
+                                mut get_crate_data: G,
+                                mut callback: F)
+    where F: FnMut(Def, ast::Name, ty::Visibility),
+          G: FnMut(CrateNum) -> Rc<CrateMetadata>,
 {
-    // Iterate over all children.
-    for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) {
-        let child_def_id = translated_def_id(cdata, child_info_doc);
+    // Find the item.
+    let item_doc = match cdata.get_item(id) {
+        None => return,
+        Some(item_doc) => item_doc,
+    };
+
+    let mut dcx = match reader::maybe_get_doc(item_doc, tag_mod_children) {
+        Some(doc) => doc.decoder(),
+        None => return
+    };
+    dcx.cdata = Some(cdata);
 
+    // Iterate over all children.
+    for child_def_id in dcx.seq_mut::<DefId>() {
         // This item may be in yet another crate if it was the child of a
         // reexport.
         let crate_data = if child_def_id.krate == cdata.cnum {
@@ -894,27 +734,20 @@ fn each_child_of_item_or_crate<F, G>(cdata: Cmd,
         // Get the item.
         if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) {
             // Hand off the item to the callback.
-            let child_name = item_name(child_item_doc);
-            let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
-            let visibility = item_visibility(child_item_doc);
-            callback(def_like, child_name, visibility);
+            if let Some(def) = item_to_def(crate_data, child_item_doc, child_def_id) {
+                let child_name = item_name(child_item_doc);
+                let visibility = item_visibility(child_item_doc);
+                callback(def, child_name, visibility);
+            }
         }
     }
 
-    for reexport_doc in reexports(item_doc) {
-        let def_id_doc = reader::get_doc(reexport_doc,
-                                         tag_items_data_item_reexport_def_id);
-        let child_def_id = translated_def_id(cdata, def_id_doc);
-
-        let name_doc = reader::get_doc(reexport_doc,
-                                       tag_items_data_item_reexport_name);
-        let name = name_doc.as_str();
-
+    for exp in dcx.seq_mut::<def::Export>() {
         // This reexport may be in yet another crate.
-        let crate_data = if child_def_id.krate == cdata.cnum {
+        let crate_data = if exp.def_id.krate == cdata.cnum {
             None
         } else {
-            Some(get_crate_data(child_def_id.krate))
+            Some(get_crate_data(exp.def_id.krate))
         };
         let crate_data = match crate_data {
             Some(ref cdata) => &**cdata,
@@ -922,38 +755,17 @@ fn each_child_of_item_or_crate<F, G>(cdata: Cmd,
         };
 
         // Get the item.
-        if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) {
+        if let Some(child_item_doc) = crate_data.get_item(exp.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
-            // a public re-export.
-            callback(def_like, token::intern(name), ty::Visibility::Public);
+            if let Some(def) = item_to_def(crate_data, child_item_doc, exp.def_id) {
+                // These items have a public visibility because they're part of
+                // a public re-export.
+                callback(def, exp.name, ty::Visibility::Public);
+            }
         }
     }
 }
 
-/// Iterates over each child of the given item.
-pub fn each_child_of_item<F, G>(cdata: Cmd, id: DefIndex, get_crate_data: G, callback: F)
-    where F: FnMut(DefLike, ast::Name, ty::Visibility),
-          G: FnMut(CrateNum) -> Rc<CrateMetadata>,
-{
-    // Find the item.
-    let item_doc = match cdata.get_item(id) {
-        None => return,
-        Some(item_doc) => item_doc,
-    };
-
-    each_child_of_item_or_crate(cdata, item_doc, get_crate_data, callback)
-}
-
-/// Iterates over all the top-level crate items.
-pub fn each_top_level_item_of_crate<F, G>(cdata: Cmd, get_crate_data: G, callback: F)
-    where F: FnMut(DefLike, ast::Name, ty::Visibility),
-          G: FnMut(CrateNum) -> Rc<CrateMetadata>,
-{
-    each_child_of_item(cdata, CRATE_DEF_INDEX, get_crate_data, callback)
-}
-
 pub fn get_item_name(cdata: Cmd, id: DefIndex) -> ast::Name {
     item_name(cdata.lookup_item(id))
 }
@@ -1030,48 +842,31 @@ pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd,
         let mut dcx = mir_doc.decoder();
         dcx.tcx = Some(tcx);
         dcx.cdata = Some(cdata);
-        Decodable::decode(&mut dcx).unwrap()
+        dcx.decode()
     })
 }
 
-fn get_explicit_self<'a, 'tcx>(item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>)
+fn get_explicit_self<'a, 'tcx>(cdata: Cmd, item: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                -> ty::ExplicitSelfCategory<'tcx> {
-    fn get_mutability(ch: u8) -> hir::Mutability {
-        match ch as char {
-            'i' => hir::MutImmutable,
-            'm' => hir::MutMutable,
-            _ => bug!("unknown mutability character: `{}`", ch as char),
-        }
-    }
+    let mut dcx = item.get(tag_item_trait_method_explicit_self).decoder();
+    dcx.cdata = Some(cdata);
+    dcx.tcx = Some(tcx);
 
-    let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
-    let string = explicit_self_doc.as_str();
-
-    let explicit_self_kind = string.as_bytes()[0];
-    match explicit_self_kind as char {
-        's' => ty::ExplicitSelfCategory::Static,
-        'v' => ty::ExplicitSelfCategory::ByValue,
-        '~' => ty::ExplicitSelfCategory::ByBox,
-        // FIXME(#4846) expl. region
-        '&' => {
-            ty::ExplicitSelfCategory::ByReference(
-                tcx.mk_region(ty::ReEmpty),
-                get_mutability(string.as_bytes()[1]))
-        }
-        _ => bug!("unknown self type code: `{}`", explicit_self_kind as char)
-    }
+    dcx.decode()
 }
 
 /// Returns the def IDs of all the items in the given implementation.
-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);
-        match item_sort(doc) {
-            Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
-            Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
-            Some('t') => ty::TypeTraitItemId(def_id),
-            _ => bug!("unknown impl item sort"),
+pub fn get_impl_or_trait_items(cdata: Cmd, impl_id: DefIndex)
+                               -> Vec<ty::ImplOrTraitItemId> {
+    let item = cdata.lookup_item(impl_id);
+    let mut dcx = item.get(tag_mod_children).decoder();
+    dcx.cdata = Some(cdata);
+    dcx.seq().map(|def_id: DefId| {
+        match item_to_def(cdata, cdata.lookup_item(def_id.index), def_id) {
+            Some(Def::AssociatedConst(def_id)) => ty::ConstTraitItemId(def_id),
+            Some(Def::Method(def_id)) => ty::MethodTraitItemId(def_id),
+            Some(Def::AssociatedTy(_, def_id)) => ty::TypeTraitItemId(def_id),
+            def => bug!("get_impl_or_trait_items: invalid def {:?}", def)
         }
     }).collect()
 }
@@ -1092,8 +887,7 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a
     } else {
         return None;
     };
-    let container_doc = cdata.lookup_item(container_id.index);
-    let container = match item_family(container_doc) {
+    let container = match item_family(cdata.lookup_item(container_id.index)) {
         Trait => TraitContainer(container_id),
         _ => ImplContainer(container_id),
     };
@@ -1102,8 +896,8 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a
     let vis = item_visibility(item_doc);
     let defaultness = item_defaultness(item_doc);
 
-    Some(match item_sort(item_doc) {
-        sort @ Some('C') | sort @ Some('c') => {
+    Some(match item_family(item_doc) {
+        Family::AssociatedConst => {
             let ty = doc_type(item_doc, tcx, cdata);
             ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
                 name: name,
@@ -1112,10 +906,10 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a
                 defaultness: defaultness,
                 def_id: def_id,
                 container: container,
-                has_value: sort == Some('C')
+                has_value: item_doc.get(tag_item_trait_item_has_body).decoder().decode(),
             }))
         }
-        Some('r') | Some('p') => {
+        Family::Method => {
             let generics = doc_generics(item_doc, tcx, cdata);
             let predicates = doc_predicates(item_doc, tcx, cdata, tag_item_predicates);
             let ity = tcx.lookup_item_type(def_id).ty;
@@ -1125,19 +919,22 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a
                     "the type {:?} of the method {:?} is not a function?",
                     ity, name)
             };
-            let explicit_self = get_explicit_self(item_doc, tcx);
-
-            ty::MethodTraitItem(Rc::new(ty::Method::new(name,
-                                                        generics,
-                                                        predicates,
-                                                        fty,
-                                                        explicit_self,
-                                                        vis,
-                                                        defaultness,
-                                                        def_id,
-                                                        container)))
+            let explicit_self = get_explicit_self(cdata, item_doc, tcx);
+
+            ty::MethodTraitItem(Rc::new(ty::Method {
+                name: name,
+                generics: generics,
+                predicates: predicates,
+                fty: fty,
+                explicit_self: explicit_self,
+                vis: vis,
+                defaultness: defaultness,
+                has_body: item_doc.get(tag_item_trait_item_has_body).decoder().decode(),
+                def_id: def_id,
+                container: container,
+            }))
         }
-        Some('t') => {
+        Family::AssociatedType => {
             let ty = maybe_doc_type(item_doc, tcx, cdata);
             ty::TypeTraitItem(Rc::new(ty::AssociatedType {
                 name: name,
@@ -1152,84 +949,19 @@ pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a
     })
 }
 
-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| {
-        let def_id = item_def_id(mth, cdata);
-        match item_sort(mth) {
-            Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
-            Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
-            Some('t') => ty::TypeTraitItemId(def_id),
-            _ => bug!("unknown trait item sort"),
-        }
-    }).collect()
-}
-
 pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec<ty::Variance> {
     let item_doc = cdata.lookup_item(id);
-    let variance_doc = reader::get_doc(item_doc, tag_item_variances);
-    Decodable::decode(&mut variance_doc.decoder()).unwrap()
-}
-
-pub fn get_provided_trait_methods<'a, 'tcx>(cdata: Cmd,
-                                            id: DefIndex,
-                                            tcx: TyCtxt<'a, 'tcx, '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.index);
-
-        if item_sort(mth) == Some('p') {
-            let trait_item = get_impl_or_trait_item(cdata, did.index, tcx);
-            if let Some(ty::MethodTraitItem(ref method)) = trait_item {
-                Some((*method).clone())
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }).collect()
-}
-
-pub fn get_associated_consts<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                                       -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
-    let item = cdata.lookup_item(id);
-
-    [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.index);
-
-            match item_sort(ac_doc) {
-                Some('C') | Some('c') => {
-                    let trait_item = get_impl_or_trait_item(cdata, did.index, tcx);
-                    if let Some(ty::ConstTraitItem(ref ac)) = trait_item {
-                        Some((*ac).clone())
-                    } else {
-                        None
-                    }
-                }
-                _ => None
-            }
-        })
-    }).collect()
-}
-
-pub fn get_variant_kind(cdata: Cmd, node_id: DefIndex) -> Option<VariantKind>
-{
-    let item = cdata.lookup_item(node_id);
-    family_to_variant_kind(item_family(item))
+    item_doc.get(tag_item_variances).decoder().decode()
 }
 
 pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option<DefId>
 {
     let item = cdata.lookup_item(node_id);
-    reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).
-        map(|ctor_doc| translated_def_id(cdata, ctor_doc))
+    reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).map(|ctor_doc| {
+        let mut dcx = ctor_doc.decoder();
+        dcx.cdata = Some(cdata);
+        dcx.decode()
+    })
 }
 
 /// If node_id is the constructor of a tuple struct, retrieve the NodeId of
@@ -1239,8 +971,12 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
     -> Option<DefId>
 {
     let item = cdata.lookup_item(node_id);
-    reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor).next().map(|_| {
-        item_require_parent_item(cdata, item)
+    reader::maybe_get_doc(item, tag_items_data_item_is_tuple_struct_ctor).and_then(|doc| {
+        if doc.decoder().decode() {
+            Some(item_require_parent_item(cdata, item))
+        } else {
+            None
+        }
     })
 }
 
@@ -1256,39 +992,18 @@ pub fn get_item_attrs(cdata: Cmd,
     get_attributes(item)
 }
 
-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 def_id = translated_def_id(cdata, reader::get_doc(field, tag_def_id));
-        let attrs = get_attributes(field);
-        (def_id, attrs)
-    }).collect()
-}
-
-fn struct_field_family_to_visibility(family: Family) -> ty::Visibility {
-    match family {
-        PublicField => ty::Visibility::Public,
-        InheritedField => ty::Visibility::PrivateExternal,
-        _ => bug!()
-    }
-}
-
 pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec<ast::Name> {
-    let item = cdata.lookup_item(id);
-    let mut index = 0;
-    reader::tagged_docs(item, tag_item_field).map(|an_item| {
-        item_name(an_item)
-    }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| {
-        let name = token::with_ident_interner(|interner| interner.intern(index.to_string()));
-        index += 1;
-        name
-    })).collect()
+    let mut dcx = cdata.lookup_item(id).get(tag_item_fields).decoder();
+    dcx.cdata = Some(cdata);
+
+    dcx.seq().map(|did: DefId| {
+        item_name(cdata.lookup_item(did.index))
+    }).collect()
 }
 
 fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
     reader::maybe_get_doc(md, tag_attributes).map_or(vec![], |attrs_doc| {
-        let mut attrs = Vec::<ast::Attribute>::decode(&mut attrs_doc.decoder()).unwrap();
+        let mut attrs = attrs_doc.decoder().decode::<Vec<ast::Attribute>>();
 
         // Need new unique IDs: old thread-local IDs won't map to new threads.
         for attr in attrs.iter_mut() {
@@ -1299,22 +1014,6 @@ fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
     })
 }
 
-fn list_crate_attributes(md: rbml::Doc, hash: &Svh,
-                         out: &mut io::Write) -> io::Result<()> {
-    write!(out, "=Crate Attributes ({})=\n", *hash)?;
-
-    let r = get_attributes(md);
-    for attr in &r {
-        write!(out, "{}\n", pprust::attribute_to_string(attr))?;
-    }
-
-    write!(out, "\n\n")
-}
-
-pub fn get_crate_attributes(data: &[u8]) -> Vec<ast::Attribute> {
-    get_attributes(rbml::Doc::new(data))
-}
-
 #[derive(Clone)]
 pub struct CrateDep {
     pub cnum: CrateNum,
@@ -1324,19 +1023,9 @@ pub struct CrateDep {
 }
 
 pub fn get_crate_deps(data: &[u8]) -> Vec<CrateDep> {
-    let cratedoc = rbml::Doc::new(data);
-    let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
+    let dcx = rbml::Doc::new(data).get(tag_crate_deps).decoder();
 
-    fn docstr(doc: rbml::Doc, tag_: usize) -> String {
-        let d = reader::get_doc(doc, tag_);
-        d.as_str().to_string()
-    }
-
-    reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| {
-        let name = docstr(depdoc, tag_crate_dep_crate_name);
-        let hash = Svh::new(reader::doc_as_u64(reader::get_doc(depdoc, tag_crate_dep_hash)));
-        let doc = reader::get_doc(depdoc, tag_crate_dep_explicitly_linked);
-        let explicitly_linked = reader::doc_as_u8(doc) != 0;
+    dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| {
         CrateDep {
             cnum: CrateNum::new(crate_num + 1),
             name: name,
@@ -1358,63 +1047,39 @@ fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> {
 pub fn maybe_get_crate_hash(data: &[u8]) -> Option<Svh> {
     let cratedoc = rbml::Doc::new(data);
     reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| {
-        Svh::new(reader::doc_as_u64(doc))
+        doc.decoder().decode()
     })
 }
 
 pub fn get_crate_hash(data: &[u8]) -> Svh {
-    let cratedoc = rbml::Doc::new(data);
-    let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
-    Svh::new(reader::doc_as_u64(hashdoc))
+    rbml::Doc::new(data).get(tag_crate_hash).decoder().decode()
 }
 
-pub fn maybe_get_crate_name(data: &[u8]) -> Option<&str> {
+pub fn maybe_get_crate_name(data: &[u8]) -> Option<String> {
     let cratedoc = rbml::Doc::new(data);
     reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| {
-        doc.as_str()
+        doc.decoder().decode()
     })
 }
 
-pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
-    let crate_doc = rbml::Doc::new(data);
-    let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
-    let slice: &'a str = disambiguator_doc.as_str();
-    slice
+pub fn get_crate_disambiguator(data: &[u8]) -> String {
+    rbml::Doc::new(data).get(tag_crate_disambiguator).decoder().decode()
 }
 
 pub fn get_crate_triple(data: &[u8]) -> Option<String> {
     let cratedoc = rbml::Doc::new(data);
     let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
-    triple_doc.map(|s| s.as_str().to_string())
+    triple_doc.map(|s| s.decoder().decode())
 }
 
-pub fn get_crate_name(data: &[u8]) -> &str {
+pub fn get_crate_name(data: &[u8]) -> String {
     maybe_get_crate_name(data).expect("no crate name in crate")
 }
 
 pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> {
-    let hash = get_crate_hash(bytes);
-    let md = rbml::Doc::new(bytes);
-    list_crate_attributes(md, &hash, out)?;
     list_crate_deps(bytes, out)
 }
 
-// Translates a def_id from an external crate to a def_id for the current
-// compilation environment. We use this when trying to load types from
-// external crates - if those types further refer to types in other crates
-// then we must translate the crate number from that encoded in the external
-// 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, index: did.index };
-    }
-
-    DefId {
-        krate: cdata.cnum_map.borrow()[did.krate],
-        index: did.index
-    }
-}
-
 // Translate a DefId from the current compilation environment to a DefId
 // for an external crate.
 fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
@@ -1433,32 +1098,41 @@ pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
     where F: FnMut(DefId),
 {
     let item_doc = cdata.lookup_item(id);
-    for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl) {
-        if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() {
-            callback(item_def_id(impl_doc, cdata));
-        }
+    let mut dcx = item_doc.get(tag_items_data_item_inherent_impls).decoder();
+    dcx.cdata = Some(cdata);
+
+    for impl_def_id in dcx.seq() {
+        callback(impl_def_id);
     }
 }
 
 pub fn each_implementation_for_trait<F>(cdata: Cmd,
-                                        def_id: DefId,
+                                        filter: Option<DefId>,
                                         mut callback: F) where
     F: FnMut(DefId),
 {
     // Do a reverse lookup beforehand to avoid touching the crate_num
     // hash map in the loop below.
-    if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) {
-        let def_id_u64 = def_to_u64(crate_local_did);
+    let filter = match filter.map(|def_id| reverse_translate_def_id(cdata, def_id)) {
+        Some(Some(def_id)) => Some(def_id),
+        Some(None) => return,
+        None => None
+    };
+
+    // FIXME(eddyb) Make this O(1) instead of O(n).
+    for trait_doc in rbml::Doc::new(cdata.data()).get(tag_impls).children() {
+        let mut dcx = trait_doc.decoder();
+        dcx.cdata = Some(cdata);
 
-        let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
-        for trait_doc in reader::tagged_docs(impls_doc, tag_impls_trait) {
-            let trait_def_id = reader::get_doc(trait_doc, tag_def_id);
-            if reader::doc_as_u64(trait_def_id) != def_id_u64 {
+        let (krate, index) = dcx.decode();
+        if let Some(local_did) = filter {
+            if (local_did.krate.as_u32(), local_did.index) != (krate, index) {
                 continue;
             }
-            for impl_doc in reader::tagged_docs(trait_doc, tag_impls_trait_impl) {
-                callback(translated_def_id(cdata, impl_doc));
-            }
+        }
+
+        for impl_def_id in dcx.seq() {
+            callback(impl_def_id);
         }
     }
 }
@@ -1479,33 +1153,20 @@ pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option<DefId> {
 
 pub fn get_native_libraries(cdata: Cmd)
                             -> Vec<(cstore::NativeLibraryKind, String)> {
-    let libraries = reader::get_doc(rbml::Doc::new(cdata.data()),
-                                    tag_native_libraries);
-    reader::tagged_docs(libraries, tag_native_libraries_lib).map(|lib_doc| {
-        let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
-        let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
-        let kind: cstore::NativeLibraryKind =
-            cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
-        let name = name_doc.as_str().to_string();
-        (kind, name)
-    }).collect()
+    rbml::Doc::new(cdata.data()).get(tag_native_libraries).decoder().decode()
 }
 
 pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> {
     reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
-        .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc)))
+        .map(|doc| doc.decoder().decode())
 }
 
 pub fn each_exported_macro<F>(data: &[u8], mut f: F) where
     F: FnMut(ast::Name, Vec<ast::Attribute>, Span, String) -> bool,
 {
-    let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
-    for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
-        let name = item_name(macro_doc);
-        let attrs = get_attributes(macro_doc);
-        let span = get_macro_span(macro_doc);
-        let body = reader::get_doc(macro_doc, tag_macro_def_body);
-        if !f(name, attrs, span, body.as_str().to_string()) {
+    let dcx = rbml::Doc::new(data).get(tag_macro_defs).decoder();
+    for (name, attrs, span, body) in dcx.seq() {
+        if !f(name, attrs, span, body) {
             break;
         }
     }
@@ -1513,86 +1174,52 @@ pub fn each_exported_macro<F>(data: &[u8], mut f: F) where
 
 pub fn get_derive_registrar_fn(data: &[u8]) -> Option<DefIndex> {
     reader::maybe_get_doc(rbml::Doc::new(data), tag_macro_derive_registrar)
-        .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc)))
-}
-
-pub fn get_macro_span(doc: rbml::Doc) -> Span {
-    let lo_doc = reader::get_doc(doc, tag_macro_def_span_lo);
-    let lo = BytePos(reader::doc_as_u32(lo_doc));
-    let hi_doc = reader::get_doc(doc, tag_macro_def_span_hi);
-    let hi = BytePos(reader::doc_as_u32(hi_doc));
-    return Span { lo: lo, hi: hi, expn_id: NO_EXPANSION };
+        .map(|doc| doc.decoder().decode())
 }
 
 pub fn get_dylib_dependency_formats(cdata: Cmd)
     -> Vec<(CrateNum, LinkagePreference)>
 {
-    let formats = reader::get_doc(rbml::Doc::new(cdata.data()),
-                                  tag_dylib_dependency_formats);
-    let mut result = Vec::new();
-
-    debug!("found dylib deps: {}", formats.as_str());
-    for spec in formats.as_str().split(',') {
-        if spec.is_empty() { continue }
-        let mut split = spec.split(':');
-        let cnum = split.next().unwrap();
-        let link = split.next().unwrap();
-        let cnum = CrateNum::new(cnum.parse().unwrap());
-        let cnum = cdata.cnum_map.borrow()[cnum];
-        result.push((cnum, if link == "d" {
-            LinkagePreference::RequireDynamic
-        } else {
-            LinkagePreference::RequireStatic
-        }));
-    }
-    return result;
-}
+    let dcx = rbml::Doc::new(cdata.data()).get(tag_dylib_dependency_formats).decoder();
 
-pub fn get_missing_lang_items(cdata: Cmd)
-    -> Vec<lang_items::LangItem>
-{
-    let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_lang_items);
-    reader::tagged_docs(items, tag_lang_items_missing).map(|missing_docs| {
-        lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap()
+    dcx.seq::<Option<_>>().enumerate().flat_map(|(i, link)| {
+        let cnum = CrateNum::new(i + 1);
+        link.map(|link| (cdata.cnum_map.borrow()[cnum], link))
     }).collect()
 }
 
+pub fn get_missing_lang_items(cdata: Cmd) -> Vec<lang_items::LangItem> {
+    rbml::Doc::new(cdata.data()).get(tag_lang_items_missing).decoder().decode()
+}
+
 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) => {
-            reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| {
-                name_doc.as_str().to_string()
-            }).collect()
-        },
+        Some(args_doc) => args_doc.decoder().decode(),
         None => vec![],
     }
 }
 
 pub fn get_reachable_ids(cdata: Cmd) -> Vec<DefId> {
-    let items = reader::get_doc(rbml::Doc::new(cdata.data()),
-                                tag_reachable_ids);
-    reader::tagged_docs(items, tag_reachable_id).map(|doc| {
+    let dcx = rbml::Doc::new(cdata.data()).get(tag_reachable_ids).decoder();
+
+    dcx.seq().map(|index| {
         DefId {
             krate: cdata.cnum,
-            index: DefIndex::from_u32(reader::doc_as_u32(doc)),
+            index: index,
         }
     }).collect()
 }
 
-pub fn is_typedef(cdata: Cmd, id: DefIndex) -> bool {
-    let item_doc = cdata.lookup_item(id);
-    match item_family(item_doc) {
-        Type => true,
-        _ => false,
-    }
-}
-
 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,
-        hir::Constness::NotConst => false,
+    match reader::maybe_get_doc(cdata.lookup_item(id), tag_items_data_item_constness) {
+        None => false,
+        Some(doc) => {
+            match doc.decoder().decode() {
+                hir::Constness::Const => true,
+                hir::Constness::NotConst => false,
+            }
+        }
     }
 }
 
@@ -1628,40 +1255,15 @@ pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool {
     item_family(parent_item_doc) == ForeignMod
 }
 
-pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
-    let item_doc = cdata.lookup_item(id);
-    match item_family(item_doc) {
-        Impl => true,
-        _ => false,
-    }
-}
-
 fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           cdata: Cmd)
                           -> &'tcx ty::Generics<'tcx>
 {
-    let mut dcx = reader::get_doc(base_doc, tag_item_generics).decoder();
-    dcx.tcx = Some(tcx);
-    dcx.cdata = Some(cdata);
-    tcx.alloc_generics(Decodable::decode(&mut dcx).unwrap())
-}
-
-fn doc_predicate<'a, 'tcx>(cdata: Cmd,
-                           doc: rbml::Doc,
-                           tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                           -> ty::Predicate<'tcx>
-{
-    let predicate_pos = cdata.xref_index.lookup(
-        cdata.data(), reader::doc_as_u32(doc)).unwrap() as usize;
-    let mut dcx = rbml::Doc {
-        data: cdata.data(),
-        start: predicate_pos,
-        end: cdata.data().len(),
-    }.decoder();
+    let mut dcx = base_doc.get(tag_item_generics).decoder();
     dcx.tcx = Some(tcx);
     dcx.cdata = Some(cdata);
-    Decodable::decode(&mut dcx).unwrap()
+    tcx.alloc_generics(dcx.decode())
 }
 
 fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
@@ -1670,51 +1272,50 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
                             tag: usize)
                             -> ty::GenericPredicates<'tcx>
 {
-    let doc = reader::get_doc(base_doc, tag);
+    let mut dcx = base_doc.get(tag).decoder();
+    dcx.cdata = Some(cdata);
 
     ty::GenericPredicates {
-        parent: item_parent_item(cdata, doc),
-        predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| {
-            doc_predicate(cdata, predicate_doc, tcx)
+        parent: dcx.decode(),
+        predicates: dcx.seq().map(|offset| {
+            let predicate_pos = cdata.xref_index.lookup(
+                cdata.data(), offset).unwrap() as usize;
+            let mut dcx = rbml::Doc {
+                data: cdata.data(),
+                start: predicate_pos,
+                end: cdata.data().len(),
+            }.decoder();
+            dcx.tcx = Some(tcx);
+            dcx.cdata = Some(cdata);
+            dcx.decode()
         }).collect()
     }
 }
 
 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
+    cdata.lookup_item(trait_id).get(tag_defaulted_trait).decoder().decode()
 }
 
 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
+    item_family(cdata.lookup_item(impl_id)) == Family::DefaultImpl
 }
 
 pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<syntax_pos::FileMap> {
-    let crate_doc = rbml::Doc::new(metadata);
-    let cm_doc = reader::get_doc(crate_doc, tag_codemap);
-
-    reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| {
-        Decodable::decode(&mut filemap_doc.decoder()).unwrap()
-    }).collect()
+    rbml::Doc::new(metadata).get(tag_codemap).decoder().decode()
 }
 
 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);
-    ty::ClosureKind::decode(&mut closure_kind_doc.decoder()).unwrap()
+    cdata.lookup_item(closure_id).get(tag_items_closure_kind).decoder().decode()
 }
 
 pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, '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);
+    let closure_ty_doc = closure_doc.get(tag_items_closure_ty);
     let mut dcx = closure_ty_doc.decoder();
     dcx.tcx = Some(tcx);
     dcx.cdata = Some(cdata);
-    Decodable::decode(&mut dcx).unwrap()
+    dcx.decode()
 }
 
 pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey {
@@ -1726,10 +1327,8 @@ pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey {
 fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
     match reader::maybe_get_doc(item_doc, tag_def_key) {
         Some(def_key_doc) => {
-            let simple_key = def_key::DefKey::decode(&mut def_key_doc.decoder()).unwrap();
-            let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| {
-                token::intern(name.as_str()).as_str()
-            });
+            let simple_key = def_key_doc.decoder().decode();
+            let name = maybe_item_name(item_doc).map(|name| name.as_str());
             def_key::recover_def_key(simple_key, name)
         }
         None => {
@@ -1753,11 +1352,5 @@ pub fn def_path(cdata: Cmd, id: DefIndex) -> Option<hir_map::DefPath> {
 }
 
 pub fn get_panic_strategy(data: &[u8]) -> PanicStrategy {
-    let crate_doc = rbml::Doc::new(data);
-    let strat_doc = reader::get_doc(crate_doc, tag_panic_strategy);
-    match reader::doc_as_u8(strat_doc) {
-        b'U' => PanicStrategy::Unwind,
-        b'A' => PanicStrategy::Abort,
-        b => panic!("unknown panic strategy in metadata: {}", b),
-    }
+    rbml::Doc::new(data).get(tag_panic_strategy).decoder().decode()
 }
index e414275f8b4258482bb1bf197ac6d68362ff563d..7b4a6972d221be6241c52074d922db396b68ca89 100644 (file)
@@ -20,7 +20,7 @@
 use def_key;
 use index::{self, IndexData};
 
-use middle::cstore::{InlinedItemRef, LinkMeta};
+use middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference};
 use rustc::hir::def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use middle::dependency_format::Linkage;
 use rustc::traits::specialization_graph;
 use rustc::ty::{self, Ty, TyCtxt};
 
-use rustc::hir::svh::Svh;
 use rustc::mir::mir_map::MirMap;
-use rustc::session::config::{self, PanicStrategy, CrateTypeRustcMacro};
+use rustc::session::config::{self, CrateTypeRustcMacro};
 use rustc::util::nodemap::{FnvHashMap, NodeSet};
 
 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
-use rustc_serialize as serialize;
 use std::cell::RefCell;
 use std::intrinsics;
 use std::io::prelude::*;
 use std::io::Cursor;
+use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::rc::Rc;
 use std::u32;
 use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID};
 use syntax::attr;
 use syntax;
-use syntax_pos::BytePos;
 use rbml;
 
 use rustc::hir::{self, PatKind};
@@ -53,7 +51,7 @@
 use rustc::hir::intravisit;
 use rustc::hir::map::DefKey;
 
-use super::index_builder::{FromId, IndexBuilder, ItemContentBuilder, Untracked, XRef};
+use super::index_builder::{FromId, IndexBuilder, Untracked};
 
 pub struct EncodeContext<'a, 'tcx: 'a> {
     rbml_w: rbml::writer::Encoder<'a>,
@@ -61,11 +59,17 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     reexports: &'a def::ExportMap,
     link_meta: &'a LinkMeta,
     cstore: &'a cstore::CStore,
-    type_shorthands: RefCell<FnvHashMap<Ty<'tcx>, usize>>,
     reachable: &'a NodeSet,
     mir_map: &'a MirMap<'tcx>,
+
+    type_shorthands: RefCell<FnvHashMap<Ty<'tcx>, usize>>,
+    xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
 }
 
+/// "interned" entries referenced by id
+#[derive(PartialEq, Eq, Hash)]
+enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
+
 impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> {
     type Target = rbml::writer::Encoder<'a>;
     fn deref(&self) -> &Self::Target {
@@ -87,8 +91,8 @@ macro_rules! encoder_methods {
     }
 }
 
-impl<'a, 'tcx> serialize::Encoder for ::encoder::EncodeContext<'a, 'tcx> {
-    type Error = <opaque::Encoder<'a> as serialize::Encoder>::Error;
+impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
+    type Error = <opaque::Encoder<'a> as Encoder>::Error;
 
     fn emit_nil(&mut self) -> Result<(), Self::Error> {
         Ok(())
@@ -146,12 +150,35 @@ fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
     }
 }
 
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+    fn seq<I, F, T>(&mut self, iter: I, mut f: F)
+    where I: IntoIterator,
+          I::IntoIter: ExactSizeIterator,
+          F: FnMut(&mut Self, I::Item) -> T,
+          T: Encodable {
+        let iter = iter.into_iter();
+        self.emit_seq(iter.len(), move |ecx| {
+            for (i, elem) in iter.enumerate() {
+                ecx.emit_seq_elt(i, |ecx| {
+                    f(ecx, elem).encode(ecx)
+                })?;
+            }
+            Ok(())
+        }).unwrap();
+    }
+}
+
 fn encode_name(ecx: &mut EncodeContext, name: Name) {
-    ecx.wr_tagged_str(tag_paths_data_name, &name.as_str());
+    ecx.start_tag(tag_paths_data_name);
+    name.encode(ecx).unwrap();
+    ecx.end_tag();
 }
 
-fn encode_def_id(ecx: &mut EncodeContext, id: DefId) {
-    ecx.wr_tagged_u64(tag_def_id, def_to_u64(id));
+fn encode_def_id(ecx: &mut EncodeContext, def_id: DefId) {
+    assert!(def_id.is_local());
+    ecx.start_tag(tag_def_index);
+    def_id.index.encode(ecx).unwrap();
+    ecx.end_tag();
 }
 
 fn encode_def_key(ecx: &mut EncodeContext, key: DefKey) {
@@ -178,16 +205,10 @@ fn encode_trait_ref<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
 }
 
 // Item info table encoding
-fn encode_family(ecx: &mut EncodeContext, c: char) {
-    ecx.wr_tagged_u8(tag_items_data_item_family, c as u8);
-}
-
-pub fn def_to_u64(did: DefId) -> u64 {
-    (did.krate.as_u32() as u64) << 32 | (did.index.as_u32() as u64)
-}
-
-pub fn def_to_string(_tcx: TyCtxt, did: DefId) -> String {
-    format!("{}:{}", did.krate, did.index.as_usize())
+fn encode_family(ecx: &mut EncodeContext, f: Family) {
+    ecx.start_tag(tag_items_data_item_family);
+    f.encode(ecx).unwrap();
+    ecx.end_tag();
 }
 
 fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) {
@@ -197,7 +218,7 @@ fn encode_item_variances(ecx: &mut EncodeContext, id: NodeId) {
     ecx.end_tag();
 }
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_bounds_and_type_for_item(&mut self, def_id: DefId) {
         let tcx = self.tcx;
         self.encode_bounds_and_type(&tcx.lookup_item_type(def_id),
@@ -210,44 +231,31 @@ fn encode_bounds_and_type(&mut self,
         self.encode_generics(&scheme.generics, &predicates);
         self.encode_type(scheme.ty);
     }
-}
-
-fn encode_variant_id(ecx: &mut EncodeContext, vid: DefId) {
-    let id = def_to_u64(vid);
-    ecx.wr_tagged_u64(tag_items_data_item_variant, id);
-    ecx.wr_tagged_u64(tag_mod_child, id);
-}
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
     fn encode_type(&mut self, typ: Ty<'tcx>) {
         self.start_tag(tag_items_data_item_type);
-        typ.encode(self.ecx).unwrap();
+        typ.encode(self).unwrap();
         self.end_tag();
     }
 
     fn encode_disr_val(&mut self,
                        disr_val: ty::Disr) {
-        // convert to u64 so just the number is printed, without any type info
-        self.wr_tagged_str(tag_disr_val, &disr_val.to_u64_unchecked().to_string());
+        self.start_tag(tag_disr_val);
+        disr_val.to_u64_unchecked().encode(self).unwrap();
+        self.end_tag();
     }
 
     fn encode_parent_item(&mut self, id: DefId) {
-        self.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(id));
+        self.start_tag(tag_items_data_parent_item);
+        id.encode(self).unwrap();
+        self.end_tag();
     }
 
-    fn encode_struct_fields(&mut self,
-                            variant: ty::VariantDef) {
-        for f in &variant.fields {
-            if variant.kind == ty::VariantKind::Tuple {
-                self.start_tag(tag_item_unnamed_field);
-            } else {
-                self.start_tag(tag_item_field);
-                encode_name(self, f.name);
-            }
-            self.encode_struct_field_family(f.vis);
-            encode_def_id(self, f.did);
-            self.end_tag();
-        }
+    fn encode_variant_fields(&mut self,
+                             variant: ty::VariantDef) {
+        self.start_tag(tag_item_fields);
+        self.seq(&variant.fields, |_, f| f.did);
+        self.end_tag();
     }
 }
 
@@ -258,13 +266,13 @@ fn encode_enum_variant_infos(&mut self, enum_did: DefId) {
         self.encode_fields(enum_did);
         for (i, variant) in def.variants.iter().enumerate() {
             self.record(variant.did,
-                        ItemContentBuilder::encode_enum_variant_info,
+                        EncodeContext::encode_enum_variant_info,
                         (enum_did, Untracked(i)));
         }
     }
 }
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     /// Encode data for the given variant of the given ADT. The
     /// index of the variant is untracked: this is ok because we
     /// will have to lookup the adt-def by its id, and that gives us
@@ -278,11 +286,7 @@ fn encode_enum_variant_info(&mut self,
         let variant = &def.variants[index];
         let vid = variant.did;
         encode_def_id_and_key(self, vid);
-        encode_family(self, match variant.kind {
-            ty::VariantKind::Struct => 'V',
-            ty::VariantKind::Tuple => 'v',
-            ty::VariantKind::Unit => 'w',
-        });
+        encode_family(self, Family::Variant(variant.kind));
         encode_name(self, variant.name);
         self.encode_parent_item(enum_did);
 
@@ -299,51 +303,35 @@ fn encode_enum_variant_info(&mut self,
         encode_stability(self, stab);
         encode_deprecation(self, depr);
 
-        self.encode_struct_fields(variant);
+        self.encode_variant_fields(variant);
         self.encode_disr_val(variant.disr_val);
         self.encode_bounds_and_type_for_item(vid);
     }
 }
 
-fn encode_reexports(ecx: &mut EncodeContext, id: NodeId) {
-    debug!("(encoding info for module) encoding reexports for {}", id);
-    match ecx.reexports.get(&id) {
-        Some(exports) => {
-            debug!("(encoding info for module) found reexports for {}", id);
-            for exp in exports {
-                debug!("(encoding info for module) reexport '{}' ({:?}) for \
-                        {}",
-                       exp.name,
-                       exp.def_id,
-                       id);
-                ecx.start_tag(tag_items_data_item_reexport);
-                ecx.wr_tagged_u64(tag_items_data_item_reexport_def_id,
-                                  def_to_u64(exp.def_id));
-                ecx.wr_tagged_str(tag_items_data_item_reexport_name,
-                                  &exp.name.as_str());
-                ecx.end_tag();
-            }
-        },
-        None => debug!("(encoding info for module) found no reexports for {}", id),
-    }
-}
-
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_mod(&mut self,
                            FromId(id, (md, attrs, name, vis)):
                            FromId<(&hir::Mod, &[ast::Attribute], Name, &hir::Visibility)>) {
         let tcx = self.tcx;
 
         encode_def_id_and_key(self, tcx.map.local_def_id(id));
-        encode_family(self, 'm');
+        encode_family(self, Family::Mod);
         encode_name(self, name);
         debug!("(encoding info for module) encoding info for module ID {}", id);
 
         // Encode info about all the module children.
-        for item_id in &md.item_ids {
-            self.wr_tagged_u64(tag_mod_child,
-                               def_to_u64(tcx.map.local_def_id(item_id.id)));
+        self.start_tag(tag_mod_children);
+        self.seq(&md.item_ids, |_, item_id| {
+            tcx.map.local_def_id(item_id.id)
+        });
+
+        // Encode the reexports of this module, if this module is public.
+        match self.reexports.get(&id) {
+            Some(exports) if *vis == hir::Public => exports.encode(self).unwrap(),
+            _ => <[def::Export]>::encode(&[], self).unwrap()
         }
+        self.end_tag();
 
         self.encode_visibility(vis);
 
@@ -352,22 +340,27 @@ fn encode_info_for_mod(&mut self,
         encode_stability(self, stab);
         encode_deprecation(self, depr);
 
-        // Encode the reexports of this module, if this module is public.
-        if *vis == hir::Public {
-            debug!("(encoding info for module) encoding reexports for {}", id);
-            encode_reexports(self, id);
-        }
         encode_attributes(self, attrs);
     }
 
     fn encode_struct_field_family(&mut self,
                                   visibility: ty::Visibility) {
-        encode_family(self, if visibility.is_public() { 'g' } else { 'N' });
+        encode_family(self, if visibility.is_public() {
+            Family::PublicField
+        } else {
+            Family::InheritedField
+        });
     }
 
     fn encode_visibility<T: HasVisibility>(&mut self, visibility: T) {
-        let ch = if visibility.is_public() { 'y' } else { 'i' };
-        self.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
+        let vis = if visibility.is_public() {
+            ty::Visibility::Public
+        } else {
+            ty::Visibility::PrivateExternal
+        };
+        self.start_tag(tag_items_data_item_visibility);
+        vis.encode(self).unwrap();
+        self.end_tag();
     }
 }
 
@@ -389,54 +382,14 @@ fn is_public(self) -> bool {
 
 fn encode_constness(ecx: &mut EncodeContext, constness: hir::Constness) {
     ecx.start_tag(tag_items_data_item_constness);
-    let ch = match constness {
-        hir::Constness::Const => 'c',
-        hir::Constness::NotConst => 'n',
-    };
-    ecx.wr_str(&ch.to_string());
+    constness.encode(ecx).unwrap();
     ecx.end_tag();
 }
 
 fn encode_defaultness(ecx: &mut EncodeContext, defaultness: hir::Defaultness) {
-    let ch = match defaultness {
-        hir::Defaultness::Default => 'd',
-        hir::Defaultness::Final => 'f',
-    };
-    ecx.wr_tagged_u8(tag_items_data_item_defaultness, ch as u8);
-}
-
-fn encode_explicit_self(ecx: &mut EncodeContext,
-                        explicit_self: &ty::ExplicitSelfCategory) {
-    let tag = tag_item_trait_method_explicit_self;
-
-    // Encode the base self type.
-    match *explicit_self {
-        ty::ExplicitSelfCategory::Static => {
-            ecx.wr_tagged_bytes(tag, &['s' as u8]);
-        }
-        ty::ExplicitSelfCategory::ByValue => {
-            ecx.wr_tagged_bytes(tag, &['v' as u8]);
-        }
-        ty::ExplicitSelfCategory::ByBox => {
-            ecx.wr_tagged_bytes(tag, &['~' as u8]);
-        }
-        ty::ExplicitSelfCategory::ByReference(_, m) => {
-            // FIXME(#4846) encode custom lifetime
-            let ch = encode_mutability(m);
-            ecx.wr_tagged_bytes(tag, &['&' as u8, ch]);
-        }
-    }
-
-    fn encode_mutability(m: hir::Mutability) -> u8 {
-        match m {
-            hir::MutImmutable => 'i' as u8,
-            hir::MutMutable => 'm' as u8,
-        }
-    }
-}
-
-fn encode_item_sort(ecx: &mut EncodeContext, sort: char) {
-    ecx.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
+    ecx.start_tag(tag_items_data_item_defaultness);
+    defaultness.encode(ecx).unwrap();
+    ecx.end_tag();
 }
 
 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
@@ -446,14 +399,14 @@ fn encode_fields(&mut self,
         for (variant_index, variant) in def.variants.iter().enumerate() {
             for (field_index, field) in variant.fields.iter().enumerate() {
                 self.record(field.did,
-                            ItemContentBuilder::encode_field,
+                            EncodeContext::encode_field,
                             (adt_def_id, Untracked((variant_index, field_index))));
             }
         }
     }
 }
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     /// Encode data for the given field of the given variant of the
     /// given ADT. The indices of the variant/field are untracked:
     /// this is ok because we will have to lookup the adt-def by its
@@ -476,6 +429,10 @@ fn encode_field(&mut self,
         self.encode_bounds_and_type_for_item(field.did);
         encode_def_id_and_key(self, field.did);
 
+        let variant_id = tcx.map.as_local_node_id(variant.did).unwrap();
+        let variant_data = tcx.map.expect_variant_data(variant_id);
+        encode_attributes(self, &variant_data.fields()[field_index].attrs);
+
         let stab = tcx.lookup_stability(field.did);
         let depr = tcx.lookup_deprecation(field.did);
         encode_stability(self, stab);
@@ -491,11 +448,7 @@ fn encode_struct_ctor(&mut self,
         let item = tcx.map.expect_item(struct_node_id);
         let ctor_def_id = tcx.map.local_def_id(ctor_node_id);
         encode_def_id_and_key(self, ctor_def_id);
-        encode_family(self, match variant.kind {
-            ty::VariantKind::Struct => 'S',
-            ty::VariantKind::Tuple => 's',
-            ty::VariantKind::Unit => 'u',
-        });
+        encode_family(self, Family::Struct(variant.kind));
         self.encode_bounds_and_type_for_item(ctor_def_id);
         encode_name(self, item.name);
         self.encode_parent_item(struct_def_id);
@@ -510,7 +463,9 @@ fn encode_struct_ctor(&mut self,
         // definition, but without this there is no way for them
         // to tell that they actually have a ctor rather than a
         // normal function
-        self.wr_tagged_bytes(tag_items_data_item_is_tuple_struct_ctor, &[]);
+        self.start_tag(tag_items_data_item_is_tuple_struct_ctor);
+        true.encode(self).unwrap();
+        self.end_tag();
     }
 
     fn encode_generics(&mut self,
@@ -518,7 +473,7 @@ fn encode_generics(&mut self,
                        predicates: &ty::GenericPredicates<'tcx>)
     {
         self.start_tag(tag_item_generics);
-        generics.encode(self.ecx).unwrap();
+        generics.encode(self).unwrap();
         self.end_tag();
         self.encode_predicates(predicates, tag_item_predicates);
     }
@@ -527,13 +482,10 @@ fn encode_predicates(&mut self,
                          predicates: &ty::GenericPredicates<'tcx>,
                          tag: usize) {
         self.start_tag(tag);
-        if let Some(def_id) = predicates.parent {
-            self.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id));
-        }
-        for predicate in &predicates.predicates {
-            let xref = self.add_xref(XRef::Predicate(predicate.clone()));
-            self.wr_tagged_u32(tag_predicate, xref);
-        }
+        predicates.parent.encode(self).unwrap();
+        self.seq(&predicates.predicates, |ecx, predicate| {
+            ecx.add_xref(XRef::Predicate(predicate.clone()))
+        });
         self.end_tag();
     }
 
@@ -542,13 +494,12 @@ fn encode_method_ty_fields(&mut self, method_ty: &ty::Method<'tcx>) {
         encode_name(self, method_ty.name);
         self.encode_generics(&method_ty.generics, &method_ty.predicates);
         self.encode_visibility(method_ty.vis);
-        encode_explicit_self(self, &method_ty.explicit_self);
-        match method_ty.explicit_self {
-            ty::ExplicitSelfCategory::Static => {
-                encode_family(self, STATIC_METHOD_FAMILY);
-            }
-            _ => encode_family(self, METHOD_FAMILY)
-        }
+
+        self.start_tag(tag_item_trait_method_explicit_self);
+        method_ty.explicit_self.encode(self).unwrap();
+        self.end_tag();
+
+        encode_family(self, Family::Method);
     }
 
     fn encode_info_for_trait_item(&mut self,
@@ -563,79 +514,47 @@ fn encode_info_for_trait_item(&mut self,
         encode_stability(self, stab);
         encode_deprecation(self, depr);
 
-        let trait_item_type =
-            tcx.impl_or_trait_item(item_def_id);
-        let is_nonstatic_method;
-        match trait_item_type {
+        match tcx.impl_or_trait_item(item_def_id) {
             ty::ConstTraitItem(associated_const) => {
                 encode_name(self, associated_const.name);
-                encode_def_id_and_key(self, associated_const.def_id);
+                encode_def_id_and_key(self, item_def_id);
                 self.encode_visibility(associated_const.vis);
 
-                encode_family(self, 'C');
-
-                self.encode_bounds_and_type_for_item(associated_const.def_id);
-
-                is_nonstatic_method = false;
+                encode_family(self, Family::AssociatedConst);
+                self.encode_bounds_and_type_for_item(item_def_id);
             }
             ty::MethodTraitItem(method_ty) => {
-                let method_def_id = item_def_id;
-
                 self.encode_method_ty_fields(&method_ty);
-
-                match method_ty.explicit_self {
-                    ty::ExplicitSelfCategory::Static => {
-                        encode_family(self, STATIC_METHOD_FAMILY);
-                    }
-                    _ => {
-                        encode_family(self, METHOD_FAMILY);
-                    }
-                }
-                self.encode_bounds_and_type_for_item(method_def_id);
-
-                is_nonstatic_method = method_ty.explicit_self !=
-                    ty::ExplicitSelfCategory::Static;
+                self.encode_bounds_and_type_for_item(item_def_id);
             }
             ty::TypeTraitItem(associated_type) => {
                 encode_name(self, associated_type.name);
-                encode_def_id_and_key(self, associated_type.def_id);
-                encode_item_sort(self, 't');
-                encode_family(self, 'y');
+                encode_def_id_and_key(self, item_def_id);
+                encode_family(self, Family::AssociatedType);
 
                 if let Some(ty) = associated_type.ty {
                     self.encode_type(ty);
                 }
-
-                is_nonstatic_method = false;
             }
         }
 
         encode_attributes(self, &trait_item.attrs);
         match trait_item.node {
             hir::ConstTraitItem(_, ref default) => {
-                if default.is_some() {
-                    encode_item_sort(self, 'C');
-                } else {
-                    encode_item_sort(self, 'c');
-                }
+                self.start_tag(tag_item_trait_item_has_body);
+                default.is_some().encode(self).unwrap();
+                self.end_tag();
 
                 encode_inlined_item(self,
                                     InlinedItemRef::TraitItem(trait_def_id, trait_item));
                 self.encode_mir(item_def_id);
             }
             hir::MethodTraitItem(ref sig, ref body) => {
-                // If this is a static method, we've already
-                // encoded self.
-                if is_nonstatic_method {
-                    self.encode_bounds_and_type_for_item(item_def_id);
-                }
+                self.start_tag(tag_item_trait_item_has_body);
+                body.is_some().encode(self).unwrap();
+                self.end_tag();
 
-                if body.is_some() {
-                    encode_item_sort(self, 'p');
-                    self.encode_mir(item_def_id);
-                } else {
-                    encode_item_sort(self, 'r');
-                }
+                self.encode_mir(item_def_id);
                 self.encode_method_argument_names(&sig.decl);
             }
 
@@ -654,7 +573,6 @@ fn encode_info_for_impl_item(&mut self,
             }
             ty::MethodTraitItem(ref method_type) => {
                 self.encode_info_for_method(&method_type,
-                                            false,
                                             impl_id,
                                             ast_item)
             }
@@ -678,10 +596,13 @@ fn encode_info_for_associated_const(&mut self,
         encode_def_id_and_key(self, associated_const.def_id);
         encode_name(self, associated_const.name);
         self.encode_visibility(associated_const.vis);
-        encode_family(self, 'C');
+        encode_family(self, Family::AssociatedConst);
 
         self.encode_parent_item(tcx.map.local_def_id(parent_id));
-        encode_item_sort(self, 'C');
+
+        self.start_tag(tag_item_trait_item_has_body);
+        true.encode(self).unwrap();
+        self.end_tag();
 
         self.encode_bounds_and_type_for_item(associated_const.def_id);
 
@@ -702,7 +623,6 @@ fn encode_info_for_associated_const(&mut self,
 
     fn encode_info_for_method(&mut self,
                               m: &ty::Method<'tcx>,
-                              is_default_impl: bool,
                               parent_id: NodeId,
                               impl_item_opt: Option<&hir::ImplItem>) {
         let tcx = self.tcx;
@@ -711,7 +631,10 @@ fn encode_info_for_method(&mut self,
                m.name);
         self.encode_method_ty_fields(m);
         self.encode_parent_item(tcx.map.local_def_id(parent_id));
-        encode_item_sort(self, 'r');
+
+        self.start_tag(tag_item_trait_item_has_body);
+        true.encode(self).unwrap();
+        self.end_tag();
 
         let stab = tcx.lookup_stability(m.def_id);
         let depr = tcx.lookup_deprecation(m.def_id);
@@ -725,8 +648,7 @@ fn encode_info_for_method(&mut self,
                 encode_attributes(self, &impl_item.attrs);
                 let generics = tcx.lookup_generics(m.def_id);
                 let types = generics.parent_types as usize + generics.types.len();
-                let needs_inline = types > 0 || is_default_impl ||
-                    attr::requests_inline(&impl_item.attrs);
+                let needs_inline = types > 0 || attr::requests_inline(&impl_item.attrs);
                 if sig.constness == hir::Constness::Const {
                     encode_inlined_item(
                         self,
@@ -755,9 +677,8 @@ fn encode_info_for_associated_type(&mut self,
         encode_def_id_and_key(self, associated_type.def_id);
         encode_name(self, associated_type.name);
         self.encode_visibility(associated_type.vis);
-        encode_family(self, 'y');
+        encode_family(self, Family::AssociatedType);
         self.encode_parent_item(tcx.map.local_def_id(parent_id));
-        encode_item_sort(self, 't');
 
         let stab = tcx.lookup_stability(associated_type.def_id);
         let depr = tcx.lookup_deprecation(associated_type.def_id);
@@ -777,15 +698,15 @@ fn encode_info_for_associated_type(&mut self,
     fn encode_method_argument_names(&mut self,
                                     decl: &hir::FnDecl) {
         self.start_tag(tag_method_argument_names);
-        for arg in &decl.inputs {
-            let tag = tag_method_argument_name;
+
+        self.seq(&decl.inputs, |_, arg| {
             if let PatKind::Binding(_, ref path1, _) = arg.pat.node {
-                let name = path1.node.as_str();
-                self.wr_tagged_bytes(tag, name.as_bytes());
+                path1.node
             } else {
-                self.wr_tagged_bytes(tag, &[]);
+                syntax::parse::token::intern("")
             }
-        }
+        });
+
         self.end_tag();
     }
 
@@ -797,36 +718,28 @@ fn encode_repr_attrs(&mut self,
                                                     attr));
         }
         self.start_tag(tag_items_data_item_repr);
-        repr_attrs.encode(self.ecx);
+        repr_attrs.encode(self);
         self.end_tag();
     }
 
     fn encode_mir(&mut self, def_id: DefId) {
         if let Some(mir) = self.mir_map.map.get(&def_id) {
             self.start_tag(tag_mir as usize);
-            mir.encode(self.ecx);
+            mir.encode(self);
             self.end_tag();
         }
     }
 }
 
-const FN_FAMILY: char = 'f';
-const STATIC_METHOD_FAMILY: char = 'F';
-const METHOD_FAMILY: char = 'h';
-
 // Encodes the inherent implementations of a structure, enumeration, or trait.
 fn encode_inherent_implementations(ecx: &mut EncodeContext,
                                    def_id: DefId) {
+    ecx.start_tag(tag_items_data_item_inherent_impls);
     match ecx.tcx.inherent_impls.borrow().get(&def_id) {
-        None => {}
-        Some(implementations) => {
-            for &impl_def_id in implementations.iter() {
-                ecx.start_tag(tag_items_data_item_inherent_impl);
-                encode_def_id(ecx, impl_def_id);
-                ecx.end_tag();
-            }
-        }
+        None => <[DefId]>::encode(&[], ecx).unwrap(),
+        Some(implementations) => implementations.encode(ecx).unwrap()
     }
+    ecx.end_tag();
 }
 
 fn encode_stability(ecx: &mut EncodeContext, stab_opt: Option<&attr::Stability>) {
@@ -845,37 +758,35 @@ fn encode_deprecation(ecx: &mut EncodeContext, depr_opt: Option<attr::Deprecatio
     });
 }
 
-fn encode_parent_impl(ecx: &mut EncodeContext, parent_opt: Option<DefId>) {
-    parent_opt.map(|parent| {
-        ecx.wr_tagged_u64(tag_items_data_parent_impl, def_to_u64(parent));
-    });
-}
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+    fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
+        let old_len = self.xrefs.len() as u32;
+        *self.xrefs.entry(xref).or_insert(old_len)
+    }
 
-fn encode_xrefs<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>,
-                          xrefs: FnvHashMap<XRef<'tcx>, u32>)
-{
-    let mut xref_positions = vec![0; xrefs.len()];
+    fn encode_xrefs(&mut self) {
+        let xrefs = mem::replace(&mut self.xrefs, Default::default());
+        let mut xref_positions = vec![0; xrefs.len()];
 
-    // Encode XRefs sorted by their ID
-    let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect();
-    sorted_xrefs.sort_by_key(|&(_, id)| id);
+        // Encode XRefs sorted by their ID
+        let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect();
+        sorted_xrefs.sort_by_key(|&(_, id)| id);
 
-    ecx.start_tag(tag_xref_data);
-    for (xref, id) in sorted_xrefs.into_iter() {
-        xref_positions[id as usize] = ecx.mark_stable_position() as u32;
-        match xref {
-            XRef::Predicate(p) => p.encode(ecx).unwrap()
+        self.start_tag(tag_xref_data);
+        for (xref, id) in sorted_xrefs.into_iter() {
+            xref_positions[id as usize] = self.mark_stable_position() as u32;
+            match xref {
+                XRef::Predicate(p) => p.encode(self).unwrap()
+            }
         }
-    }
-    ecx.mark_stable_position();
-    ecx.end_tag();
+        self.mark_stable_position();
+        self.end_tag();
 
-    ecx.start_tag(tag_xref_index);
-    index::write_dense_index(xref_positions, &mut ecx.opaque.cursor);
-    ecx.end_tag();
-}
+        self.start_tag(tag_xref_index);
+        index::write_dense_index(xref_positions, &mut self.opaque.cursor);
+        self.end_tag();
+    }
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
     fn encode_info_for_item(&mut self,
                             (def_id, item): (DefId, &hir::Item)) {
         let tcx = self.tcx;
@@ -893,11 +804,11 @@ fn encode_info_for_item(&mut self,
         match item.node {
             hir::ItemStatic(_, m, _) => {
                 encode_def_id_and_key(self, def_id);
-                if m == hir::MutMutable {
-                    encode_family(self, 'b');
+                encode_family(self, if m == hir::MutMutable {
+                    Family::MutStatic
                 } else {
-                    encode_family(self, 'c');
-                }
+                    Family::ImmStatic
+                });
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, item.name);
                 self.encode_visibility(vis);
@@ -907,7 +818,7 @@ fn encode_info_for_item(&mut self,
             }
             hir::ItemConst(..) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'C');
+                encode_family(self, Family::Const);
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, item.name);
                 encode_attributes(self, &item.attrs);
@@ -919,7 +830,7 @@ fn encode_info_for_item(&mut self,
             }
             hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, FN_FAMILY);
+                encode_family(self, Family::Fn);
                 let tps_len = generics.ty_params.len();
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, item.name);
@@ -942,22 +853,24 @@ fn encode_info_for_item(&mut self,
             }
             hir::ItemForeignMod(ref fm) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'n');
+                encode_family(self, Family::ForeignMod);
                 encode_name(self, item.name);
 
                 // Encode all the items in self module.
-                for foreign_item in &fm.items {
-                    self.wr_tagged_u64(
-                        tag_mod_child,
-                        def_to_u64(tcx.map.local_def_id(foreign_item.id)));
-                }
+                self.start_tag(tag_mod_children);
+                self.seq(&fm.items, |_, foreign_item| {
+                    tcx.map.local_def_id(foreign_item.id)
+                });
+                <[def::Export]>::encode(&[], self).unwrap();
+                self.end_tag();
+
                 self.encode_visibility(vis);
                 encode_stability(self, stab);
                 encode_deprecation(self, depr);
             }
             hir::ItemTy(..) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'y');
+                encode_family(self, Family::Type);
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, item.name);
                 self.encode_visibility(vis);
@@ -966,15 +879,19 @@ fn encode_info_for_item(&mut self,
             }
             hir::ItemEnum(ref enum_definition, _) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 't');
+                encode_family(self, Family::Enum);
                 encode_item_variances(self, item.id);
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, item.name);
                 encode_attributes(self, &item.attrs);
                 self.encode_repr_attrs(&item.attrs);
-                for v in &enum_definition.variants {
-                    encode_variant_id(self, tcx.map.local_def_id(v.node.data.id()));
-                }
+
+                self.start_tag(tag_mod_children);
+                self.seq(&enum_definition.variants, |_, v| {
+                    tcx.map.local_def_id(v.node.data.id())
+                });
+                <[def::Export]>::encode(&[], self).unwrap();
+                self.end_tag();
 
                 // Encode inherent implementations for self enumeration.
                 encode_inherent_implementations(self, def_id);
@@ -990,11 +907,7 @@ fn encode_info_for_item(&mut self,
 
                 /* Now, make an item for the class itself */
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, match *struct_def {
-                    hir::VariantData::Struct(..) => 'S',
-                    hir::VariantData::Tuple(..) => 's',
-                    hir::VariantData::Unit(..) => 'u',
-                });
+                encode_family(self, Family::Struct(variant.kind));
                 self.encode_bounds_and_type_for_item(def_id);
 
                 encode_item_variances(self, item.id);
@@ -1008,15 +921,16 @@ fn encode_info_for_item(&mut self,
                 /* Encode def_ids for each field and method
                 for methods, write all the stuff get_trait_method
                 needs to know*/
-                self.encode_struct_fields(variant);
+                self.encode_variant_fields(variant);
 
                 // Encode inherent implementations for self structure.
                 encode_inherent_implementations(self, def_id);
 
                 if !struct_def.is_struct() {
                     let ctor_did = tcx.map.local_def_id(struct_def.id());
-                    self.wr_tagged_u64(tag_items_data_item_struct_ctor,
-                                       def_to_u64(ctor_did));
+                    self.start_tag(tag_items_data_item_struct_ctor);
+                    ctor_did.encode(self).unwrap();
+                    self.end_tag();
                 }
             }
             hir::ItemUnion(..) => {
@@ -1024,7 +938,7 @@ fn encode_info_for_item(&mut self,
                 let variant = def.struct_variant();
 
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'U');
+                encode_family(self, Family::Union);
                 self.encode_bounds_and_type_for_item(def_id);
 
                 encode_item_variances(self, item.id);
@@ -1038,7 +952,7 @@ fn encode_info_for_item(&mut self,
                 /* Encode def_ids for each field and method
                 for methods, write all the stuff get_trait_method
                 needs to know*/
-                self.encode_struct_fields(variant);
+                self.encode_variant_fields(variant);
 
                 encode_inlined_item(self, InlinedItemRef::Item(def_id, item));
                 self.encode_mir(def_id);
@@ -1046,28 +960,24 @@ fn encode_info_for_item(&mut self,
                 // Encode inherent implementations for self union.
                 encode_inherent_implementations(self, def_id);
             }
-            hir::ItemDefaultImpl(unsafety, _) => {
+            hir::ItemDefaultImpl(..) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'd');
+                encode_family(self, Family::DefaultImpl);
                 encode_name(self, item.name);
-                encode_unsafety(self, unsafety);
 
                 let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(item.id)).unwrap();
                 encode_trait_ref(self, trait_ref, tag_item_trait_ref);
             }
-            hir::ItemImpl(unsafety, polarity, ..) => {
-                // We need to encode information about the default methods we
-                // have inherited, so we drive self based on the impl structure.
-                let impl_items = tcx.impl_items.borrow();
-                let items = &impl_items[&def_id];
-
+            hir::ItemImpl(_, polarity, ..) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'i');
+                encode_family(self, Family::Impl);
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, item.name);
                 encode_attributes(self, &item.attrs);
-                encode_unsafety(self, unsafety);
-                encode_polarity(self, polarity);
+
+                self.start_tag(tag_polarity);
+                polarity.encode(self).unwrap();
+                self.end_tag();
 
                 match
                     tcx.custom_coerce_unsized_kinds
@@ -1076,30 +986,17 @@ fn encode_info_for_item(&mut self,
                 {
                     Some(&kind) => {
                         self.start_tag(tag_impl_coerce_unsized_kind);
-                        kind.encode(self.ecx);
+                        kind.encode(self);
                         self.end_tag();
                     }
                     None => {}
                 }
 
-                for &item_def_id in items {
-                    self.start_tag(tag_item_impl_item);
-                    match item_def_id {
-                        ty::ConstTraitItemId(item_def_id) => {
-                            encode_def_id(self, item_def_id);
-                            encode_item_sort(self, 'C');
-                        }
-                        ty::MethodTraitItemId(item_def_id) => {
-                            encode_def_id(self, item_def_id);
-                            encode_item_sort(self, 'r');
-                        }
-                        ty::TypeTraitItemId(item_def_id) => {
-                            encode_def_id(self, item_def_id);
-                            encode_item_sort(self, 't');
-                        }
-                    }
-                    self.end_tag();
-                }
+                self.start_tag(tag_mod_children);
+                let items = tcx.impl_or_trait_items(def_id);
+                self.seq(&items[..], |_, id| id.def_id());
+                <[def::Export]>::encode(&[], self).unwrap();
+                self.end_tag();
 
                 let did = tcx.map.local_def_id(item.id);
                 if let Some(trait_ref) = tcx.impl_trait_ref(did) {
@@ -1114,20 +1011,34 @@ fn encode_info_for_item(&mut self,
                                                   Some(parent),
                                               _ => None,
                                           });
-                    encode_parent_impl(self, parent);
+                    parent.map(|parent| {
+                        self.start_tag(tag_items_data_parent_impl);
+                        parent.encode(self).unwrap();
+                        self.end_tag();
+                    });
                 }
                 encode_stability(self, stab);
                 encode_deprecation(self, depr);
             }
             hir::ItemTrait(..) => {
                 encode_def_id_and_key(self, def_id);
-                encode_family(self, 'I');
+                encode_family(self, Family::Trait);
                 encode_item_variances(self, item.id);
                 let trait_def = tcx.lookup_trait_def(def_id);
                 let trait_predicates = tcx.lookup_predicates(def_id);
-                encode_unsafety(self, trait_def.unsafety);
-                encode_paren_sugar(self, trait_def.paren_sugar);
-                encode_defaulted(self, tcx.trait_has_default_impl(def_id));
+
+                self.start_tag(tag_unsafety);
+                trait_def.unsafety.encode(self).unwrap();
+                self.end_tag();
+
+                self.start_tag(tag_paren_sugar);
+                trait_def.paren_sugar.encode(self).unwrap();
+                self.end_tag();
+
+                self.start_tag(tag_defaulted_trait);
+                tcx.trait_has_default_impl(def_id).encode(self).unwrap();
+                self.end_tag();
+
                 encode_associated_type_names(self, &trait_def.associated_type_names);
                 self.encode_generics(&trait_def.generics, &trait_predicates);
                 self.encode_predicates(&tcx.lookup_super_predicates(def_id),
@@ -1138,27 +1049,12 @@ fn encode_info_for_item(&mut self,
                 self.encode_visibility(vis);
                 encode_stability(self, stab);
                 encode_deprecation(self, depr);
-                for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
-                    self.start_tag(tag_item_trait_item);
-                    match method_def_id {
-                        ty::ConstTraitItemId(const_def_id) => {
-                            encode_def_id(self, const_def_id);
-                            encode_item_sort(self, 'C');
-                        }
-                        ty::MethodTraitItemId(method_def_id) => {
-                            encode_def_id(self, method_def_id);
-                            encode_item_sort(self, 'r');
-                        }
-                        ty::TypeTraitItemId(type_def_id) => {
-                            encode_def_id(self, type_def_id);
-                            encode_item_sort(self, 't');
-                        }
-                    }
-                    self.end_tag();
 
-                    self.wr_tagged_u64(tag_mod_child,
-                                       def_to_u64(method_def_id.def_id()));
-                }
+                self.start_tag(tag_mod_children);
+                let items = tcx.impl_or_trait_items(def_id);
+                self.seq(&items[..], |_, id| id.def_id());
+                <[def::Export]>::encode(&[], self).unwrap();
+                self.end_tag();
 
                 // Encode inherent implementations for self trait.
                 encode_inherent_implementations(self, def_id);
@@ -1227,7 +1123,7 @@ fn encode_addl_struct_info(&mut self,
                 // Foo()` and `struct Foo`
                 let ctor_def_id = self.tcx.map.local_def_id(struct_node_id);
                 self.record(ctor_def_id,
-                            ItemContentBuilder::encode_struct_ctor,
+                            EncodeContext::encode_struct_ctor,
                             (def_id, item.id, struct_node_id));
             }
         }
@@ -1241,8 +1137,7 @@ fn encode_addl_impl_info(&mut self,
                              def_id: DefId,
                              impl_id: ast::NodeId,
                              ast_items: &[hir::ImplItem]) {
-        let impl_items = self.tcx.impl_items.borrow();
-        let items = &impl_items[&def_id];
+        let items = self.tcx.impl_or_trait_items(def_id);
 
         // Iterate down the trait items, emitting them. We rely on the
         // assumption that all of the actually implemented trait items
@@ -1258,7 +1153,7 @@ fn encode_addl_impl_info(&mut self,
 
             let trait_item_def_id = trait_item_def_id.def_id();
             self.record(trait_item_def_id,
-                        ItemContentBuilder::encode_info_for_impl_item,
+                        EncodeContext::encode_info_for_impl_item,
                         (impl_id, trait_item_def_id, ast_item));
         }
     }
@@ -1267,19 +1162,18 @@ fn encode_addl_trait_info(&mut self,
                               def_id: DefId,
                               trait_items: &[hir::TraitItem]) {
         // Now output the trait item info for each trait item.
-        let tcx = self.tcx;
-        let r = tcx.trait_item_def_ids(def_id);
+        let r = self.tcx.impl_or_trait_items(def_id);
         for (item_def_id, trait_item) in r.iter().zip(trait_items) {
             let item_def_id = item_def_id.def_id();
             assert!(item_def_id.is_local());
             self.record(item_def_id,
-                        ItemContentBuilder::encode_info_for_trait_item,
+                        EncodeContext::encode_info_for_trait_item,
                         (def_id, item_def_id, trait_item));
         }
     }
 }
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_foreign_item(&mut self,
                                     (def_id, nitem): (DefId, &hir::ForeignItem)) {
         let tcx = self.tcx;
@@ -1292,7 +1186,7 @@ fn encode_info_for_foreign_item(&mut self,
         self.encode_visibility(&nitem.vis);
         match nitem.node {
             hir::ForeignItemFn(ref fndecl, _) => {
-                encode_family(self, FN_FAMILY);
+                encode_family(self, Family::Fn);
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_name(self, nitem.name);
                 encode_attributes(self, &nitem.attrs);
@@ -1303,11 +1197,11 @@ fn encode_info_for_foreign_item(&mut self,
                 self.encode_method_argument_names(&fndecl);
             }
             hir::ForeignItemStatic(_, mutbl) => {
-                if mutbl {
-                    encode_family(self, 'b');
+                encode_family(self, if mutbl {
+                    Family::MutStatic
                 } else {
-                    encode_family(self, 'c');
-                }
+                    Family::ImmStatic
+                });
                 self.encode_bounds_and_type_for_item(def_id);
                 encode_attributes(self, &nitem.attrs);
                 let stab = tcx.lookup_stability(tcx.map.local_def_id(nitem.id));
@@ -1335,7 +1229,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         match item.node {
             hir::ItemExternCrate(_) | hir::ItemUse(_) => (), // ignore these
             _ => self.index.record(def_id,
-                                   ItemContentBuilder::encode_info_for_item,
+                                   EncodeContext::encode_info_for_item,
                                    (def_id, item)),
         }
         self.index.encode_addl_info_for_item(item);
@@ -1344,7 +1238,7 @@ fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
         intravisit::walk_foreign_item(self, ni);
         let def_id = self.index.tcx.map.local_def_id(ni.id);
         self.index.record(def_id,
-                          ItemContentBuilder::encode_info_for_foreign_item,
+                          EncodeContext::encode_info_for_foreign_item,
                           (def_id, ni));
     }
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
@@ -1358,7 +1252,7 @@ fn encode_info_for_ty(&mut self, ty: &hir::Ty) {
         if let hir::TyImplTrait(_) = ty.node {
             let def_id = self.tcx.map.local_def_id(ty.id);
             self.record(def_id,
-                        ItemContentBuilder::encode_info_for_anon_ty,
+                        EncodeContext::encode_info_for_anon_ty,
                         def_id);
         }
     }
@@ -1368,7 +1262,7 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
             hir::ExprClosure(..) => {
                 let def_id = self.tcx.map.local_def_id(expr.id);
                 self.record(def_id,
-                            ItemContentBuilder::encode_info_for_closure,
+                            EncodeContext::encode_info_for_closure,
                             def_id);
             }
             _ => { }
@@ -1376,10 +1270,9 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr) {
     }
 }
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn encode_info_for_anon_ty(&mut self, def_id: DefId) {
         encode_def_id_and_key(self, def_id);
-        encode_family(self, 'y');
         self.encode_bounds_and_type_for_item(def_id);
     }
 
@@ -1389,11 +1282,11 @@ fn encode_info_for_closure(&mut self, def_id: DefId) {
         encode_name(self, syntax::parse::token::intern("<closure>"));
 
         self.start_tag(tag_items_closure_ty);
-        tcx.tables.borrow().closure_tys[&def_id].encode(self.ecx).unwrap();
+        tcx.tables.borrow().closure_tys[&def_id].encode(self).unwrap();
         self.end_tag();
 
         self.start_tag(tag_items_closure_kind);
-        tcx.closure_kind(def_id).encode(self.ecx).unwrap();
+        tcx.closure_kind(def_id).encode(self).unwrap();
         self.end_tag();
 
         assert!(self.mir_map.map.contains_key(&def_id));
@@ -1401,30 +1294,29 @@ fn encode_info_for_closure(&mut self, def_id: DefId) {
     }
 }
 
-fn encode_info_for_items<'a, 'tcx>(ecx: &mut EncodeContext<'a, 'tcx>)
-                                   -> (IndexData, FnvHashMap<XRef<'tcx>, u32>) {
+fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData {
     let krate = ecx.tcx.map.krate();
 
     ecx.start_tag(tag_items_data);
 
-    let fields = {
+    let items = {
         let mut index = IndexBuilder::new(ecx);
         index.record(DefId::local(CRATE_DEF_INDEX),
-                     ItemContentBuilder::encode_info_for_mod,
+                     EncodeContext::encode_info_for_mod,
                      FromId(CRATE_NODE_ID, (&krate.module,
-                                            &[],
+                                            &krate.attrs,
                                             syntax::parse::token::intern(&ecx.link_meta.crate_name),
                                             &hir::Public)));
         let mut visitor = EncodeVisitor {
             index: index,
         };
         krate.visit_all_items(&mut visitor);
-        visitor.index.into_fields()
+        visitor.index.into_items()
     };
 
     ecx.end_tag();
 
-    fields
+    items
 }
 
 fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) {
@@ -1439,40 +1331,12 @@ fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) {
     ecx.end_tag();
 }
 
-fn encode_unsafety(ecx: &mut EncodeContext, unsafety: hir::Unsafety) {
-    let byte: u8 = match unsafety {
-        hir::Unsafety::Normal => 0,
-        hir::Unsafety::Unsafe => 1,
-    };
-    ecx.wr_tagged_u8(tag_unsafety, byte);
-}
-
-fn encode_paren_sugar(ecx: &mut EncodeContext, paren_sugar: bool) {
-    let byte: u8 = if paren_sugar {1} else {0};
-    ecx.wr_tagged_u8(tag_paren_sugar, byte);
-}
-
-fn encode_defaulted(ecx: &mut EncodeContext, is_defaulted: bool) {
-    let byte: u8 = if is_defaulted {1} else {0};
-    ecx.wr_tagged_u8(tag_defaulted_trait, byte);
-}
-
 fn encode_associated_type_names(ecx: &mut EncodeContext, names: &[Name]) {
     ecx.start_tag(tag_associated_type_names);
-    for &name in names {
-        ecx.wr_tagged_str(tag_associated_type_name, &name.as_str());
-    }
+    names.encode(ecx).unwrap();
     ecx.end_tag();
 }
 
-fn encode_polarity(ecx: &mut EncodeContext, polarity: hir::ImplPolarity) {
-    let byte: u8 = match polarity {
-        hir::ImplPolarity::Positive => 0,
-        hir::ImplPolarity::Negative => 1,
-    };
-    ecx.wr_tagged_u8(tag_polarity, byte);
-}
-
 fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore)
                         -> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
@@ -1500,48 +1364,56 @@ fn get_ordered_deps(cstore: &cstore::CStore)
     // FIXME (#2166): This is not nearly enough to support correct versioning
     // but is enough to get transitive crate dependencies working.
     ecx.start_tag(tag_crate_deps);
-    for (_cnum, dep) in get_ordered_deps(cstore) {
-        encode_crate_dep(ecx, &dep);
-    }
+    ecx.seq(&get_ordered_deps(cstore), |_, &(_, ref dep)| {
+        (dep.name(), decoder::get_crate_hash(dep.data()),
+         dep.explicitly_linked.get())
+    });
     ecx.end_tag();
 }
 
 fn encode_lang_items(ecx: &mut EncodeContext) {
-    ecx.start_tag(tag_lang_items);
-
-    for (i, &opt_def_id) in ecx.tcx.lang_items.items().iter().enumerate() {
-        if let Some(def_id) = opt_def_id {
-            if def_id.is_local() {
-                ecx.start_tag(tag_lang_items_item);
-                ecx.wr_tagged_u32(tag_lang_items_item_id, i as u32);
-                ecx.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32());
-                ecx.end_tag();
+    let tcx = ecx.tcx;
+    let lang_items = || {
+        tcx.lang_items.items().iter().enumerate().filter_map(|(i, &opt_def_id)| {
+            if let Some(def_id) = opt_def_id {
+                if def_id.is_local() {
+                    return Some((def_id.index, i));
+                }
             }
-        }
-    }
+            None
+        })
+    };
 
-    for i in &ecx.tcx.lang_items.missing {
-        ecx.wr_tagged_u32(tag_lang_items_missing, *i as u32);
-    }
+    let count = lang_items().count();
+    let mut lang_items = lang_items();
 
-    ecx.end_tag();   // tag_lang_items
+    ecx.start_tag(tag_lang_items);
+    ecx.seq(0..count, |_, _| lang_items.next().unwrap());
+    ecx.end_tag();
+
+    ecx.start_tag(tag_lang_items_missing);
+    tcx.lang_items.missing.encode(ecx).unwrap();
+    ecx.end_tag();
 }
 
 fn encode_native_libraries(ecx: &mut EncodeContext) {
-    ecx.start_tag(tag_native_libraries);
-
-    for &(ref lib, kind) in ecx.tcx.sess.cstore.used_libraries().iter() {
-        match kind {
-            cstore::NativeStatic => {} // these libraries are not propagated
-            cstore::NativeFramework | cstore::NativeUnknown => {
-                ecx.start_tag(tag_native_libraries_lib);
-                ecx.wr_tagged_u32(tag_native_libraries_kind, kind as u32);
-                ecx.wr_tagged_str(tag_native_libraries_name, lib);
-                ecx.end_tag();
+    let used_libraries = ecx.tcx.sess.cstore.used_libraries();
+    let libs = || {
+        used_libraries.iter().filter_map(|&(ref lib, kind)| {
+            match kind {
+                cstore::NativeStatic => None, // these libraries are not propagated
+                cstore::NativeFramework | cstore::NativeUnknown => {
+                    Some((kind, lib))
+                }
             }
-        }
-    }
+        })
+    };
+
+    let count = libs().count();
+    let mut libs = libs();
 
+    ecx.start_tag(tag_native_libraries);
+    ecx.seq(0..count, |_, _| libs.next().unwrap());
     ecx.end_tag();
 }
 
@@ -1549,84 +1421,55 @@ fn encode_plugin_registrar_fn(ecx: &mut EncodeContext) {
     match ecx.tcx.sess.plugin_registrar_fn.get() {
         Some(id) => {
             let def_id = ecx.tcx.map.local_def_id(id);
-            ecx.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32());
+            ecx.start_tag(tag_plugin_registrar_fn);
+            def_id.index.encode(ecx).unwrap();
+            ecx.end_tag();
         }
         None => {}
     }
 }
 
 fn encode_codemap(ecx: &mut EncodeContext) {
-    ecx.start_tag(tag_codemap);
     let codemap = ecx.tcx.sess.codemap();
+    let all_filemaps = codemap.files.borrow();
+    let filemaps = || {
+        // No need to export empty filemaps, as they can't contain spans
+        // that need translation.
+        // Also no need to re-export imported filemaps, as any downstream
+        // crate will import them from their original source.
+        all_filemaps.iter().filter(|filemap| {
+            !filemap.lines.borrow().is_empty() && !filemap.is_imported()
+        })
+    };
 
-    for filemap in &codemap.files.borrow()[..] {
-
-        if filemap.lines.borrow().is_empty() || filemap.is_imported() {
-            // No need to export empty filemaps, as they can't contain spans
-            // that need translation.
-            // Also no need to re-export imported filemaps, as any downstream
-            // crate will import them from their original source.
-            continue;
-        }
-
-        ecx.start_tag(tag_codemap_filemap);
-        filemap.encode(ecx).unwrap();
-        ecx.end_tag();
-    }
+    let count = filemaps().count();
+    let mut filemaps = filemaps();
 
+    ecx.start_tag(tag_codemap);
+    ecx.seq(0..count, |_, _| filemaps.next().unwrap());
     ecx.end_tag();
 }
 
 /// Serialize the text of the exported macros
-fn encode_macro_defs(ecx: &mut EncodeContext,
-                     krate: &hir::Crate) {
+fn encode_macro_defs(ecx: &mut EncodeContext) {
+    let tcx = ecx.tcx;
     ecx.start_tag(tag_macro_defs);
-    for def in &krate.exported_macros {
-        ecx.start_tag(tag_macro_def);
-
-        encode_name(ecx, def.name);
-        encode_attributes(ecx, &def.attrs);
-        let &BytePos(lo) = &def.span.lo;
-        let &BytePos(hi) = &def.span.hi;
-        ecx.wr_tagged_u32(tag_macro_def_span_lo, lo);
-        ecx.wr_tagged_u32(tag_macro_def_span_hi, hi);
-
-        ecx.wr_tagged_str(tag_macro_def_body,
-                          &::syntax::print::pprust::tts_to_string(&def.body));
-
-        ecx.end_tag();
-    }
+    ecx.seq(&tcx.map.krate().exported_macros, |_, def| {
+        let body = ::syntax::print::pprust::tts_to_string(&def.body);
+        (def.name, &def.attrs, def.span, body)
+    });
     ecx.end_tag();
 
     if ecx.tcx.sess.crate_types.borrow().contains(&CrateTypeRustcMacro) {
         let id = ecx.tcx.sess.derive_registrar_fn.get().unwrap();
         let did = ecx.tcx.map.local_def_id(id);
-        ecx.wr_tagged_u32(tag_macro_derive_registrar, did.index.as_u32());
-    }
-}
 
-fn encode_struct_field_attrs(ecx: &mut EncodeContext, krate: &hir::Crate) {
-    struct StructFieldVisitor<'a, 'b:'a, 'tcx:'b> {
-        ecx: &'a mut EncodeContext<'b, 'tcx>
-    }
-
-    impl<'a, 'b, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'tcx> {
-        fn visit_struct_field(&mut self, field: &hir::StructField) {
-            self.ecx.start_tag(tag_struct_field);
-            let def_id = self.ecx.tcx.map.local_def_id(field.id);
-            encode_def_id(self.ecx, def_id);
-            encode_attributes(self.ecx, &field.attrs);
-            self.ecx.end_tag();
-        }
+        ecx.start_tag(tag_macro_derive_registrar);
+        did.index.encode(ecx).unwrap();
+        ecx.end_tag();
     }
-
-    ecx.start_tag(tag_struct_fields);
-    krate.visit_all_items(&mut StructFieldVisitor { ecx: ecx });
-    ecx.end_tag();
 }
 
-
-
 struct ImplVisitor<'a, 'tcx:'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     impls: FnvHashMap<DefId, Vec<DefId>>
@@ -1646,20 +1489,19 @@ fn visit_item(&mut self, item: &hir::Item) {
 }
 
 /// Encodes an index, mapping each trait to its (local) implementations.
-fn encode_impls(ecx: &mut EncodeContext, krate: &hir::Crate) {
+fn encode_impls(ecx: &mut EncodeContext) {
     let mut visitor = ImplVisitor {
         tcx: ecx.tcx,
         impls: FnvHashMap()
     };
-    krate.visit_all_items(&mut visitor);
+    ecx.tcx.map.krate().visit_all_items(&mut visitor);
 
     ecx.start_tag(tag_impls);
-    for (trait_, trait_impls) in visitor.impls {
-        ecx.start_tag(tag_impls_trait);
-        encode_def_id(ecx, trait_);
-        for impl_ in trait_impls {
-            ecx.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_));
-        }
+    for (trait_def_id, trait_impls) in visitor.impls {
+        // FIXME(eddyb) Avoid wrapping the entries in docs.
+        ecx.start_tag(0);
+        (trait_def_id.krate.as_u32(), trait_def_id.index).encode(ecx).unwrap();
+        trait_impls.encode(ecx).unwrap();
         ecx.end_tag();
     }
     ecx.end_tag();
@@ -1673,74 +1515,32 @@ fn encode_impls(ecx: &mut EncodeContext, krate: &hir::Crate) {
 // definition (as that's not defined in this crate).
 fn encode_reachable(ecx: &mut EncodeContext) {
     ecx.start_tag(tag_reachable_ids);
-    for &id in ecx.reachable {
-        let def_id = ecx.tcx.map.local_def_id(id);
-        ecx.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32());
-    }
-    ecx.end_tag();
-}
-
-fn encode_crate_dep(ecx: &mut EncodeContext,
-                    dep: &cstore::CrateMetadata) {
-    ecx.start_tag(tag_crate_dep);
-    ecx.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
-    let hash = decoder::get_crate_hash(dep.data());
-    ecx.wr_tagged_u64(tag_crate_dep_hash, hash.as_u64());
-    ecx.wr_tagged_u8(tag_crate_dep_explicitly_linked,
-                     dep.explicitly_linked.get() as u8);
-    ecx.end_tag();
-}
-
-fn encode_hash(ecx: &mut EncodeContext, hash: &Svh) {
-    ecx.wr_tagged_u64(tag_crate_hash, hash.as_u64());
-}
-
-fn encode_rustc_version(ecx: &mut EncodeContext) {
-    ecx.wr_tagged_str(tag_rustc_version, &rustc_version());
-}
 
-fn encode_crate_name(ecx: &mut EncodeContext, crate_name: &str) {
-    ecx.wr_tagged_str(tag_crate_crate_name, crate_name);
-}
+    let reachable = ecx.reachable;
+    ecx.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index);
 
-fn encode_crate_disambiguator(ecx: &mut EncodeContext, crate_disambiguator: &str) {
-    ecx.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator);
-}
-
-fn encode_crate_triple(ecx: &mut EncodeContext, triple: &str) {
-    ecx.wr_tagged_str(tag_crate_triple, triple);
+    ecx.end_tag();
 }
 
 fn encode_dylib_dependency_formats(ecx: &mut EncodeContext) {
-    let tag = tag_dylib_dependency_formats;
+    ecx.start_tag(tag_dylib_dependency_formats);
     match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) {
         Some(arr) => {
-            let s = arr.iter().enumerate().filter_map(|(i, slot)| {
-                let kind = match *slot {
+            ecx.seq(arr, |_, slot| {
+                match *slot {
                     Linkage::NotLinked |
-                    Linkage::IncludedFromDylib => return None,
-                    Linkage::Dynamic => "d",
-                    Linkage::Static => "s",
-                };
-                Some(format!("{}:{}", i + 1, kind))
-            }).collect::<Vec<String>>();
-            ecx.wr_tagged_str(tag, &s.join(","));
-        }
-        None => {
-            ecx.wr_tagged_str(tag, "");
-        }
-    }
-}
+                    Linkage::IncludedFromDylib => None,
 
-fn encode_panic_strategy(ecx: &mut EncodeContext) {
-    match ecx.tcx.sess.opts.cg.panic {
-        PanicStrategy::Unwind => {
-            ecx.wr_tagged_u8(tag_panic_strategy, b'U');
+                    Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
+                    Linkage::Static => Some(LinkagePreference::RequireStatic),
+                }
+            });
         }
-        PanicStrategy::Abort => {
-            ecx.wr_tagged_u8(tag_panic_strategy, b'A');
+        None => {
+            <[Option<LinkagePreference>]>::encode(&[], ecx).unwrap();
         }
     }
+    ecx.end_tag();
 }
 
 pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -1764,6 +1564,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         reachable: reachable,
         mir_map: mir_map,
         type_shorthands: Default::default(),
+        xrefs: Default::default()
     });
 
     // RBML compacts the encoded bytes whenever appropriate,
@@ -1806,24 +1607,34 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn encode_metadata_inner(ecx: &mut EncodeContext) {
-    encode_rustc_version(ecx);
+    ecx.wr_tagged_str(tag_rustc_version, &rustc_version());
 
     let tcx = ecx.tcx;
     let link_meta = ecx.link_meta;
-    encode_crate_name(ecx, &link_meta.crate_name);
-    encode_crate_triple(ecx, &tcx.sess.opts.target_triple);
-    encode_hash(ecx, &link_meta.crate_hash);
-    encode_crate_disambiguator(ecx, &tcx.sess.local_crate_disambiguator());
+
+    ecx.start_tag(tag_crate_crate_name);
+    link_meta.crate_name.encode(ecx).unwrap();
+    ecx.end_tag();
+
+    ecx.start_tag(tag_crate_triple);
+    tcx.sess.opts.target_triple.encode(ecx).unwrap();
+    ecx.end_tag();
+
+    ecx.start_tag(tag_crate_hash);
+    link_meta.crate_hash.encode(ecx).unwrap();
+    ecx.end_tag();
+
+    ecx.start_tag(tag_crate_disambiguator);
+    tcx.sess.local_crate_disambiguator().encode(ecx).unwrap();
+    ecx.end_tag();
+
     encode_dylib_dependency_formats(ecx);
-    encode_panic_strategy(ecx);
 
-    let krate = tcx.map.krate();
+    ecx.start_tag(tag_panic_strategy);
+    ecx.tcx.sess.opts.cg.panic.encode(ecx);
+    ecx.end_tag();
 
     let mut i = ecx.position();
-    encode_attributes(ecx, &krate.attrs);
-    let attr_bytes = ecx.position() - i;
-
-    i = ecx.position();
     encode_crate_deps(ecx, ecx.cstore);
     let dep_bytes = ecx.position() - i;
 
@@ -1849,12 +1660,12 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
 
     // Encode macro definitions
     i = ecx.position();
-    encode_macro_defs(ecx, krate);
+    encode_macro_defs(ecx);
     let macro_defs_bytes = ecx.position() - i;
 
     // Encode the def IDs of impls, for coherence checking.
     i = ecx.position();
-    encode_impls(ecx, krate);
+    encode_impls(ecx);
     let impl_bytes = ecx.position() - i;
 
     // Encode reachability info.
@@ -1865,7 +1676,7 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
     // Encode and index the items.
     ecx.start_tag(tag_items);
     i = ecx.position();
-    let (items, xrefs) = encode_info_for_items(ecx);
+    let items = encode_info_for_items(ecx);
     let item_bytes = ecx.position() - i;
     ecx.end_tag();
 
@@ -1874,11 +1685,9 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
     let index_bytes = ecx.position() - i;
 
     i = ecx.position();
-    encode_xrefs(ecx, xrefs);
+    ecx.encode_xrefs();
     let xref_bytes = ecx.position() - i;
 
-    encode_struct_field_attrs(ecx, krate);
-
     let total_bytes = ecx.position();
 
     if ecx.tcx.sess.meta_stats() {
@@ -1890,7 +1699,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
         }
 
         println!("metadata stats:");
-        println!("       attribute bytes: {}", attr_bytes);
         println!("             dep bytes: {}", dep_bytes);
         println!("       lang item bytes: {}", lang_item_bytes);
         println!("          native bytes: {}", native_lib_bytes);
index fd25128575f1ae55124990767d6faf4f6cea260d..2cfa6f8d5d1154b833314c5a6b9c7aeb8d61dbac 100644 (file)
 //!
 //! What record will do is to (a) record the current offset, (b) emit
 //! the `common::data_item` tag, and then call `callback_fn` with the
-//! given data as well as an `ItemContentBuilder`. Once `callback_fn`
+//! given data as well as the `EncodingContext`. Once `callback_fn`
 //! returns, the `common::data_item` tag will be closed.
 //!
-//! The `ItemContentBuilder` is another type that just offers access
-//! to the `ecx` that was given in, as well as maintaining a list of
-//! `xref` instances, which are used to extract common data so it is
-//! not re-serialized.
-//!
-//! `ItemContentBuilder` is a distinct type which does not offer the
-//! `record` method, so that we can ensure that `common::data_item` elements
-//! are never nested.
+//! `EncodingContext` does not offer the `record` method, so that we
+//! can ensure that `common::data_item` elements are never nested.
 //!
 //! In addition, while the `callback_fn` is executing, we will push a
 //! task `MetaData(some_def_id)`, which can then observe the
@@ -67,8 +61,7 @@
 use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::ty::{self, TyCtxt};
-use rustc_data_structures::fnv::FnvHashMap;
+use rustc::ty::TyCtxt;
 use syntax::ast;
 
 use std::ops::{Deref, DerefMut};
 /// Item encoding cannot be nested.
 pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
     items: IndexData,
-    builder: ItemContentBuilder<'a, 'b, 'tcx>,
-}
-
-/// Builder that can encode the content of items, but can't start a
-/// new item itself. Most code is attached to here.
-pub struct ItemContentBuilder<'a, 'b: 'a, 'tcx: 'b> {
-    xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
     pub ecx: &'a mut EncodeContext<'b, 'tcx>,
 }
 
 impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> {
-    type Target = EncodeContext<'b, 'tcx>;
-    fn deref(&self) -> &Self::Target {
-        self.builder.ecx
-    }
-}
-
-impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        self.builder.ecx
-    }
-}
-
-impl<'a, 'b, 'tcx> Deref for ItemContentBuilder<'a, 'b, 'tcx> {
     type Target = EncodeContext<'b, 'tcx>;
     fn deref(&self) -> &Self::Target {
         self.ecx
     }
 }
 
-impl<'a, 'b, 'tcx> DerefMut for ItemContentBuilder<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         self.ecx
     }
 }
 
-/// "interned" entries referenced by id
-#[derive(PartialEq, Eq, Hash)]
-pub enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
-
 impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
     pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
         IndexBuilder {
             items: IndexData::new(ecx.tcx.map.num_local_def_ids()),
-            builder: ItemContentBuilder {
-                ecx: ecx,
-                xrefs: FnvHashMap(),
-            },
+            ecx: ecx,
         }
     }
 
@@ -147,28 +113,21 @@ pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
     /// content system.
     pub fn record<DATA>(&mut self,
                         id: DefId,
-                        op: fn(&mut ItemContentBuilder<'a, 'b, 'tcx>, DATA),
+                        op: fn(&mut EncodeContext<'b, 'tcx>, DATA),
                         data: DATA)
         where DATA: DepGraphRead
     {
-        let position = self.builder.ecx.mark_stable_position();
+        let position = self.ecx.mark_stable_position();
         self.items.record(id, position);
         let _task = self.tcx.dep_graph.in_task(DepNode::MetaData(id));
-        self.builder.ecx.start_tag(tag_items_data_item).unwrap();
+        self.ecx.start_tag(tag_items_data_item).unwrap();
         data.read(self.tcx);
-        op(&mut self.builder, data);
-        self.builder.ecx.end_tag().unwrap();
-    }
-
-    pub fn into_fields(self) -> (IndexData, FnvHashMap<XRef<'tcx>, u32>) {
-        (self.items, self.builder.xrefs)
+        op(&mut self.ecx, data);
+        self.ecx.end_tag().unwrap();
     }
-}
 
-impl<'a, 'b, 'tcx> ItemContentBuilder<'a, 'b, 'tcx> {
-    pub fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
-        let old_len = self.xrefs.len() as u32;
-        *self.xrefs.entry(xref).or_insert(old_len)
+    pub fn into_items(self) -> IndexData {
+        self.items
     }
 }
 
index e5f7aab38c364a3e540dd24f69e78261a8b1876b..b7125daa4ad5773b0b0a84bbf46b4a42db6ac051 100644 (file)
@@ -17,6 +17,7 @@
        html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![cfg_attr(not(stage0), deny(warnings))]
 
+#![feature(conservative_impl_trait)]
 #![feature(core_intrinsics)]
 #![feature(box_patterns)]
 #![feature(dotdot_in_tuple_patterns)]
index 9bbeb73ce3ecae470dd54952938f417d157d344d..24a0329602beb0becc3440aa120a05f0fa711cca 100644 (file)
@@ -80,19 +80,16 @@ pub fn at(data: &'doc [u8], start: usize) -> Doc<'doc> {
     }
 
     pub fn get(&self, tag: usize) -> Doc<'doc> {
-        get_doc(*self, tag)
-    }
-
-    pub fn is_empty(&self) -> bool {
-        self.start == self.end
-    }
-
-    pub fn as_str(&self) -> &'doc str {
-        str::from_utf8(&self.data[self.start..self.end]).unwrap()
+        match maybe_get_doc(*self, tag) {
+            Some(d) => d,
+            None => {
+                bug!("failed to find block with tag {:?}", tag);
+            }
+        }
     }
 
-    pub fn to_string(&self) -> String {
-        self.as_str().to_string()
+    pub fn children(self) -> DocsIterator<'doc> {
+        DocsIterator { d: self }
     }
 }
 
@@ -129,7 +126,7 @@ pub struct Res {
     pub next: usize,
 }
 
-pub fn tag_at(data: &[u8], start: usize) -> Result<Res, Error> {
+fn tag_at(data: &[u8], start: usize) -> Result<Res, Error> {
     let v = data[start] as usize;
     if v < 0xf0 {
         Ok(Res {
@@ -180,7 +177,7 @@ fn vuint_at_slow(data: &[u8], start: usize) -> Result<Res, Error> {
     Err(Error::IntTooBig(a as usize))
 }
 
-pub fn vuint_at(data: &[u8], start: usize) -> Result<Res, Error> {
+fn vuint_at(data: &[u8], start: usize) -> Result<Res, Error> {
     if data.len() - start < 4 {
         return vuint_at_slow(data, start);
     }
@@ -234,7 +231,7 @@ pub fn vuint_at(data: &[u8], start: usize) -> Result<Res, Error> {
     }
 }
 
-pub fn tag_len_at(data: &[u8], next: usize) -> Result<Res, Error> {
+fn tag_len_at(data: &[u8], next: usize) -> Result<Res, Error> {
     vuint_at(data, next)
 }
 
@@ -255,27 +252,14 @@ pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option<Doc<'a>> {
     None
 }
 
-pub fn get_doc<'a>(d: Doc<'a>, tg: usize) -> Doc<'a> {
-    match maybe_get_doc(d, tg) {
-        Some(d) => d,
-        None => {
-            bug!("failed to find block with tag {:?}", tg);
-        }
-    }
-}
-
-pub fn docs<'a>(d: Doc<'a>) -> DocsIterator<'a> {
-    DocsIterator { d: d }
-}
-
 pub struct DocsIterator<'a> {
     d: Doc<'a>,
 }
 
 impl<'a> Iterator for DocsIterator<'a> {
-    type Item = (usize, Doc<'a>);
+    type Item = Doc<'a>;
 
-    fn next(&mut self) -> Option<(usize, Doc<'a>)> {
+    fn next(&mut self) -> Option<Doc<'a>> {
         if self.d.start >= self.d.end {
             return None;
         }
@@ -297,98 +281,10 @@ fn next(&mut self) -> Option<(usize, Doc<'a>)> {
         };
 
         self.d.start = end;
-        return Some((elt_tag.val, doc));
-    }
-}
-
-pub fn tagged_docs<'a>(d: Doc<'a>, tag: usize) -> TaggedDocsIterator<'a> {
-    TaggedDocsIterator {
-        iter: docs(d),
-        tag: tag,
+        return Some(doc);
     }
 }
 
-pub struct TaggedDocsIterator<'a> {
-    iter: DocsIterator<'a>,
-    tag: usize,
-}
-
-impl<'a> Iterator for TaggedDocsIterator<'a> {
-    type Item = Doc<'a>;
-
-    fn next(&mut self) -> Option<Doc<'a>> {
-        while let Some((tag, doc)) = self.iter.next() {
-            if tag == self.tag {
-                return Some(doc);
-            }
-        }
-        None
-    }
-}
-
-pub fn with_doc_data<T, F>(d: Doc, f: F) -> T
-    where F: FnOnce(&[u8]) -> T
-{
-    f(&d.data[d.start..d.end])
-}
-
-pub fn doc_as_u8(d: Doc) -> u8 {
-    assert_eq!(d.end, d.start + 1);
-    d.data[d.start]
-}
-
-pub fn doc_as_u64(d: Doc) -> u64 {
-    if d.end >= 8 {
-        // For performance, we read 8 big-endian bytes,
-        // and mask off the junk if there is any. This
-        // obviously won't work on the first 8 bytes
-        // of a file - we will fall of the start
-        // of the page and segfault.
-
-        let mut b = [0; 8];
-        b.copy_from_slice(&d.data[d.end - 8..d.end]);
-        let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() };
-        let len = d.end - d.start;
-        if len < 8 {
-            data & ((1 << (len * 8)) - 1)
-        } else {
-            data
-        }
-    } else {
-        let mut result = 0;
-        for b in &d.data[d.start..d.end] {
-            result = (result << 8) + (*b as u64);
-        }
-        result
-    }
-}
-
-#[inline]
-pub fn doc_as_u16(d: Doc) -> u16 {
-    doc_as_u64(d) as u16
-}
-#[inline]
-pub fn doc_as_u32(d: Doc) -> u32 {
-    doc_as_u64(d) as u32
-}
-
-#[inline]
-pub fn doc_as_i8(d: Doc) -> i8 {
-    doc_as_u8(d) as i8
-}
-#[inline]
-pub fn doc_as_i16(d: Doc) -> i16 {
-    doc_as_u16(d) as i16
-}
-#[inline]
-pub fn doc_as_i32(d: Doc) -> i32 {
-    doc_as_u32(d) as i32
-}
-#[inline]
-pub fn doc_as_i64(d: Doc) -> i64 {
-    doc_as_u64(d) as i64
-}
-
 #[test]
 fn test_vuint_at() {
     let data = &[
index 94e9b394f1f90c7eb61a02c2cead3e5264934d27..46b63cb134031ac413b396dd6d7f7f44bb8d4a5e 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::mem;
 use std::io::prelude::*;
 use std::io::{self, SeekFrom, Cursor};
 
@@ -112,50 +111,10 @@ pub fn end_tag(&mut self) -> EncodeResult {
         Ok(())
     }
 
-    pub fn wr_tag<F>(&mut self, tag_id: usize, blk: F) -> EncodeResult
-        where F: FnOnce() -> EncodeResult
-    {
-        self.start_tag(tag_id)?;
-        blk()?;
-        self.end_tag()
-    }
-
-    pub fn wr_tagged_bytes(&mut self, tag_id: usize, b: &[u8]) -> EncodeResult {
-        write_tag(&mut self.opaque.cursor, tag_id)?;
-        write_vuint(&mut self.opaque.cursor, b.len())?;
-        self.opaque.cursor.write_all(b)
-    }
-
-    pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
-        let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
-        // tagged integers are emitted in big-endian, with no
-        // leading zeros.
-        let leading_zero_bytes = v.leading_zeros() / 8;
-        self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..])
-    }
-
-    #[inline]
-    pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32) -> EncodeResult {
-        self.wr_tagged_u64(tag_id, v as u64)
-    }
-
-    #[inline]
-    pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
-        self.wr_tagged_bytes(tag_id, &[v])
-    }
-
     pub fn wr_tagged_str(&mut self, tag_id: usize, v: &str) -> EncodeResult {
-        self.wr_tagged_bytes(tag_id, v.as_bytes())
-    }
-
-    pub fn wr_bytes(&mut self, b: &[u8]) -> EncodeResult {
-        debug!("Write {:?} bytes", b.len());
-        self.opaque.cursor.write_all(b)
-    }
-
-    pub fn wr_str(&mut self, s: &str) -> EncodeResult {
-        debug!("Write str: {:?}", s);
-        self.opaque.cursor.write_all(s.as_bytes())
+        write_tag(&mut self.opaque.cursor, tag_id)?;
+        write_vuint(&mut self.opaque.cursor, v.len())?;
+        self.opaque.cursor.write_all(v.as_bytes())
     }
 
     pub fn position(&mut self) -> usize {
index 83f03e7cfc5acc2f09b6379b91295e36ca059f47..3df3a2decba3ba0dd6edf89c6d2a08ebc9d793a9 100644 (file)
 use Resolver;
 use {resolve_error, resolve_struct_error, ResolutionError};
 
-use rustc::middle::cstore::{ChildItem, DlDef};
+use rustc::middle::cstore::ChildItem;
 use rustc::hir::def::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
-use rustc::ty::{self, VariantKind};
+use rustc::ty;
 
 use std::cell::Cell;
 
@@ -201,7 +201,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item) {
                     let module = self.new_extern_crate_module(parent_link, def, item.id);
                     self.define(parent, name, TypeNS, (module, sp, vis));
 
-                    self.build_reduced_graph_for_external_crate(module);
+                    self.populate_module_if_necessary(module);
                 }
             }
 
@@ -388,13 +388,8 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) {
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcdef: ChildItem) {
-        let def = match xcdef.def {
-            DlDef(def) => def,
-            _ => return,
-        };
-
-        if let Def::ForeignMod(def_id) = def {
+    fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: ChildItem) {
+        if let Def::ForeignMod(def_id) = child.def {
             // Foreign modules have no names. Recur and populate eagerly.
             for child in self.session.cstore.item_children(def_id) {
                 self.build_reduced_graph_for_external_crate_def(parent, child);
@@ -402,8 +397,9 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcd
             return;
         }
 
-        let name = xcdef.name;
-        let vis = if parent.is_trait() { ty::Visibility::Public } else { xcdef.vis };
+        let def = child.def;
+        let name = child.name;
+        let vis = if parent.is_trait() { ty::Visibility::Public } else { child.vis };
 
         match def {
             Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => {
@@ -413,16 +409,12 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcd
                 let module = self.new_module(parent_link, Some(def), None);
                 let _ = self.try_define(parent, name, TypeNS, (module, DUMMY_SP, vis));
             }
-            Def::Variant(_, variant_id) => {
+            Def::Variant(..) => {
                 debug!("(building reduced graph for external crate) building variant {}", name);
                 // Variants are always treated as importable to allow them to be glob used.
                 // All variants are defined in both type and value namespaces as future-proofing.
                 let _ = self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
                 let _ = self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
-                if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
-                    // Not adding fields for variants as they are not accessed with a self receiver
-                    self.structs.insert(variant_id, Vec::new());
-                }
             }
             Def::Fn(..) |
             Def::Static(..) |
@@ -439,7 +431,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcd
                 // If this is a trait, add all the trait item names to the trait
                 // info.
 
-                let trait_item_def_ids = self.session.cstore.trait_item_def_ids(def_id);
+                let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id);
                 for trait_item_def in &trait_item_def_ids {
                     let trait_item_name =
                         self.session.cstore.item_name(trait_item_def.def_id());
@@ -493,15 +485,6 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, xcd
         }
     }
 
-    /// Builds the reduced graph rooted at the 'use' directive for an external
-    /// crate.
-    fn build_reduced_graph_for_external_crate(&mut self, root: Module<'b>) {
-        let root_cnum = root.def_id().unwrap().krate;
-        for child in self.session.cstore.crate_top_level_items(root_cnum) {
-            self.build_reduced_graph_for_external_crate_def(root, child);
-        }
-    }
-
     /// Ensures that the reduced graph rooted at the given external module
     /// is built, building it if it is not.
     pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
index 5e78ac7ca94c7a69d8639baa07656977183624b1..b03e76c829a3e9f4d6bd6741665c1d89e0083ca5 100644 (file)
@@ -1275,6 +1275,7 @@ fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def, local_n
                                -> Module<'a> {
         let mut module = ModuleS::new(parent_link, Some(def), Some(local_node_id));
         module.extern_crate_id = Some(local_node_id);
+        module.populated.set(false);
         self.arenas.modules.alloc(module)
     }
 
index 3764e26b020db414e28caeb5b2a52a5d9c014e98..186183a8ad4d4f37765ca008e833d4b1e0e74bc2 100644 (file)
@@ -543,10 +543,8 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
                                 .map(|mr| mr.def_id())
                         }
                         ty::ImplContainer(def_id) => {
-                            let impl_items = self.tcx.impl_items.borrow();
-                            Some(impl_items.get(&def_id)
-                                           .unwrap()
-                                           .iter()
+                            let impl_items = self.tcx.impl_or_trait_items(def_id);
+                            Some(impl_items.iter()
                                            .find(|mr| {
                                                self.tcx.impl_or_trait_item(mr.def_id()).name() ==
                                                ti.name()
index a58de71ca41ed2e8247af47ea0e094f67e359ad1..b9449eeecf427f260c649187d796eb98f8d5cd0e 100644 (file)
@@ -627,25 +627,23 @@ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
         fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               def_id: DefId)
                                               -> bool {
-            if !match tcx.lookup_item_type(def_id).ty.sty {
-                ty::TyFnDef(def_id, ..) => {
+            match tcx.lookup_item_type(def_id).ty.sty {
+                ty::TyFnDef(def_id, _, f) => {
                     // Some constructors also have type TyFnDef but they are
                     // always instantiated inline and don't result in
                     // translation item. Same for FFI functions.
-                    match tcx.map.get_if_local(def_id) {
-                        Some(hir_map::NodeVariant(_))    |
-                        Some(hir_map::NodeStructCtor(_)) |
-                        Some(hir_map::NodeForeignItem(_)) => false,
-                        Some(_) => true,
-                        None => {
-                            tcx.sess.cstore.variant_kind(def_id).is_none()
+                    if let Some(hir_map::NodeForeignItem(_)) = tcx.map.get_if_local(def_id) {
+                        return false;
+                    }
+
+                    if let Some(adt_def) = f.sig.output().skip_binder().ty_adt_def() {
+                        if adt_def.variants.iter().any(|v| def_id == v.did) {
+                            return false;
                         }
                     }
                 }
-                ty::TyClosure(..) => true,
-                _ => false
-            } {
-                return false;
+                ty::TyClosure(..) => {}
+                _ => return false
             }
 
             can_have_local_instance(tcx, def_id)
index ee2f24d21e07cb846e6f3ea6be5aae8bab081b2a..9db5020747e1f39619a2c49db9eb733955007dfb 100644 (file)
@@ -230,7 +230,7 @@ pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     tcx.populate_implementations_for_trait_if_necessary(trait_id);
 
-    let trait_item_def_ids = tcx.trait_item_def_ids(trait_id);
+    let trait_item_def_ids = tcx.impl_or_trait_items(trait_id);
     trait_item_def_ids
         .iter()
 
index e9f324c0b08f00e16cb9a9f4d5bb509089732514..999433db2407182d22204d96adbb6aa29b209c05 100644 (file)
@@ -247,11 +247,17 @@ fn trans_def(ccx: &'a CrateContext<'a, 'tcx>,
             let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
             if let traits::VtableImpl(vtable_impl) = vtable {
                 let name = ccx.tcx().item_name(instance.def);
-                for ac in ccx.tcx().associated_consts(vtable_impl.impl_def_id) {
-                    if ac.name == name {
-                        instance = Instance::new(ac.def_id, vtable_impl.substs);
-                        break;
-                    }
+                let ac = ccx.tcx().impl_or_trait_items(vtable_impl.impl_def_id)
+                    .iter().filter_map(|id| {
+                        match *id {
+                            ty::ConstTraitItemId(def_id) => {
+                                Some(ccx.tcx().impl_or_trait_item(def_id))
+                            }
+                            _ => None
+                        }
+                    }).find(|ic| ic.name() == name);
+                if let Some(ac) = ac {
+                    instance = Instance::new(ac.def_id(), vtable_impl.substs);
                 }
             }
         }
index bcb410e1b8d0132b284ce0932e43cec3f366b85b..71219d82668e4f4822ceb2eec27e9ee5f93a06e5 100644 (file)
@@ -218,7 +218,7 @@ pub fn lookup_method_in_trait_adjusted(&self,
         // Trait must have a method named `m_name` and it should not have
         // type parameters or early-bound regions.
         let tcx = self.tcx;
-        let method_item = self.trait_item(trait_def_id, m_name).unwrap();
+        let method_item = self.impl_or_trait_item(trait_def_id, m_name).unwrap();
         let method_ty = method_item.as_opt_method().unwrap();
         assert_eq!(method_ty.generics.types.len(), 0);
         assert_eq!(method_ty.generics.regions.len(), 0);
@@ -359,27 +359,14 @@ pub fn resolve_ufcs(&self,
         Ok(def)
     }
 
-    /// Find item with name `item_name` defined in `trait_def_id`
-    /// and return it, or `None`, if no such item.
-    pub fn trait_item(&self,
-                      trait_def_id: DefId,
-                      item_name: ast::Name)
-                      -> Option<ty::ImplOrTraitItem<'tcx>>
+    /// Find item with name `item_name` defined in impl/trait `def_id`
+    /// and return it, or `None`, if no such item was defined there.
+    pub fn impl_or_trait_item(&self,
+                              def_id: DefId,
+                              item_name: ast::Name)
+                              -> Option<ty::ImplOrTraitItem<'tcx>>
     {
-        let trait_items = self.tcx.trait_items(trait_def_id);
-        trait_items.iter()
-                   .find(|item| item.name() == item_name)
-                   .cloned()
-    }
-
-    pub fn impl_item(&self,
-                     impl_def_id: DefId,
-                     item_name: ast::Name)
-                     -> Option<ty::ImplOrTraitItem<'tcx>>
-    {
-        let impl_items = self.tcx.impl_items.borrow();
-        let impl_items = impl_items.get(&impl_def_id).unwrap();
-        impl_items
+        self.tcx.impl_or_trait_items(def_id)
             .iter()
             .map(|&did| self.tcx.impl_or_trait_item(did.def_id()))
             .find(|m| m.name() == item_name)
index 81e95c91e7ff94e0657b5225be12e2acdb766ace..9fba9bcb757b6a78149d03e1dd0565fe7f7e0fba 100644 (file)
@@ -403,7 +403,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
 
         debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
 
-        let item = match self.impl_item(impl_def_id) {
+        let item = match self.impl_or_trait_item(impl_def_id) {
             Some(m) => m,
             None => { return; } // No method with correct name on this impl
         };
@@ -555,7 +555,7 @@ fn elaborate_bounds<F>(
 
         let tcx = self.tcx;
         for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
-            let item = match self.trait_item(bound_trait_ref.def_id()) {
+            let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
                 Some(v) => v,
                 None => { continue; }
             };
@@ -1292,18 +1292,12 @@ fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
         self.tcx.erase_late_bound_regions(value)
     }
 
-    fn impl_item(&self, impl_def_id: DefId)
-                 -> Option<ty::ImplOrTraitItem<'tcx>>
+    /// Find item with name `item_name` defined in impl/trait `def_id`
+    /// and return it, or `None`, if no such item was defined there.
+    fn impl_or_trait_item(&self, def_id: DefId)
+                          -> Option<ty::ImplOrTraitItem<'tcx>>
     {
-        self.fcx.impl_item(impl_def_id, self.item_name)
-    }
-
-    /// Find item with name `item_name` defined in `trait_def_id`
-    /// and return it, or `None`, if no such item.
-    fn trait_item(&self, trait_def_id: DefId)
-                  -> Option<ty::ImplOrTraitItem<'tcx>>
-    {
-        self.fcx.trait_item(trait_def_id, self.item_name)
+        self.fcx.impl_or_trait_item(def_id, self.item_name)
     }
 }
 
index 3692d6fbf73d6a9069ebb472ad5bb8cda3cae1c4..7ec4918070233eb94e720922531c43997166f606 100644 (file)
@@ -16,9 +16,8 @@
 use check::{FnCtxt};
 use rustc::hir::map as hir_map;
 use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
-use middle::cstore;
 use hir::def::Def;
-use hir::def_id::DefId;
+use hir::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::lang_items::FnOnceTraitLangItem;
 use rustc::ty::subst::Substs;
 use rustc::traits::{Obligation, SelectionContext};
@@ -92,9 +91,9 @@ pub fn report_method_error(&self,
                     CandidateSource::ImplSource(impl_did) => {
                         // Provide the best span we can. Use the item, if local to crate, else
                         // the impl, if local to crate (item may be defaulted), else nothing.
-                        let item = self.impl_item(impl_did, item_name)
+                        let item = self.impl_or_trait_item(impl_did, item_name)
                             .or_else(|| {
-                                self.trait_item(
+                                self.impl_or_trait_item(
                                     self.tcx.impl_trait_ref(impl_did).unwrap().def_id,
 
                                     item_name
@@ -127,7 +126,7 @@ pub fn report_method_error(&self,
                         }
                     }
                     CandidateSource::TraitSource(trait_did) => {
-                        let item = self.trait_item(trait_did, item_name).unwrap();
+                        let item = self.impl_or_trait_item(trait_did, item_name).unwrap();
                         let item_span = self.tcx.map.def_id_span(item.def_id(), span);
                         span_note!(err, item_span,
                                    "candidate #{} is defined in the trait `{}`",
@@ -321,7 +320,7 @@ fn suggest_traits_to_import(&self,
                 // implementing a trait would be legal but is rejected
                 // here).
                 (type_is_local || info.def_id.is_local())
-                    && self.trait_item(info.def_id, item_name).is_some()
+                    && self.impl_or_trait_item(info.def_id, item_name).is_some()
             })
             .collect::<Vec<_>>();
 
@@ -449,34 +448,30 @@ fn visit_item(&mut self, i: &'v hir::Item) {
 
         // Cross-crate:
         let mut external_mods = FnvHashSet();
-        fn handle_external_def(traits: &mut AllTraitsVec,
+        fn handle_external_def(ccx: &CrateCtxt,
+                               traits: &mut AllTraitsVec,
                                external_mods: &mut FnvHashSet<DefId>,
-                               ccx: &CrateCtxt,
-                               cstore: &for<'a> cstore::CrateStore<'a>,
-                               dl: cstore::DefLike) {
-            match dl {
-                cstore::DlDef(Def::Trait(did)) => {
+                               def: Def) {
+            match def {
+                Def::Trait(did) => {
                     traits.push(TraitInfo::new(did));
                 }
-                cstore::DlDef(Def::Mod(did)) => {
+                Def::Mod(did) => {
                     if !external_mods.insert(did) {
                         return;
                     }
-                    for child in cstore.item_children(did) {
-                        handle_external_def(traits, external_mods,
-                                            ccx, cstore, child.def)
+                    for child in ccx.tcx.sess.cstore.item_children(did) {
+                        handle_external_def(ccx, traits, external_mods, child.def)
                     }
                 }
                 _ => {}
             }
         }
-        let cstore = &*ccx.tcx.sess.cstore;
-
         for cnum in ccx.tcx.sess.cstore.crates() {
-            for child in cstore.crate_top_level_items(cnum) {
-                handle_external_def(&mut traits, &mut external_mods,
-                                    ccx, cstore, child.def)
-            }
+            handle_external_def(ccx, &mut traits, &mut external_mods, Def::Mod(DefId {
+                krate: cnum,
+                index: CRATE_DEF_INDEX
+            }));
         }
 
         *ccx.all_traits.borrow_mut() = Some(traits);
index 26c33c00b9cf923b71db950433c38df6dd6dc3c3..fb077d279c99875b84e54fda5d99fec2d5ed9310 100644 (file)
@@ -39,6 +39,8 @@
 use rustc::hir::{Item, ItemImpl};
 use rustc::hir;
 
+use std::rc::Rc;
+
 mod orphan;
 mod overlap;
 mod unsafety;
@@ -156,7 +158,7 @@ fn check_implementation(&self, item: &Item) {
             }
         }
 
-        tcx.impl_items.borrow_mut().insert(impl_did, impl_items);
+        tcx.impl_or_trait_item_ids.borrow_mut().insert(impl_did, Rc::new(impl_items));
     }
 
     fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
@@ -208,7 +210,7 @@ fn populate_destructors(&self) {
         tcx.populate_implementations_for_trait_if_necessary(drop_trait);
         let drop_trait = tcx.lookup_trait_def(drop_trait);
 
-        let impl_items = tcx.impl_items.borrow();
+        let impl_items = tcx.impl_or_trait_item_ids.borrow();
 
         drop_trait.for_each_impl(tcx, |impl_did| {
             let items = impl_items.get(&impl_did).unwrap();
index 890b6c72e6fee5baeae296751b6aef687cabf543..9d072491cc28b532871b54723f54dcb55150fa08 100644 (file)
@@ -55,12 +55,12 @@ fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             })
         }
 
-        let impl_items = self.tcx.impl_items.borrow();
+        let impl_items = self.tcx.impl_or_trait_item_ids.borrow();
 
-        for item1 in &impl_items[&impl1] {
+        for item1 in &impl_items[&impl1][..] {
             let (name, namespace) = name_and_namespace(self.tcx, item1);
 
-            for item2 in &impl_items[&impl2] {
+            for item2 in &impl_items[&impl2][..] {
                 if (name, namespace) == name_and_namespace(self.tcx, item2) {
                     let msg = format!("duplicate definitions with name `{}`", name);
                     let node_id = self.tcx.map.as_local_node_id(item1.def_id()).unwrap();
index 04aca8c0947caa7e603a9bbfd8efe499c965d4df..fa052bec7be3d6f1eab92d9e221feb62b432b815 100644 (file)
@@ -563,6 +563,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             vis: &hir::Visibility,
                             sig: &hir::MethodSig,
                             defaultness: hir::Defaultness,
+                            has_body: bool,
                             untransformed_rcvr_ty: Ty<'tcx>,
                             rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) {
     let def_id = ccx.tcx.map.local_def_id(id);
@@ -580,15 +581,18 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               sig, untransformed_rcvr_ty, anon_scope)
     };
 
-    let ty_method = ty::Method::new(name,
-                                    ty_generics,
-                                    ty_generic_predicates,
-                                    fty,
-                                    explicit_self_category,
-                                    ty::Visibility::from_hir(vis, id, ccx.tcx),
-                                    defaultness,
-                                    def_id,
-                                    container);
+    let ty_method = ty::Method {
+        name: name,
+        generics: ty_generics,
+        predicates: ty_generic_predicates,
+        fty: fty,
+        explicit_self: explicit_self_category,
+        vis: ty::Visibility::from_hir(vis, id, ccx.tcx),
+        defaultness: defaultness,
+        has_body: has_body,
+        def_id: def_id,
+        container: container,
+    };
 
     let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
                                 ccx.tcx.map.span(id), def_id);
@@ -843,7 +847,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
                     convert_method(ccx, ImplContainer(def_id),
                                    impl_item.name, impl_item.id, method_vis,
-                                   sig, impl_item.defaultness, selfty,
+                                   sig, impl_item.defaultness, true, selfty,
                                    &ty_predicates);
                 }
             }
@@ -905,7 +909,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
             // Convert all the methods
             for trait_item in trait_items {
-                if let hir::MethodTraitItem(ref sig, _) = trait_item.node {
+                if let hir::MethodTraitItem(ref sig, ref body) = trait_item.node {
                     convert_method(ccx,
                                    container,
                                    trait_item.name,
@@ -913,6 +917,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                                    &hir::Inherited,
                                    sig,
                                    hir::Defaultness::Default,
+                                   body.is_some(),
                                    tcx.mk_self_type(),
                                    &trait_predicates);
 
@@ -928,8 +933,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     hir::TypeTraitItem(..) => ty::TypeTraitItemId(def_id)
                 }
             }).collect());
-            tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
-                                                       trait_item_def_ids);
+            tcx.impl_or_trait_item_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
+                                                           trait_item_def_ids);
         },
         hir::ItemStruct(ref struct_def, _) |
         hir::ItemUnion(ref struct_def, _) => {
index 709e36989244faa6ea602f609455ad627b5ee9e4..e992861b77bc6c29df444e4e32c15622f1068033 100644 (file)
@@ -15,7 +15,6 @@
 use syntax::ast;
 use rustc::hir;
 
-use rustc::middle::cstore;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::hir::print as pprust;
@@ -96,12 +95,12 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         Def::TyAlias(did) => {
             record_extern_fqn(cx, did, clean::TypeTypedef);
             ret.extend(build_impls(cx, tcx, did));
-            build_type(cx, tcx, did)
+            clean::TypedefItem(build_type_alias(cx, tcx, did), false)
         }
         Def::Enum(did) => {
             record_extern_fqn(cx, did, clean::TypeEnum);
             ret.extend(build_impls(cx, tcx, did));
-            build_type(cx, tcx, did)
+            clean::EnumItem(build_enum(cx, tcx, did))
         }
         // Assume that the enum type is reexported next to the variant, and
         // variants don't show up in documentation specially.
@@ -200,6 +199,18 @@ fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx
     }
 }
 
+fn build_enum<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        did: DefId) -> clean::Enum {
+    let t = tcx.lookup_item_type(did);
+    let predicates = tcx.lookup_predicates(did);
+
+    clean::Enum {
+        generics: (t.generics, &predicates).clean(cx),
+        variants_stripped: false,
+        variants: tcx.lookup_adt_def(did).variants.clean(cx),
+    }
+}
+
 fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           did: DefId) -> clean::Struct {
     let t = tcx.lookup_item_type(did);
@@ -232,25 +243,15 @@ fn build_union<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        did: DefId) -> clean::ItemEnum {
+fn build_type_alias<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              did: DefId) -> clean::Typedef {
     let t = tcx.lookup_item_type(did);
     let predicates = tcx.lookup_predicates(did);
-    match t.ty.sty {
-        ty::TyAdt(edef, _) if edef.is_enum() && !tcx.sess.cstore.is_typedef(did) => {
-            return clean::EnumItem(clean::Enum {
-                generics: (t.generics, &predicates).clean(cx),
-                variants_stripped: false,
-                variants: edef.variants.clean(cx),
-            })
-        }
-        _ => {}
-    }
 
-    clean::TypedefItem(clean::Typedef {
+    clean::Typedef {
         type_: t.ty.clean(cx),
         generics: (t.generics, &predicates).clean(cx),
-    }, false)
+    }
 }
 
 pub fn build_impls<'a, 'tcx>(cx: &DocContext,
@@ -264,32 +265,49 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext,
             build_impl(cx, tcx, did, &mut impls);
         }
     }
-
-    // If this is the first time we've inlined something from this crate, then
-    // we inline *all* impls from the crate into this crate. Note that there's
+    // If this is the first time we've inlined something from another crate, then
+    // we inline *all* impls from all the crates into this crate. Note that there's
     // currently no way for us to filter this based on type, and we likely need
     // many impls for a variety of reasons.
     //
     // Primarily, the impls will be used to populate the documentation for this
     // type being inlined, but impls can also be used when generating
     // documentation for primitives (no way to find those specifically).
-    if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
-        for item in tcx.sess.cstore.crate_top_level_items(did.krate) {
-            populate_impls(cx, tcx, item.def, &mut impls);
-        }
+    if cx.populated_all_crate_impls.get() {
+        return impls;
+    }
 
-        fn populate_impls<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                    def: cstore::DefLike,
-                                    impls: &mut Vec<clean::Item>) {
-            match def {
-                cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
-                cstore::DlDef(Def::Mod(did)) => {
-                    for item in tcx.sess.cstore.item_children(did) {
-                        populate_impls(cx, tcx, item.def, impls)
-                    }
-                }
-                _ => {}
-            }
+    cx.populated_all_crate_impls.set(true);
+
+    for did in tcx.sess.cstore.implementations_of_trait(None) {
+        build_impl(cx, tcx, did, &mut impls);
+    }
+
+    // Also try to inline primitive impls from other crates.
+    let primitive_impls = [
+        tcx.lang_items.isize_impl(),
+        tcx.lang_items.i8_impl(),
+        tcx.lang_items.i16_impl(),
+        tcx.lang_items.i32_impl(),
+        tcx.lang_items.i64_impl(),
+        tcx.lang_items.usize_impl(),
+        tcx.lang_items.u8_impl(),
+        tcx.lang_items.u16_impl(),
+        tcx.lang_items.u32_impl(),
+        tcx.lang_items.u64_impl(),
+        tcx.lang_items.f32_impl(),
+        tcx.lang_items.f64_impl(),
+        tcx.lang_items.char_impl(),
+        tcx.lang_items.str_impl(),
+        tcx.lang_items.slice_impl(),
+        tcx.lang_items.slice_impl(),
+        tcx.lang_items.const_ptr_impl()
+    ];
+
+    for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
+        if !def_id.is_local() {
+            tcx.populate_implementations_for_primitive_if_necessary(def_id);
+            build_impl(cx, tcx, def_id, &mut impls);
         }
     }
 
@@ -348,7 +366,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
     }
 
     let predicates = tcx.lookup_predicates(did);
-    let trait_items = tcx.sess.cstore.impl_items(did)
+    let trait_items = tcx.sess.cstore.impl_or_trait_items(did)
             .iter()
             .filter_map(|did| {
         let did = did.def_id();
@@ -453,7 +471,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
             for_: for_,
             generics: (ty.generics, &predicates).clean(cx),
             items: trait_items,
-            polarity: polarity.map(|p| { p.clean(cx) }),
+            polarity: Some(polarity.clean(cx)),
         }),
         source: clean::Span::empty(),
         name: None,
@@ -482,19 +500,17 @@ fn fill_in<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut visited = FnvHashSet();
         for item in tcx.sess.cstore.item_children(did) {
             match item.def {
-                cstore::DlDef(Def::ForeignMod(did)) => {
+                Def::ForeignMod(did) => {
                     fill_in(cx, tcx, did, items);
                 }
-                cstore::DlDef(def) if item.vis == ty::Visibility::Public => {
-                    if !visited.insert(def) { continue }
-                    if let Some(i) = try_inline_def(cx, tcx, def) {
-                        items.extend(i)
+                def => {
+                    if item.vis == ty::Visibility::Public {
+                        if !visited.insert(def) { continue }
+                        if let Some(i) = try_inline_def(cx, tcx, def) {
+                            items.extend(i)
+                        }
                     }
                 }
-                cstore::DlDef(..) => {}
-                // All impls were inlined above
-                cstore::DlImpl(..) => {}
-                cstore::DlField => panic!("unimplemented field"),
             }
         }
     }
index 7eb7b24015e101063f09c6dd63b39f719eb059bf..f9d7eb50edaec59ff10e6447b19d14d93a65c141 100644 (file)
@@ -33,7 +33,6 @@
 use syntax_pos::{self, DUMMY_SP, Pos};
 
 use rustc_trans::back::link;
-use rustc::middle::cstore;
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::resolve_lifetime::DefRegion::*;
 use rustc::hir::def::Def;
@@ -239,9 +238,10 @@ impl Clean<ExternalCrate> for CrateNum {
     fn clean(&self, cx: &DocContext) -> ExternalCrate {
         let mut primitives = Vec::new();
         cx.tcx_opt().map(|tcx| {
-            for item in tcx.sess.cstore.crate_top_level_items(self.0) {
+            let root = DefId { krate: self.0, index: CRATE_DEF_INDEX };
+            for item in tcx.sess.cstore.item_children(root) {
                 let did = match item.def {
-                    cstore::DlDef(Def::Mod(did)) => did,
+                    Def::Mod(did) => did,
                     _ => continue
                 };
                 let attrs = inline::load_attrs(cx, tcx, did);
@@ -1877,11 +1877,9 @@ fn clean(&self, cx: &DocContext) -> Item {
 
 impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
     fn clean(&self, cx: &DocContext) -> Item {
-        // FIXME: possible O(n^2)-ness! Not my fault.
-        let attr_map = cx.tcx().sess.cstore.crate_struct_field_attrs(self.did.krate);
         Item {
             name: Some(self.name).clean(cx),
-            attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx),
+            attrs: cx.tcx().get_attrs(self.did).clean(cx),
             source: Span::empty(),
             visibility: self.vis.clean(cx),
             stability: get_stability(cx, self.did),
index 399702003ea4fc59643a8c0333181c46d280f128..c52497dc89bd6b7c824ff2b3acc0010afddee7ab 100644 (file)
 use rustc_driver::{driver, target_features, abort_on_err};
 use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config};
-use rustc::hir::def_id::{CrateNum, DefId};
+use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, TyCtxt};
 use rustc::hir::map as hir_map;
 use rustc::lint;
-use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
+use rustc::util::nodemap::FnvHashMap;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
@@ -53,7 +53,7 @@ pub struct DocContext<'a, 'tcx: 'a> {
     pub map: &'a hir_map::Map<'tcx>,
     pub maybe_typed: MaybeTyped<'a, 'tcx>,
     pub input: Input,
-    pub populated_crate_impls: RefCell<FnvHashSet<CrateNum>>,
+    pub populated_all_crate_impls: Cell<bool>,
     pub deref_trait_did: Cell<Option<DefId>>,
     pub deref_mut_trait_did: Cell<Option<DefId>>,
     // Note that external items for which `doc(hidden)` applies to are shown as
@@ -205,7 +205,7 @@ pub fn run_core(search_paths: SearchPaths,
             map: &tcx.map,
             maybe_typed: Typed(tcx),
             input: input,
-            populated_crate_impls: Default::default(),
+            populated_all_crate_impls: Cell::new(false),
             deref_trait_did: Cell::new(None),
             deref_mut_trait_did: Cell::new(None),
             access_levels: RefCell::new(access_levels),
index 3d2caeda1468d7b38a02502fbf09d64c8514cfa3..4518945dd9857ffd99bed3791eb02f264dee4341 100644 (file)
@@ -106,8 +106,8 @@ pub fn run(input: &str,
         map: &map,
         maybe_typed: core::NotTyped(&sess),
         input: input,
+        populated_all_crate_impls: Cell::new(false),
         external_traits: Default::default(),
-        populated_crate_impls: Default::default(),
         deref_trait_did: Cell::new(None),
         deref_mut_trait_did: Cell::new(None),
         access_levels: Default::default(),
index cbc556730fb63099ddeefd3bcfced820563a6c24..da11f652b4b34d6df44e51077ef682a4e01af1db 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::middle::cstore::{CrateStore, ChildItem, DefLike};
+use rustc::middle::cstore::{CrateStore, ChildItem};
 use rustc::middle::privacy::{AccessLevels, AccessLevel};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
@@ -66,39 +66,32 @@ fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLev
 
     pub fn visit_mod(&mut self, did: DefId) {
         for item in self.cstore.item_children(did) {
-            if let DefLike::DlDef(def) = item.def {
-                match def {
-                    Def::Mod(did) |
-                    Def::ForeignMod(did) |
-                    Def::Trait(did) |
-                    Def::Struct(did) |
-                    Def::Union(did) |
-                    Def::Enum(did) |
-                    Def::TyAlias(did) |
-                    Def::Fn(did) |
-                    Def::Method(did) |
-                    Def::Static(did, _) |
-                    Def::Const(did) => self.visit_item(did, item),
-                    _ => {}
-                }
+            match item.def {
+                Def::Mod(did) |
+                Def::ForeignMod(did) |
+                Def::Trait(did) |
+                Def::Struct(did) |
+                Def::Union(did) |
+                Def::Enum(did) |
+                Def::TyAlias(did) |
+                Def::Fn(did) |
+                Def::Method(did) |
+                Def::Static(did, _) |
+                Def::Const(did) => self.visit_item(did, item),
+                _ => {}
             }
         }
     }
 
     fn visit_item(&mut self, did: DefId, item: ChildItem) {
         let inherited_item_level = match item.def {
-            DefLike::DlImpl(..) | DefLike::DlField => unreachable!(),
-            DefLike::DlDef(def) => {
-                match def {
-                    Def::ForeignMod(..) => self.prev_level,
-                    _ => if item.vis == Visibility::Public { self.prev_level } else { None }
-                }
-            }
+            Def::ForeignMod(..) => self.prev_level,
+            _ => if item.vis == Visibility::Public { self.prev_level } else { None }
         };
 
         let item_level = self.update(did, inherited_item_level);
 
-        if let DefLike::DlDef(Def::Mod(did)) = item.def {
+        if let Def::Mod(did) = item.def {
             let orig_level = self.prev_level;
 
             self.prev_level = item_level;