about summary refs log tree commit diff
path: root/src/librustc/metadata/encoder.rs
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2014-02-14 07:07:09 +0200
committerEduard Burtescu <edy.burt@gmail.com>2014-02-14 08:43:29 +0200
commita02b10a0621adfe36eb3cc2e46f45fc7ccdb7ea2 (patch)
tree86fe8ac57360a232b07c4303547194646129561a /src/librustc/metadata/encoder.rs
parent22c34f3c4cddea33b916eb92f8d7286b02b865a7 (diff)
Refactored ast_map and friends, mainly to have Paths without storing them.
Diffstat (limited to 'src/librustc/metadata/encoder.rs')
-rw-r--r--src/librustc/metadata/encoder.rs375
1 files changed, 150 insertions, 225 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index b5fef36607f..5fb3f48bd6e 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -28,10 +28,10 @@ use std::cell::{Cell, RefCell};
 use std::hashmap::{HashMap, HashSet};
 use std::io::MemWriter;
 use std::str;
-use std::vec;
 use syntax::abi::AbiSet;
 use syntax::ast::*;
 use syntax::ast;
+use syntax::ast_map::{PathElem, PathElems};
 use syntax::ast_map;
 use syntax::ast_util::*;
 use syntax::ast_util;
@@ -57,10 +57,9 @@ pub enum InlinedItemRef<'a> {
     IIForeignRef(&'a ast::ForeignItem)
 }
 
-pub type encode_inlined_item<'a> = 'a |ecx: &EncodeContext,
-                                       ebml_w: &mut writer::Encoder,
-                                       path: &[ast_map::PathElem],
-                                       ii: InlinedItemRef|;
+pub type EncodeInlinedItem<'a> = 'a |ecx: &EncodeContext,
+                                     ebml_w: &mut writer::Encoder,
+                                     ii: InlinedItemRef|;
 
 pub struct EncodeParams<'a> {
     diag: @SpanHandler,
@@ -70,7 +69,7 @@ pub struct EncodeParams<'a> {
     non_inlineable_statics: &'a RefCell<HashSet<ast::NodeId>>,
     link_meta: &'a LinkMeta,
     cstore: @cstore::CStore,
-    encode_inlined_item: encode_inlined_item<'a>,
+    encode_inlined_item: EncodeInlinedItem<'a>,
     reachable: @RefCell<HashSet<ast::NodeId>>,
     codemap: @codemap::CodeMap,
 }
@@ -100,7 +99,7 @@ pub struct EncodeContext<'a> {
     non_inlineable_statics: &'a RefCell<HashSet<ast::NodeId>>,
     link_meta: &'a LinkMeta,
     cstore: &'a cstore::CStore,
-    encode_inlined_item: encode_inlined_item<'a>,
+    encode_inlined_item: EncodeInlinedItem<'a>,
     type_abbrevs: abbrev_map,
     reachable: @RefCell<HashSet<ast::NodeId>>,
     codemap: @codemap::CodeMap,
@@ -111,17 +110,12 @@ pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool {
     reachable.get().contains(&id)
 }
 
-fn encode_name(ecx: &EncodeContext,
-               ebml_w: &mut writer::Encoder,
-               name: Ident) {
-    ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
+fn encode_name(ebml_w: &mut writer::Encoder, name: Ident) {
+    ebml_w.wr_tagged_str(tag_paths_data_name, token::get_ident(name).get());
 }
 
-fn encode_impl_type_basename(ecx: &EncodeContext,
-                             ebml_w: &mut writer::Encoder,
-                             name: Ident) {
-    ebml_w.wr_tagged_str(tag_item_impl_type_basename,
-                         ecx.tcx.sess.str_of(name));
+fn encode_impl_type_basename(ebml_w: &mut writer::Encoder, name: Ident) {
+    ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
 }
 
 pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
@@ -188,13 +182,12 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
 }
 
 fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
-                            ecx: &EncodeContext,
                             params: &[ty::RegionParameterDef]) {
     for param in params.iter() {
         ebml_w.start_tag(tag_region_param_def);
 
         ebml_w.start_tag(tag_region_param_def_ident);
-        encode_name(ecx, ebml_w, param.ident);
+        encode_name(ebml_w, param.ident);
         ebml_w.end_tag();
 
         ebml_w.wr_tagged_str(tag_region_param_def_def_id,
@@ -218,7 +211,7 @@ fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
                           tpt: &ty::ty_param_bounds_and_ty) {
     encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
                               tag_items_data_item_ty_param_bounds);
-    encode_region_param_defs(ebml_w, ecx, tpt.generics.region_param_defs());
+    encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
     encode_type(ecx, ebml_w, tpt.ty);
 }
 
@@ -311,15 +304,14 @@ fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
     ebml_w.end_tag();
 }
 
-fn encode_struct_fields(ecx: &EncodeContext,
-                             ebml_w: &mut writer::Encoder,
-                             def: @StructDef) {
+fn encode_struct_fields(ebml_w: &mut writer::Encoder,
+                        def: @StructDef) {
     for f in def.fields.iter() {
         match f.node.kind {
             NamedField(ident, vis) => {
                ebml_w.start_tag(tag_item_field);
                encode_struct_field_family(ebml_w, vis);
-               encode_name(ecx, ebml_w, ident);
+               encode_name(ebml_w, ident);
                encode_def_id(ebml_w, local_def(f.node.id));
                ebml_w.end_tag();
             }
@@ -336,7 +328,6 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             ebml_w: &mut writer::Encoder,
                             id: NodeId,
                             variants: &[P<Variant>],
-                            path: &[ast_map::PathElem],
                             index: @RefCell<~[entry<i64>]>,
                             generics: &ast::Generics) {
     debug!("encode_enum_variant_info(id={:?})", id);
@@ -360,7 +351,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
             ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
             ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
         }
-        encode_name(ecx, ebml_w, variant.node.name);
+        encode_name(ebml_w, variant.node.name);
         encode_parent_item(ebml_w, local_def(id));
         encode_visibility(ebml_w, variant.node.vis);
         encode_attributes(ebml_w, variant.node.attrs);
@@ -371,9 +362,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
             }
             ast::TupleVariantKind(_) => {},
             ast::StructVariantKind(def) => {
-                let idx = encode_info_for_struct(ecx, ebml_w, path,
-                                         def.fields, index);
-                encode_struct_fields(ecx, ebml_w, def);
+                let idx = encode_info_for_struct(ecx, ebml_w, def.fields, index);
+                encode_struct_fields(ebml_w, def);
                 let bkts = create_index(idx);
                 encode_index(ebml_w, bkts, write_i64);
             }
@@ -384,60 +374,40 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         }
         encode_bounds_and_type(ebml_w, ecx,
                                &lookup_item_type(ecx.tcx, def_id));
-        encode_path(ecx, ebml_w, path,
-                    ast_map::PathName(variant.node.name));
+
+        ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
         ebml_w.end_tag();
         disr_val += 1;
         i += 1;
     }
 }
 
-fn encode_path(ecx: &EncodeContext,
-               ebml_w: &mut writer::Encoder,
-               path: &[ast_map::PathElem],
-               name: ast_map::PathElem) {
-    fn encode_path_elem(ecx: &EncodeContext,
-                       ebml_w: &mut writer::Encoder,
-                       elt: ast_map::PathElem) {
-        match elt {
-            ast_map::PathMod(n) => {
-                ebml_w.wr_tagged_str(tag_path_elem_mod, ecx.tcx.sess.str_of(n));
-            }
-            ast_map::PathName(n) => {
-                ebml_w.wr_tagged_str(tag_path_elem_name, ecx.tcx.sess.str_of(n));
-            }
-            ast_map::PathPrettyName(n, extra) => {
-                ebml_w.start_tag(tag_path_elem_pretty_name);
-                ebml_w.wr_tagged_str(tag_path_elem_pretty_name_ident,
-                                     ecx.tcx.sess.str_of(n));
-                ebml_w.wr_tagged_u64(tag_path_elem_pretty_name_extra, extra);
-                ebml_w.end_tag();
-            }
-        }
-    }
-
+fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut writer::Encoder,
+                                               mut path: PI) {
     ebml_w.start_tag(tag_path);
-    ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
-    for pe in path.iter() {
-        encode_path_elem(ecx, ebml_w, *pe);
+    ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
+    for pe in path {
+        let tag = match pe {
+            ast_map::PathMod(_) => tag_path_elem_mod,
+            ast_map::PathName(_) => tag_path_elem_name
+        };
+        ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
     }
-    encode_path_elem(ecx, ebml_w, name);
     ebml_w.end_tag();
 }
 
-fn encode_reexported_static_method(ecx: &EncodeContext,
-                                   ebml_w: &mut writer::Encoder,
+fn encode_reexported_static_method(ebml_w: &mut writer::Encoder,
                                    exp: &middle::resolve::Export2,
                                    method_def_id: DefId,
                                    method_ident: Ident) {
     debug!("(encode reexported static method) {}::{}",
-            exp.name, ecx.tcx.sess.str_of(method_ident));
+            exp.name, token::get_ident(method_ident));
     ebml_w.start_tag(tag_items_data_item_reexport);
     ebml_w.start_tag(tag_items_data_item_reexport_def_id);
     ebml_w.wr_str(def_to_str(method_def_id));
     ebml_w.end_tag();
     ebml_w.start_tag(tag_items_data_item_reexport_name);
-    ebml_w.wr_str(format!("{}::{}", exp.name, ecx.tcx.sess.str_of(method_ident)));
+    ebml_w.wr_str(format!("{}::{}", exp.name, token::get_ident(method_ident)));
     ebml_w.end_tag();
     ebml_w.end_tag();
 }
@@ -453,8 +423,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
             for &base_impl in implementations.get().iter() {
                 for &m in base_impl.methods.iter() {
                     if m.explicit_self == ast::SelfStatic {
-                        encode_reexported_static_method(ecx, ebml_w, exp,
-                                                        m.def_id, m.ident);
+                        encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
                     }
                 }
             }
@@ -474,8 +443,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
         Some(methods) => {
             for &m in methods.iter() {
                 if m.explicit_self == ast::SelfStatic {
-                    encode_reexported_static_method(ecx, ebml_w, exp,
-                                                    m.def_id, m.ident);
+                    encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
                 }
             }
 
@@ -487,11 +455,22 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
 
 fn encode_reexported_static_methods(ecx: &EncodeContext,
                                     ebml_w: &mut writer::Encoder,
-                                    mod_path: &[ast_map::PathElem],
+                                    mod_path: PathElems,
                                     exp: &middle::resolve::Export2) {
-    match ecx.tcx.items.find(exp.def_id.node) {
-        Some(ast_map::NodeItem(item, path)) => {
-            let original_name = token::get_ident(item.ident.name);
+    match ecx.tcx.map.find(exp.def_id.node) {
+        Some(ast_map::NodeItem(item)) => {
+            let original_name = token::get_ident(item.ident);
+
+            let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
+                let (mut a, mut b) = (path, mod_path.clone());
+                loop {
+                    match (a.next(), b.next()) {
+                        (None, None) => return true,
+                        (None, _) | (_, None) => return false,
+                        (Some(x), Some(y)) => if x != y { return false },
+                    }
+                }
+            });
 
             //
             // We don't need to reexport static methods on items
@@ -503,7 +482,7 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
             // encoded metadata for static methods relative to Bar,
             // but not yet for Foo.
             //
-            if mod_path != *path || original_name.get() != exp.name {
+            if path_differs || original_name.get() != exp.name {
                 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
                     if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
                         debug!("(encode reexported static methods) {} \
@@ -558,7 +537,7 @@ fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
 fn encode_reexports(ecx: &EncodeContext,
                     ebml_w: &mut writer::Encoder,
                     id: NodeId,
-                    path: &[ast_map::PathElem]) {
+                    path: PathElems) {
     debug!("(encoding info for module) encoding reexports for {}", id);
     let reexports2 = ecx.reexports2.borrow();
     match reexports2.get().find(&id) {
@@ -579,7 +558,7 @@ fn encode_reexports(ecx: &EncodeContext,
                 ebml_w.wr_str(exp.name);
                 ebml_w.end_tag();
                 ebml_w.end_tag();
-                encode_reexported_static_methods(ecx, ebml_w, path, exp);
+                encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
             }
         }
         None => {
@@ -593,13 +572,13 @@ fn encode_info_for_mod(ecx: &EncodeContext,
                        ebml_w: &mut writer::Encoder,
                        md: &Mod,
                        id: NodeId,
-                       path: &[ast_map::PathElem],
+                       path: PathElems,
                        name: Ident,
                        vis: Visibility) {
     ebml_w.start_tag(tag_items_data_item);
     encode_def_id(ebml_w, local_def(id));
     encode_family(ebml_w, 'm');
-    encode_name(ecx, ebml_w, name);
+    encode_name(ebml_w, name);
     debug!("(encoding info for module) encoding info for module ID {}", id);
 
     // Encode info about all the module children.
@@ -620,9 +599,8 @@ fn encode_info_for_mod(ecx: &EncodeContext,
                 let (ident, did) = (item.ident, item.id);
                 debug!("(encoding info for module) ... encoding impl {} \
                         ({:?}/{:?})",
-                        ecx.tcx.sess.str_of(ident),
-                        did,
-                        ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
+                        token::get_ident(ident),
+                        did, ecx.tcx.map.node_to_str(did));
 
                 ebml_w.start_tag(tag_mod_impl);
                 ebml_w.wr_str(def_to_str(local_def(did)));
@@ -632,7 +610,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
         }
     }
 
-    encode_path(ecx, ebml_w, path, ast_map::PathMod(name));
+    encode_path(ebml_w, path.clone());
     encode_visibility(ebml_w, vis);
 
     // Encode the reexports of this module, if this module is public.
@@ -709,7 +687,6 @@ fn encode_provided_source(ebml_w: &mut writer::Encoder,
 /* Returns an index of items in this class */
 fn encode_info_for_struct(ecx: &EncodeContext,
                           ebml_w: &mut writer::Encoder,
-                          path: &[ast_map::PathElem],
                           fields: &[StructField],
                           global_index: @RefCell<~[entry<i64>]>)
                           -> ~[entry<i64>] {
@@ -736,10 +713,9 @@ fn encode_info_for_struct(ecx: &EncodeContext,
         }
         ebml_w.start_tag(tag_items_data_item);
         debug!("encode_info_for_struct: doing {} {}",
-               tcx.sess.str_of(nm), id);
+               token::get_ident(nm), id);
         encode_struct_field_family(ebml_w, vis);
-        encode_name(ecx, ebml_w, nm);
-        encode_path(ecx, ebml_w, path, ast_map::PathName(nm));
+        encode_name(ebml_w, nm);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
         encode_def_id(ebml_w, local_def(id));
         ebml_w.end_tag();
@@ -749,7 +725,6 @@ fn encode_info_for_struct(ecx: &EncodeContext,
 
 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                ebml_w: &mut writer::Encoder,
-                               path: &[ast_map::PathElem],
                                name: ast::Ident,
                                ctor_id: NodeId,
                                index: @RefCell<~[entry<i64>]>,
@@ -767,9 +742,9 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
     encode_family(ebml_w, 'f');
     encode_bounds_and_type(ebml_w, ecx,
                            &lookup_item_type(ecx.tcx, local_def(ctor_id)));
-    encode_name(ecx, ebml_w, name);
+    encode_name(ebml_w, name);
     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
-    encode_path(ecx, ebml_w, path, ast_map::PathName(name));
+    ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
     encode_parent_item(ebml_w, local_def(struct_id));
 
     let item_symbols = ecx.item_symbols.borrow();
@@ -790,7 +765,7 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
                            ebml_w: &mut writer::Encoder,
                            method_ty: &ty::Method) {
     encode_def_id(ebml_w, method_ty.def_id);
-    encode_name(ecx, ebml_w, method_ty.ident);
+    encode_name(ebml_w, method_ty.ident);
     encode_ty_type_param_defs(ebml_w, ecx,
                               method_ty.generics.type_param_defs(),
                               tag_item_method_tps);
@@ -810,13 +785,13 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
 fn encode_info_for_method(ecx: &EncodeContext,
                           ebml_w: &mut writer::Encoder,
                           m: &ty::Method,
-                          impl_path: &[ast_map::PathElem],
+                          impl_path: PathElems,
                           is_default_impl: bool,
                           parent_id: NodeId,
                           ast_method_opt: Option<@Method>) {
 
     debug!("encode_info_for_method: {:?} {}", m.def_id,
-           ecx.tcx.sess.str_of(m.ident));
+           token::get_ident(m.ident));
     ebml_w.start_tag(tag_items_data_item);
 
     encode_method_ty_fields(ecx, ebml_w, m);
@@ -826,7 +801,8 @@ fn encode_info_for_method(ecx: &EncodeContext,
     let tpt = lookup_item_type(ecx.tcx, m.def_id);
     encode_bounds_and_type(ebml_w, ecx, &tpt);
 
-    encode_path(ecx, ebml_w, impl_path, ast_map::PathName(m.ident));
+    let elem = ast_map::PathName(m.ident.name);
+    encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
     match ast_method_opt {
         Some(ast_method) => encode_attributes(ebml_w, ast_method.attrs),
         None => ()
@@ -834,11 +810,9 @@ fn encode_info_for_method(ecx: &EncodeContext,
 
     for &ast_method in ast_method_opt.iter() {
         let num_params = tpt.generics.type_param_defs().len();
-        if num_params > 0u || is_default_impl
-            || should_inline(ast_method.attrs) {
+        if num_params > 0u || is_default_impl || should_inline(ast_method.attrs) {
             (ecx.encode_inlined_item)(
-                ecx, ebml_w, impl_path,
-                IIMethodRef(local_def(parent_id), false, ast_method));
+                ecx, ebml_w, IIMethodRef(local_def(parent_id), false, ast_method));
         } else {
             encode_symbol(ecx, ebml_w, m.def_id.node);
         }
@@ -912,7 +886,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                         ebml_w: &mut writer::Encoder,
                         item: &Item,
                         index: @RefCell<~[entry<i64>]>,
-                        path: &[ast_map::PathElem],
+                        path: PathElems,
                         vis: ast::Visibility) {
     let tcx = ecx.tcx;
 
@@ -941,18 +915,13 @@ fn encode_info_for_item(ecx: &EncodeContext,
         }
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
-        encode_name(ecx, ebml_w, item.ident);
-        let elt = ast_map::PathPrettyName(item.ident, item.id as u64);
-        encode_path(ecx, ebml_w, path, elt);
+        encode_name(ebml_w, item.ident);
+        encode_path(ebml_w, path);
 
-        let non_inlineable;
-        {
-            let non_inlineable_statics = ecx.non_inlineable_statics.borrow();
-            non_inlineable = non_inlineable_statics.get().contains(&item.id);
-        }
+        let inlineable = !ecx.non_inlineable_statics.borrow().get().contains(&item.id);
 
-        if !non_inlineable {
-            (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
+        if inlineable {
+            (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
         }
         encode_visibility(ebml_w, vis);
         ebml_w.end_tag();
@@ -964,11 +933,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_family(ebml_w, purity_fn_family(purity));
         let tps_len = generics.ty_params.len();
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
-        encode_name(ecx, ebml_w, item.ident);
-        encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
+        encode_name(ebml_w, item.ident);
+        encode_path(ebml_w, path);
         encode_attributes(ebml_w, item.attrs);
         if tps_len > 0u || should_inline(item.attrs) {
-            (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
+            (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
         } else {
             encode_symbol(ecx, ebml_w, item.id);
         }
@@ -990,8 +959,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'n');
-        encode_name(ecx, ebml_w, item.ident);
-        encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
+        encode_name(ebml_w, item.ident);
+        encode_path(ebml_w, path);
 
         // Encode all the items in this module.
         for foreign_item in fm.items.iter() {
@@ -1008,8 +977,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'y');
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
-        encode_name(ecx, ebml_w, item.ident);
-        encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
+        encode_name(ebml_w, item.ident);
+        encode_path(ebml_w, path);
         encode_visibility(ebml_w, vis);
         ebml_w.end_tag();
       }
@@ -1021,13 +990,13 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_family(ebml_w, 't');
         encode_item_variances(ebml_w, ecx, item.id);
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
-        encode_name(ecx, ebml_w, item.ident);
+        encode_name(ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         for v in (*enum_definition).variants.iter() {
             encode_variant_id(ebml_w, local_def(v.node.id));
         }
-        (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
-        encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
+        (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
+        encode_path(ebml_w, path);
 
         // Encode inherent implementations for this enumeration.
         encode_inherent_implementations(ecx, ebml_w, def_id);
@@ -1039,7 +1008,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                  ebml_w,
                                  item.id,
                                  (*enum_definition).variants,
-                                 path,
                                  index,
                                  generics);
       }
@@ -1048,7 +1016,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
            These come first because we need to write them to make
            the index, and the index needs to be in the item for the
            class itself */
-        let idx = encode_info_for_struct(ecx, ebml_w, path,
+        let idx = encode_info_for_struct(ecx, ebml_w,
                                          struct_def.fields, index);
 
         /* Index the class*/
@@ -1061,17 +1029,17 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
 
         encode_item_variances(ebml_w, ecx, item.id);
-        encode_name(ecx, ebml_w, item.ident);
+        encode_name(ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
-        encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
+        encode_path(ebml_w, path.clone());
         encode_visibility(ebml_w, vis);
 
         /* Encode def_ids for each field and method
          for methods, write all the stuff get_trait_method
         needs to know*/
-        encode_struct_fields(ecx, ebml_w, struct_def);
+        encode_struct_fields(ebml_w, struct_def);
 
-        (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
+        (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
 
         // Encode inherent implementations for this structure.
         encode_inherent_implementations(ecx, ebml_w, def_id);
@@ -1081,22 +1049,13 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_index(ebml_w, bkts, write_i64);
         ebml_w.end_tag();
 
-        // If this is a tuple- or enum-like struct, encode the type of the
-        // constructor.
-        if struct_def.fields.len() > 0 &&
-                struct_def.fields[0].node.kind == ast::UnnamedField {
-            let ctor_id = match struct_def.ctor_id {
-                Some(ctor_id) => ctor_id,
-                None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
-            };
-
-            encode_info_for_struct_ctor(ecx,
-                                        ebml_w,
-                                        path,
-                                        item.ident,
-                                        ctor_id,
-                                        index,
-                                        def_id.node);
+        // If this is a tuple-like struct, encode the type of the constructor.
+        match struct_def.ctor_id {
+            Some(ctor_id) => {
+                encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
+                                            ctor_id, index, def_id.node);
+            }
+            None => {}
         }
       }
       ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
@@ -1110,14 +1069,13 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'i');
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
-        encode_name(ecx, ebml_w, item.ident);
+        encode_name(ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         match ty.node {
             ast::TyPath(ref path, ref bounds, _) if path.segments
                                                         .len() == 1 => {
                 assert!(bounds.is_none());
-                encode_impl_type_basename(ecx, ebml_w,
-                                          ast_util::path_to_ident(path));
+                encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
             }
             _ => {}
         }
@@ -1134,14 +1092,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
         }
-        let elt = ast_map::impl_pretty_name(opt_trait, ty);
-        encode_path(ecx, ebml_w, path, elt);
+        encode_path(ebml_w, path.clone());
         ebml_w.end_tag();
 
-        // >:-<
-        let mut impl_path = vec::append(~[], path);
-        impl_path.push(elt);
-
         // Iterate down the methods, emitting them. We rely on the
         // assumption that all of the actually implemented methods
         // appear first in the impl structure, in the same order they do
@@ -1162,7 +1115,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             encode_info_for_method(ecx,
                                    ebml_w,
                                    *m,
-                                   impl_path,
+                                   path.clone(),
                                    false,
                                    item.id,
                                    ast_method)
@@ -1178,10 +1131,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_ty_type_param_defs(ebml_w, ecx,
                                   trait_def.generics.type_param_defs(),
                                   tag_items_data_item_ty_param_bounds);
-        encode_region_param_defs(ebml_w, ecx,
-                                 trait_def.generics.region_param_defs());
+        encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
         encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
-        encode_name(ecx, ebml_w, item.ident);
+        encode_name(ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         encode_visibility(ebml_w, vis);
         for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
@@ -1193,7 +1145,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             ebml_w.wr_str(def_to_str(method_def_id));
             ebml_w.end_tag();
         }
-        encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
+        encode_path(ebml_w, path.clone());
         // FIXME(#8559): This should use the tcx's supertrait cache instead of
         // reading the AST's list, because the former has already filtered out
         // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
@@ -1228,9 +1180,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
             encode_parent_item(ebml_w, def_id);
 
-            let mut trait_path = vec::append(~[], path);
-            trait_path.push(ast_map::PathName(item.ident));
-            encode_path(ecx, ebml_w, trait_path, ast_map::PathName(method_ty.ident));
+            let elem = ast_map::PathName(method_ty.ident.name);
+            encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
 
             match method_ty.explicit_self {
                 SelfStatic => {
@@ -1266,8 +1217,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                     }
                     encode_method_sort(ebml_w, 'p');
                     (ecx.encode_inlined_item)(
-                        ecx, ebml_w, path,
-                        IIMethodRef(def_id, true, m));
+                        ecx, ebml_w, IIMethodRef(def_id, true, m));
                 }
             }
 
@@ -1287,7 +1237,7 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 ebml_w: &mut writer::Encoder,
                                 nitem: &ForeignItem,
                                 index: @RefCell<~[entry<i64>]>,
-                                path: &ast_map::Path,
+                                path: PathElems,
                                 abi: AbiSet) {
     {
         let mut index = index.borrow_mut();
@@ -1298,22 +1248,20 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
     }
 
     ebml_w.start_tag(tag_items_data_item);
+    encode_def_id(ebml_w, local_def(nitem.id));
     match nitem.node {
       ForeignItemFn(..) => {
-        encode_def_id(ebml_w, local_def(nitem.id));
         encode_family(ebml_w, purity_fn_family(ImpureFn));
         encode_bounds_and_type(ebml_w, ecx,
                                &lookup_item_type(ecx.tcx,local_def(nitem.id)));
-        encode_name(ecx, ebml_w, nitem.ident);
+        encode_name(ebml_w, nitem.ident);
         if abi.is_intrinsic() {
-            (ecx.encode_inlined_item)(ecx, ebml_w, *path, IIForeignRef(nitem));
+            (ecx.encode_inlined_item)(ecx, ebml_w, IIForeignRef(nitem));
         } else {
             encode_symbol(ecx, ebml_w, nitem.id);
         }
-        encode_path(ecx, ebml_w, *path, ast_map::PathName(nitem.ident));
       }
       ForeignItemStatic(_, mutbl) => {
-        encode_def_id(ebml_w, local_def(nitem.id));
         if mutbl {
             encode_family(ebml_w, 'b');
         } else {
@@ -1321,66 +1269,51 @@ fn encode_info_for_foreign_item(ecx: &EncodeContext,
         }
         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
         encode_symbol(ecx, ebml_w, nitem.id);
-        encode_name(ecx, ebml_w, nitem.ident);
-        encode_path(ecx, ebml_w, *path, ast_map::PathName(nitem.ident));
+        encode_name(ebml_w, nitem.ident);
       }
     }
+    encode_path(ebml_w, path);
     ebml_w.end_tag();
 }
 
 fn my_visit_expr(_e: &Expr) { }
 
 fn my_visit_item(i: &Item,
-                 items: ast_map::Map,
                  ebml_w: &mut writer::Encoder,
                  ecx_ptr: *int,
                  index: @RefCell<~[entry<i64>]>) {
-    match items.get(i.id) {
-        ast_map::NodeItem(_, pt) => {
-            let mut ebml_w = unsafe {
-                ebml_w.unsafe_clone()
-            };
-            // See above
-            let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
-            encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
-        }
-        _ => fail!("bad item")
-    }
+    let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
+    // See above
+    let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
+    ecx.tcx.map.with_path(i.id, |path| {
+        encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
+    });
 }
 
 fn my_visit_foreign_item(ni: &ForeignItem,
-                         items: ast_map::Map,
                          ebml_w: &mut writer::Encoder,
                          ecx_ptr:*int,
                          index: @RefCell<~[entry<i64>]>) {
-    match items.get(ni.id) {
-        ast_map::NodeForeignItem(_, abi, _, pt) => {
-            let string = token::get_ident(ni.ident.name);
-            debug!("writing foreign item {}::{}",
-                   ast_map::path_to_str(*pt, token::get_ident_interner()),
-                   string.get());
-
-            let mut ebml_w = unsafe {
-                ebml_w.unsafe_clone()
-            };
-            // See above
-            let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
-            encode_info_for_foreign_item(ecx,
-                                         &mut ebml_w,
-                                         ni,
-                                         index,
-                                         pt,
-                                         abi);
-        }
-        // case for separate item and foreign-item tables
-        _ => fail!("bad foreign item")
-    }
+    // See above
+    let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
+    debug!("writing foreign item {}::{}",
+            ecx.tcx.map.path_to_str(ni.id),
+            token::get_ident(ni.ident));
+
+    let mut ebml_w = unsafe {
+        ebml_w.unsafe_clone()
+    };
+    let abis = ecx.tcx.map.get_foreign_abis(ni.id);
+    ecx.tcx.map.with_path(ni.id, |path| {
+        encode_info_for_foreign_item(ecx, &mut ebml_w,
+                                     ni, index,
+                                     path, abis);
+    });
 }
 
 struct EncodeVisitor<'a,'b> {
     ebml_w_for_visit_item: &'a mut writer::Encoder<'b>,
     ecx_ptr:*int,
-    items: ast_map::Map,
     index: @RefCell<~[entry<i64>]>,
 }
 
@@ -1392,7 +1325,6 @@ impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
     fn visit_item(&mut self, i: &Item, _: ()) {
         visit::walk_item(self, i, ());
         my_visit_item(i,
-                      self.items,
                       self.ebml_w_for_visit_item,
                       self.ecx_ptr,
                       self.index);
@@ -1400,7 +1332,6 @@ impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
     fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
         visit::walk_foreign_item(self, ni, ());
         my_visit_foreign_item(ni,
-                              self.items,
                               self.ebml_w_for_visit_item,
                               self.ecx_ptr,
                               self.index);
@@ -1424,17 +1355,15 @@ fn encode_info_for_items(ecx: &EncodeContext,
                         ebml_w,
                         &krate.module,
                         CRATE_NODE_ID,
-                        [],
+                        ast_map::Values([].iter()).chain(None),
                         syntax::parse::token::special_idents::invalid,
                         Public);
-    let items = ecx.tcx.items;
 
     // See comment in `encode_side_tables_for_ii` in astencode
-    let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
+    let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
     {
         let mut visitor = EncodeVisitor {
             index: index,
-            items: items,
             ecx_ptr: ecx_ptr,
             ebml_w_for_visit_item: &mut *ebml_w,
         };
@@ -1581,20 +1510,17 @@ fn synthesize_crate_attrs(ecx: &EncodeContext,
     attrs
 }
 
-fn encode_crate_deps(ecx: &EncodeContext,
-                     ebml_w: &mut writer::Encoder,
-                     cstore: &cstore::CStore) {
-    fn get_ordered_deps(ecx: &EncodeContext, cstore: &cstore::CStore)
-                     -> ~[decoder::CrateDep] {
-        type numdep = decoder::CrateDep;
-
+fn encode_crate_deps(ebml_w: &mut writer::Encoder, cstore: &cstore::CStore) {
+    fn get_ordered_deps(cstore: &cstore::CStore) -> ~[decoder::CrateDep] {
         // Pull the cnums and name,vers,hash out of cstore
         let mut deps = ~[];
         cstore.iter_crate_data(|key, val| {
-            let dep = decoder::CrateDep {cnum: key,
-                       name: ecx.tcx.sess.ident_of(val.name),
-                       vers: decoder::get_crate_vers(val.data()),
-                       hash: decoder::get_crate_hash(val.data())};
+            let dep = decoder::CrateDep {
+                cnum: key,
+                name: token::str_to_ident(val.name),
+                vers: decoder::get_crate_vers(val.data()),
+                hash: decoder::get_crate_hash(val.data())
+            };
             deps.push(dep);
         });
 
@@ -1616,9 +1542,9 @@ fn encode_crate_deps(ecx: &EncodeContext,
     // FIXME (#2166): This is not nearly enough to support correct versioning
     // but is enough to get transitive crate dependencies working.
     ebml_w.start_tag(tag_crate_deps);
-    let r = get_ordered_deps(ecx, cstore);
+    let r = get_ordered_deps(cstore);
     for dep in r.iter() {
-        encode_crate_dep(ecx, ebml_w, (*dep).clone());
+        encode_crate_dep(ebml_w, (*dep).clone());
     }
     ebml_w.end_tag();
 }
@@ -1801,19 +1727,18 @@ fn encode_misc_info(ecx: &EncodeContext,
     }
 
     // Encode reexports for the root module.
-    encode_reexports(ecx, ebml_w, 0, []);
+    encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
 
     ebml_w.end_tag();
     ebml_w.end_tag();
 }
 
-fn encode_crate_dep(ecx: &EncodeContext,
-                    ebml_w: &mut writer::Encoder,
+fn encode_crate_dep(ebml_w: &mut writer::Encoder,
                     dep: decoder::CrateDep) {
     ebml_w.start_tag(tag_crate_dep);
     ebml_w.start_tag(tag_crate_dep_name);
-    let s = ecx.tcx.sess.str_of(dep.name);
-    ebml_w.writer.write(s.as_bytes());
+    let s = token::get_ident(dep.name);
+    ebml_w.writer.write(s.get().as_bytes());
     ebml_w.end_tag();
     ebml_w.start_tag(tag_crate_dep_vers);
     ebml_w.writer.write(dep.vers.as_bytes());
@@ -1900,7 +1825,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
     ecx.stats.attr_bytes.set(ebml_w.writer.tell().unwrap() - i);
 
     i = ebml_w.writer.tell().unwrap();
-    encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
+    encode_crate_deps(&mut ebml_w, ecx.cstore);
     ecx.stats.dep_bytes.set(ebml_w.writer.tell().unwrap() - i);
 
     // Encode the language items.