about summary refs log tree commit diff
path: root/src/rustc/metadata
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-07-18 16:18:02 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2012-08-22 14:59:25 -0700
commit1153b5dcc86c3567b0a86e441938f05d4f2e295b (patch)
treefdcbcea39abecb4ad1ea5145e62e8c013b05e930 /src/rustc/metadata
parent7317bf8792ebb3f27768109b7d574ee0806cc5e5 (diff)
downloadrust-1153b5dcc86c3567b0a86e441938f05d4f2e295b.tar.gz
rust-1153b5dcc86c3567b0a86e441938f05d4f2e295b.zip
intern identifiers
Diffstat (limited to 'src/rustc/metadata')
-rw-r--r--src/rustc/metadata/common.rs2
-rw-r--r--src/rustc/metadata/creader.rs79
-rw-r--r--src/rustc/metadata/csearch.rs24
-rw-r--r--src/rustc/metadata/cstore.rs44
-rw-r--r--src/rustc/metadata/decoder.rs145
-rw-r--r--src/rustc/metadata/encoder.rs170
-rw-r--r--src/rustc/metadata/loader.rs34
-rw-r--r--src/rustc/metadata/tydecode.rs6
-rw-r--r--src/rustc/metadata/tyencode.rs12
9 files changed, 269 insertions, 247 deletions
diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs
index 7746f18e167..15e15a8a54c 100644
--- a/src/rustc/metadata/common.rs
+++ b/src/rustc/metadata/common.rs
@@ -134,5 +134,5 @@ fn hash_path(&&s: ~str) -> uint {
     return h;
 }
 
-type link_meta = {name: @~str, vers: @~str, extras_hash: ~str};
+type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
 
diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs
index 744ee50da8b..2a3b59bf349 100644
--- a/src/rustc/metadata/creader.rs
+++ b/src/rustc/metadata/creader.rs
@@ -10,6 +10,7 @@ import syntax::print::pprust;
 import filesearch::filesearch;
 import common::*;
 import dvec::{DVec, dvec};
+import syntax::parse::token::ident_interner;
 
 export read_crates;
 
@@ -17,28 +18,29 @@ export read_crates;
 // libraries necessary for later resolving, typechecking, linking, etc.
 fn read_crates(diag: span_handler, crate: ast::crate,
                cstore: cstore::cstore, filesearch: filesearch,
-               os: loader::os, static: bool) {
+               os: loader::os, static: bool, intr: ident_interner) {
     let e = @{diag: diag,
               filesearch: filesearch,
               cstore: cstore,
               os: os,
               static: static,
               crate_cache: dvec(),
-              mut next_crate_num: 1};
+              mut next_crate_num: 1,
+              intr: intr};
     let v =
         visit::mk_simple_visitor(@{visit_view_item:
                                        |a| visit_view_item(e, a),
                                    visit_item: |a| visit_item(e, a)
-                                      with *visit::default_simple_visitor()});
+                                   with *visit::default_simple_visitor()});
     visit::visit_crate(crate, (), v);
     dump_crates(e.crate_cache);
-    warn_if_multiple_versions(diag, e.crate_cache.get());
+    warn_if_multiple_versions(e, diag, e.crate_cache.get());
 }
 
 type cache_entry = {
     cnum: int,
     span: span,
-    hash: @~str,
+    hash: ~str,
     metas: @~[@ast::meta_item]
 };
 
@@ -48,16 +50,10 @@ fn dump_crates(crate_cache: DVec<cache_entry>) {
         debug!{"cnum: %?", entry.cnum};
         debug!{"span: %?", entry.span};
         debug!{"hash: %?", entry.hash};
-        let attrs = ~[
-            attr::mk_attr(attr::mk_list_item(@~"link", *entry.metas))
-        ];
-        for attr::find_linkage_attrs(attrs).each |attr| {
-            debug!{"meta: %s", pprust::attr_to_str(attr)};
-        }
     }
 }
 
-fn warn_if_multiple_versions(diag: span_handler,
+fn warn_if_multiple_versions(e: env, diag: span_handler,
                              crate_cache: ~[cache_entry]) {
     import either::*;
 
@@ -77,17 +73,17 @@ fn warn_if_multiple_versions(diag: span_handler,
 
         if matches.len() != 1u {
             diag.handler().warn(
-                fmt!{"using multiple versions of crate `%s`", *name});
+                fmt!{"using multiple versions of crate `%s`", name});
             for matches.each |match_| {
                 diag.span_note(match_.span, ~"used here");
                 let attrs = ~[
-                    attr::mk_attr(attr::mk_list_item(@~"link", *match_.metas))
+                    attr::mk_attr(attr::mk_list_item(~"link", *match_.metas))
                 ];
-                loader::note_linkage_attrs(diag, attrs);
+                loader::note_linkage_attrs(e.intr, diag, attrs);
             }
         }
 
-        warn_if_multiple_versions(diag, non_matches);
+        warn_if_multiple_versions(e, diag, non_matches);
     }
 }
 
@@ -97,7 +93,8 @@ type env = @{diag: span_handler,
              os: loader::os,
              static: bool,
              crate_cache: DVec<cache_entry>,
-             mut next_crate_num: ast::crate_num};
+             mut next_crate_num: ast::crate_num,
+             intr: ident_interner};
 
 fn visit_view_item(e: env, i: @ast::view_item) {
     match i.node {
@@ -125,28 +122,28 @@ fn visit_item(e: env, i: @ast::item) {
         let foreign_name =
             match attr::first_attr_value_str_by_name(i.attrs, ~"link_name") {
               some(nn) => {
-                if *nn == ~"" {
+                if nn == ~"" {
                     e.diag.span_fatal(
                         i.span,
                         ~"empty #[link_name] not allowed; use #[nolink].");
                 }
                 nn
               }
-              none => i.ident
+              none => *e.intr.get(i.ident)
             };
         let mut already_added = false;
         if vec::len(attr::find_attrs_by_name(i.attrs, ~"nolink")) == 0u {
-            already_added = !cstore::add_used_library(cstore, *foreign_name);
+            already_added = !cstore::add_used_library(cstore, foreign_name);
         }
         let link_args = attr::find_attrs_by_name(i.attrs, ~"link_args");
         if vec::len(link_args) > 0u && already_added {
-            e.diag.span_fatal(i.span, ~"library '" + *foreign_name +
+            e.diag.span_fatal(i.span, ~"library '" + foreign_name +
                               ~"' already added: can't specify link_args.");
         }
         for link_args.each |a| {
             match attr::get_meta_item_value_str(attr::attr_meta(a)) {
               some(linkarg) => {
-                cstore::add_used_link_args(cstore, *linkarg);
+                cstore::add_used_link_args(cstore, linkarg);
               }
               none => {/* fallthrough */ }
             }
@@ -156,19 +153,19 @@ fn visit_item(e: env, i: @ast::item) {
     }
 }
 
-fn metas_with(ident: ast::ident, key: ast::ident,
-                    metas: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
-    let name_items = attr::find_meta_items_by_name(metas, *key);
+fn metas_with(ident: ~str, key: ~str, metas: ~[@ast::meta_item])
+    -> ~[@ast::meta_item] {
+    let name_items = attr::find_meta_items_by_name(metas, key);
     if name_items.is_empty() {
-        vec::append_one(metas, attr::mk_name_value_item_str(key, *ident))
+        vec::append_one(metas, attr::mk_name_value_item_str(key, ident))
     } else {
         metas
     }
 }
 
-fn metas_with_ident(ident: ast::ident,
-                    metas: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
-    metas_with(ident, @~"name", metas)
+fn metas_with_ident(ident: ~str, metas: ~[@ast::meta_item])
+    -> ~[@ast::meta_item] {
+    metas_with(ident, ~"name", metas)
 }
 
 fn existing_match(e: env, metas: ~[@ast::meta_item], hash: ~str) ->
@@ -176,7 +173,7 @@ fn existing_match(e: env, metas: ~[@ast::meta_item], hash: ~str) ->
 
     for e.crate_cache.each |c| {
         if loader::metadata_matches(*c.metas, metas)
-            && (hash.is_empty() || *c.hash == hash) {
+            && (hash.is_empty() || c.hash == hash) {
             return some(c.cnum);
         }
     }
@@ -185,7 +182,7 @@ fn existing_match(e: env, metas: ~[@ast::meta_item], hash: ~str) ->
 
 fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
                  hash: ~str, span: span) -> ast::crate_num {
-    let metas = metas_with_ident(ident, metas);
+    let metas = metas_with_ident(*e.intr.get(ident), metas);
 
     match existing_match(e, metas, hash) {
       none => {
@@ -197,7 +194,8 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
             metas: metas,
             hash: hash,
             os: e.os,
-            static: e.static
+            static: e.static,
+            intr: e.intr
         };
         let cinfo = loader::load_library_crate(load_ctxt);
 
@@ -220,9 +218,9 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
         let cname =
             match attr::last_meta_item_value_str_by_name(metas, ~"name") {
               option::some(v) => v,
-              option::none => ident
+              option::none => *e.intr.get(ident)
             };
-        let cmeta = @{name: *cname, data: cdata,
+        let cmeta = @{name: cname, data: cdata,
                       cnum_map: cnum_map, cnum: cnum};
 
         let cstore = e.cstore;
@@ -242,13 +240,14 @@ fn resolve_crate_deps(e: env, cdata: @~[u8]) -> cstore::cnum_map {
     // The map from crate numbers in the crate we're resolving to local crate
     // numbers
     let cnum_map = int_hash::<ast::crate_num>();
-    for decoder::get_crate_deps(cdata).each |dep| {
+    for decoder::get_crate_deps(e.intr, cdata).each |dep| {
         let extrn_cnum = dep.cnum;
         let cname = dep.name;
-        let cmetas = metas_with(dep.vers, @~"vers", ~[]);
+        let cmetas = metas_with(dep.vers, ~"vers", ~[]);
         debug!{"resolving dep crate %s ver: %s hash: %s",
-               *dep.name, *dep.vers, *dep.hash};
-        match existing_match(e, metas_with_ident(cname, cmetas), *dep.hash) {
+               *e.intr.get(dep.name), dep.vers, dep.hash};
+        match existing_match(e, metas_with_ident(*e.intr.get(cname), cmetas),
+                             dep.hash) {
           some(local_cnum) => {
             debug!{"already have it"};
             // We've already seen this crate
@@ -260,8 +259,8 @@ fn resolve_crate_deps(e: env, cdata: @~[u8]) -> cstore::cnum_map {
             // FIXME (#2404): Need better error reporting than just a bogus
             // span.
             let fake_span = ast_util::dummy_sp();
-            let local_cnum =
-                resolve_crate(e, cname, cmetas, *dep.hash, fake_span);
+            let local_cnum = resolve_crate(e, cname, cmetas, dep.hash,
+                                           fake_span);
             cnum_map.insert(extrn_cnum, local_cnum);
           }
         }
diff --git a/src/rustc/metadata/csearch.rs b/src/rustc/metadata/csearch.rs
index 0dd3aaa82a5..388e746cb03 100644
--- a/src/rustc/metadata/csearch.rs
+++ b/src/rustc/metadata/csearch.rs
@@ -54,17 +54,17 @@ fn lookup_method_purity(cstore: cstore::cstore, did: ast::def_id)
 fn each_path(cstore: cstore::cstore, cnum: ast::crate_num,
              f: fn(decoder::path_entry) -> bool) {
     let crate_data = cstore::get_crate_data(cstore, cnum);
-    decoder::each_path(crate_data, f);
+    decoder::each_path(cstore.intr, crate_data, f);
 }
 
 fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    let path = decoder::get_item_path(cdata, def.node);
+    let path = decoder::get_item_path(cstore.intr, cdata, def.node);
 
     // FIXME #1920: This path is not always correct if the crate is not linked
     // into the root namespace.
-    vec::append(~[ast_map::path_mod(@cdata.name)], path)
+    vec::append(~[ast_map::path_mod(tcx.sess.ident_of(cdata.name))], path)
 }
 
 enum found_ast {
@@ -81,7 +81,7 @@ fn maybe_get_item_ast(tcx: ty::ctxt, def: ast::def_id,
     -> found_ast {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::maybe_get_item_ast(cdata, tcx, def.node,
+    decoder::maybe_get_item_ast(cstore.intr, cdata, tcx, def.node,
                                 decode_inlined_item)
 }
 
@@ -89,14 +89,14 @@ fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id)
     -> ~[ty::variant_info] {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    return decoder::get_enum_variants(cdata, def.node, tcx)
+    return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx)
 }
 
 fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id,
                      name: option<ast::ident>)
     -> @~[@decoder::_impl] {
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    do decoder::get_impls_for_mod(cdata, def.node, name) |cnum| {
+    do decoder::get_impls_for_mod(cstore.intr, cdata, def.node, name) |cnum| {
         cstore::get_crate_data(cstore, cnum)
     }
 }
@@ -104,14 +104,14 @@ fn get_impls_for_mod(cstore: cstore::cstore, def: ast::def_id,
 fn get_trait_methods(tcx: ty::ctxt, def: ast::def_id) -> @~[ty::method] {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_trait_methods(cdata, def.node, tcx)
+    decoder::get_trait_methods(cstore.intr, cdata, def.node, tcx)
 }
 
 fn get_method_names_if_trait(cstore: cstore::cstore, def: ast::def_id)
-    -> option<@DVec<(@~str, ast::self_ty_)>> {
+    -> option<@DVec<(ast::ident, ast::self_ty_)>> {
 
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    return decoder::get_method_names_if_trait(cdata, def.node);
+    return decoder::get_method_names_if_trait(cstore.intr, cdata, def.node);
 }
 
 fn get_item_attrs(cstore: cstore::cstore,
@@ -125,7 +125,7 @@ fn get_item_attrs(cstore: cstore::cstore,
 fn get_class_fields(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::field_ty] {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_class_fields(cdata, def.node)
+    decoder::get_class_fields(cstore.intr, cdata, def.node)
 }
 
 fn get_type(tcx: ty::ctxt, def: ast::def_id) -> ty::ty_param_bounds_and_ty {
@@ -173,7 +173,7 @@ fn get_impl_method(cstore: cstore::cstore,
                    def: ast::def_id, mname: ast::ident)
     -> ast::def_id {
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_impl_method(cdata, def.node, mname)
+    decoder::get_impl_method(cstore.intr, cdata, def.node, mname)
 }
 
 /* Because classes use the trait format rather than the impl format
@@ -184,7 +184,7 @@ fn get_class_method(cstore: cstore::cstore,
                     def: ast::def_id, mname: ast::ident)
     -> ast::def_id {
     let cdata = cstore::get_crate_data(cstore, def.crate);
-    decoder::get_class_method(cdata, def.node, mname)
+    decoder::get_class_method(cstore.intr, cdata, def.node, mname)
 }
 
 /* If def names a class with a dtor, return it. Otherwise, return none. */
diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs
index 0041093cee3..56ea0f028f6 100644
--- a/src/rustc/metadata/cstore.rs
+++ b/src/rustc/metadata/cstore.rs
@@ -5,6 +5,7 @@ import std::map;
 import std::map::hashmap;
 import syntax::{ast, attr};
 import syntax::ast_util::new_def_hash;
+import syntax::parse::token::ident_interner;
 
 export cstore;
 export cnum_map;
@@ -57,7 +58,8 @@ type cstore_private =
       mod_path_map: mod_path_map,
       mut used_crate_files: ~[~str],
       mut used_libraries: ~[~str],
-      mut used_link_args: ~[~str]};
+      mut used_link_args: ~[~str],
+      intr: ident_interner};
 
 // Map from node_id's of local use statements to crate numbers
 type use_crate_map = map::hashmap<ast::node_id, ast::crate_num>;
@@ -67,28 +69,29 @@ pure fn p(cstore: cstore) -> cstore_private {
     match cstore { private(p) => p }
 }
 
-fn mk_cstore() -> cstore {
+fn mk_cstore(intr: ident_interner) -> cstore {
     let meta_cache = map::int_hash::<crate_metadata>();
     let crate_map = map::int_hash::<ast::crate_num>();
     let mod_path_map = new_def_hash();
     return private(@{metas: meta_cache,
-                  use_crate_map: crate_map,
-                  mod_path_map: mod_path_map,
-                  mut used_crate_files: ~[],
-                  mut used_libraries: ~[],
-                  mut used_link_args: ~[]});
+                     use_crate_map: crate_map,
+                     mod_path_map: mod_path_map,
+                     mut used_crate_files: ~[],
+                     mut used_libraries: ~[],
+                     mut used_link_args: ~[],
+                     intr: intr});
 }
 
 fn get_crate_data(cstore: cstore, cnum: ast::crate_num) -> crate_metadata {
     return p(cstore).metas.get(cnum);
 }
 
-fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> @~str {
+fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> ~str {
     let cdata = get_crate_data(cstore, cnum);
     return decoder::get_crate_hash(cdata.data);
 }
 
-fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> @~str {
+fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> ~str {
     let cdata = get_crate_data(cstore, cnum);
     return decoder::get_crate_vers(cdata.data);
 }
@@ -96,7 +99,7 @@ fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> @~str {
 fn set_crate_data(cstore: cstore, cnum: ast::crate_num,
                   data: crate_metadata) {
     p(cstore).metas.insert(cnum, data);
-    do vec::iter(decoder::get_crate_module_paths(data)) |dp| {
+    do vec::iter(decoder::get_crate_module_paths(cstore.intr, data)) |dp| {
         let (did, path) = dp;
         let d = {crate: cnum, node: did.node};
         p(cstore).mod_path_map.insert(d, @path);
@@ -153,32 +156,29 @@ fn find_use_stmt_cnum(cstore: cstore,
 
 // returns hashes of crates directly used by this crate. Hashes are
 // sorted by crate name.
-fn get_dep_hashes(cstore: cstore) -> ~[@~str] {
-    type crate_hash = {name: @~str, hash: @~str};
+fn get_dep_hashes(cstore: cstore) -> ~[~str] {
+    type crate_hash = {name: ~str, hash: ~str};
     let mut result = ~[];
 
     for p(cstore).use_crate_map.each_value |cnum| {
         let cdata = cstore::get_crate_data(cstore, cnum);
         let hash = decoder::get_crate_hash(cdata.data);
-        debug!{"Add hash[%s]: %s", cdata.name, *hash};
-        vec::push(result, {name: @cdata.name, hash: hash});
+        debug!{"Add hash[%s]: %s", cdata.name, hash};
+        vec::push(result, {name: cdata.name, hash: hash});
     };
-    pure fn lteq(a: &crate_hash, b: &crate_hash) -> bool {
-        *a.name <= *b.name
-    }
+    pure fn lteq(a: &crate_hash, b: &crate_hash) -> bool {a.name <= b.name}
     let sorted = std::sort::merge_sort(lteq, result);
     debug!{"sorted:"};
     for sorted.each |x| {
-        debug!{"  hash[%s]: %s", *x.name, *x.hash};
+        debug!{"  hash[%s]: %s", x.name, x.hash};
     }
-    fn mapper(ch: crate_hash) -> @~str { return ch.hash; }
+    fn mapper(ch: crate_hash) -> ~str { return ch.hash; }
     return vec::map(sorted, mapper);
 }
 
-fn get_path(cstore: cstore, d: ast::def_id) -> ~[ast::ident] {
-    // let f = bind str::split_str(_, "::");
+fn get_path(cstore: cstore, d: ast::def_id) -> ~[~str] {
     option::map_default(p(cstore).mod_path_map.find(d), ~[],
-                        |ds| str::split_str(*ds, ~"::").map(|x| @x ) )
+                        |ds| str::split_str(*ds, ~"::"))
 }
 // Local Variables:
 // mode: rust
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index ea5405cc510..d9bec9fc5b2 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -15,6 +15,8 @@ import cmd=cstore::crate_metadata;
 import util::ppaux::ty_to_str;
 import syntax::diagnostic::span_handler;
 import common::*;
+import syntax::parse::token::ident_interner;
+
 
 export class_dtor;
 export get_class_fields;
@@ -212,7 +214,7 @@ fn enum_variant_ids(item: ebml::doc, cdata: cmd) -> ~[ast::def_id] {
     return ids;
 }
 
-fn item_path(item_doc: ebml::doc) -> ast_map::path {
+fn item_path(intr: ident_interner, item_doc: ebml::doc) -> ast_map::path {
     let path_doc = ebml::get_doc(item_doc, tag_path);
 
     let len_doc = ebml::get_doc(path_doc, tag_path_len);
@@ -224,10 +226,10 @@ fn item_path(item_doc: ebml::doc) -> ast_map::path {
     for ebml::docs(path_doc) |tag, elt_doc| {
         if tag == tag_path_elt_mod {
             let str = ebml::doc_as_str(elt_doc);
-            vec::push(result, ast_map::path_mod(@str));
+            vec::push(result, ast_map::path_mod(intr.intern(@str)));
         } else if tag == tag_path_elt_name {
             let str = ebml::doc_as_str(elt_doc);
-            vec::push(result, ast_map::path_name(@str));
+            vec::push(result, ast_map::path_name(intr.intern(@str)));
         } else {
             // ignore tag_path_len element
         }
@@ -236,9 +238,9 @@ fn item_path(item_doc: ebml::doc) -> ast_map::path {
     return result;
 }
 
-fn item_name(item: ebml::doc) -> ast::ident {
+fn item_name(intr: ident_interner, item: ebml::doc) -> ast::ident {
     let name = ebml::get_doc(item, tag_paths_data_name);
-    @str::from_bytes(ebml::doc_data(name))
+    intr.intern(@str::from_bytes(ebml::doc_data(name)))
 }
 
 fn item_to_def_like(item: ebml::doc, did: ast::def_id, cnum: ast::crate_num)
@@ -304,37 +306,38 @@ fn get_impl_traits(cdata: cmd, id: ast::node_id, tcx: ty::ctxt) -> ~[ty::t] {
     item_impl_traits(lookup_item(id, cdata.data), tcx, cdata)
 }
 
-fn get_impl_method(cdata: cmd, id: ast::node_id,
+fn get_impl_method(intr: ident_interner, cdata: cmd, id: ast::node_id,
                    name: ast::ident) -> ast::def_id {
     let items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
     let mut found = none;
     for ebml::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| {
         let m_did = ebml::with_doc_data(mid, |d| parse_def_id(d));
-        if item_name(find_item(m_did.node, items)) == name {
+        if item_name(intr, find_item(m_did.node, items)) == name {
             found = some(translate_def_id(cdata, m_did));
         }
     }
     option::get(found)
 }
 
-fn get_class_method(cdata: cmd, id: ast::node_id,
+fn get_class_method(intr: ident_interner, cdata: cmd, id: ast::node_id,
                     name: ast::ident) -> ast::def_id {
     let items = ebml::get_doc(ebml::doc(cdata.data), tag_items);
     let mut found = none;
     let cls_items = match maybe_find_item(id, items) {
       some(it) => it,
       none => fail (fmt!{"get_class_method: class id not found \
-                              when looking up method %s", *name})
+                              when looking up method %s", *intr.get(name)})
     };
     for ebml::tagged_docs(cls_items, tag_item_trait_method) |mid| {
         let m_did = item_def_id(mid, cdata);
-        if item_name(mid) == name {
+        if item_name(intr, mid) == name {
             found = some(m_did);
         }
     }
     match found {
       some(found) => found,
-      none => fail (fmt!{"get_class_method: no method named %s", *name})
+      none => fail (fmt!{"get_class_method: no method named %s",
+                         *intr.get(name)})
     }
 }
 
@@ -387,7 +390,7 @@ struct path_entry {
 }
 
 /// Iterates over all the paths in the given crate.
-fn each_path(cdata: cmd, f: fn(path_entry) -> bool) {
+fn each_path(intr: ident_interner, cdata: cmd, f: fn(path_entry) -> bool) {
     let root = ebml::doc(cdata.data);
     let items = ebml::get_doc(root, tag_items);
     let items_data = ebml::get_doc(items, tag_items_data);
@@ -397,8 +400,8 @@ fn each_path(cdata: cmd, f: fn(path_entry) -> bool) {
     // First, go through all the explicit items.
     for ebml::tagged_docs(items_data, tag_items_data_item) |item_doc| {
         if !broken {
-            let path = ast_map::path_to_str_with_sep(item_path(item_doc),
-                                                     ~"::");
+            let path = ast_map::path_to_str_with_sep(
+                item_path(intr, item_doc), ~"::", intr);
             if path != ~"" {
                 // Extract the def ID.
                 let def_id = item_def_id(item_doc, cdata);
@@ -467,8 +470,9 @@ fn each_path(cdata: cmd, f: fn(path_entry) -> bool) {
     }
 }
 
-fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path {
-    item_path(lookup_item(id, cdata.data))
+fn get_item_path(intr: ident_interner, cdata: cmd, id: ast::node_id)
+    -> ast_map::path {
+    item_path(intr, lookup_item(id, cdata.data))
 }
 
 type decode_inlined_item = fn(
@@ -477,13 +481,13 @@ type decode_inlined_item = fn(
     path: ast_map::path,
     par_doc: ebml::doc) -> option<ast::inlined_item>;
 
-fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
+fn maybe_get_item_ast(intr: ident_interner, cdata: cmd, tcx: ty::ctxt,
                       id: ast::node_id,
                       decode_inlined_item: decode_inlined_item
                      ) -> csearch::found_ast {
     debug!{"Looking up item: %d", id};
     let item_doc = lookup_item(id, cdata.data);
-    let path = vec::init(item_path(item_doc));
+    let path = vec::init(item_path(intr, item_doc));
     match decode_inlined_item(cdata, tcx, path, item_doc) {
       some(ii) => csearch::found(ii),
       none => {
@@ -503,8 +507,8 @@ fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
     }
 }
 
-fn get_enum_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-    -> ~[ty::variant_info] {
+fn get_enum_variants(intr: ident_interner, cdata: cmd, id: ast::node_id,
+                     tcx: ty::ctxt) -> ~[ty::variant_info] {
     let data = cdata.data;
     let items = ebml::get_doc(ebml::doc(data), tag_items);
     let item = find_item(id, items);
@@ -515,7 +519,7 @@ fn get_enum_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
         let item = find_item(did.node, items);
         let ctor_ty = item_type({crate: cdata.cnum, node: id}, item,
                                 tcx, cdata);
-        let name = item_name(item);
+        let name = item_name(intr, item);
         let mut arg_tys: ~[ty::t] = ~[];
         match ty::get(ctor_ty).struct {
           ty::ty_fn(f) => {
@@ -573,8 +577,8 @@ fn get_self_ty(item: ebml::doc) -> ast::self_ty_ {
     }
 }
 
-fn item_impl_methods(cdata: cmd, item: ebml::doc, base_tps: uint)
-    -> ~[@method_info] {
+fn item_impl_methods(intr: ident_interner, cdata: cmd, item: ebml::doc,
+                     base_tps: uint) -> ~[@method_info] {
     let mut rslt = ~[];
     for ebml::tagged_docs(item, tag_item_impl_method) |doc| {
         let m_did = ebml::with_doc_data(doc, |d| parse_def_id(d));
@@ -583,15 +587,14 @@ fn item_impl_methods(cdata: cmd, item: ebml::doc, base_tps: uint)
         vec::push(rslt, @{did: translate_def_id(cdata, m_did),
                     /* FIXME (maybe #2323) tjc: take a look at this. */
                    n_tps: item_ty_param_count(mth_item) - base_tps,
-                   ident: item_name(mth_item),
+                   ident: item_name(intr, mth_item),
                    self_type: self_ty});
     }
     rslt
 }
 
-fn get_impls_for_mod(cdata: cmd,
-                     m_id: ast::node_id,
-                     name: option<ast::ident>,
+fn get_impls_for_mod(intr: ident_interner, cdata: cmd,
+                     m_id: ast::node_id, name: option<ast::ident>,
                      get_cdata: fn(ast::crate_num) -> cmd)
                   -> @~[@_impl] {
 
@@ -608,12 +611,12 @@ fn get_impls_for_mod(cdata: cmd,
         let impl_cdata = get_cdata(local_did.crate);
         let impl_data = impl_cdata.data;
         let item = lookup_item(local_did.node, impl_data);
-        let nm = item_name(item);
+        let nm = item_name(intr, item);
         if match name { some(n) => { n == nm } none => { true } } {
            let base_tps = item_ty_param_count(item);
            vec::push(result, @{
                 did: local_did, ident: nm,
-                methods: item_impl_methods(impl_cdata, item, base_tps)
+                methods: item_impl_methods(intr, impl_cdata, item, base_tps)
             });
         };
     }
@@ -621,14 +624,14 @@ fn get_impls_for_mod(cdata: cmd,
 }
 
 /* Works for both classes and traits */
-fn get_trait_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
-    -> @~[ty::method] {
+fn get_trait_methods(intr: ident_interner, cdata: cmd, id: ast::node_id,
+                     tcx: ty::ctxt) -> @~[ty::method] {
     let data = cdata.data;
     let item = lookup_item(id, data);
     let mut result = ~[];
     for ebml::tagged_docs(item, tag_item_trait_method) |mth| {
         let bounds = item_ty_param_bounds(mth, tcx, cdata);
-        let name = item_name(mth);
+        let name = item_name(intr, mth);
         let ty = doc_type(mth, tcx, cdata);
         let fty = match ty::get(ty).struct {
           ty::ty_fn(f) => f,
@@ -651,8 +654,9 @@ fn get_trait_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
 // If the item in question is a trait, returns its set of methods and
 // their self types. Otherwise, returns none. This overlaps in an
 // annoying way with get_trait_methods.
-fn get_method_names_if_trait(cdata: cmd, node_id: ast::node_id)
-                          -> option<@DVec<(@~str, ast::self_ty_)>> {
+fn get_method_names_if_trait(intr: ident_interner, cdata: cmd,
+                             node_id: ast::node_id)
+                          -> option<@DVec<(ast::ident, ast::self_ty_)>> {
 
     let item = lookup_item(node_id, cdata.data);
     if item_family(item) != 'I' {
@@ -662,7 +666,7 @@ fn get_method_names_if_trait(cdata: cmd, node_id: ast::node_id)
     let resulting_methods = @dvec();
     for ebml::tagged_docs(item, tag_item_trait_method) |method| {
         resulting_methods.push(
-            (item_name(method), get_self_ty(method)));
+            (item_name(intr, method), get_self_ty(method)));
     }
     return some(resulting_methods);
 }
@@ -680,7 +684,7 @@ fn get_item_attrs(cdata: cmd,
 }
 
 // Helper function that gets either fields or methods
-fn get_class_members(cdata: cmd, id: ast::node_id,
+fn get_class_members(intr: ident_interner, cdata: cmd, id: ast::node_id,
                      p: fn(char) -> bool) -> ~[ty::field_ty] {
     let data = cdata.data;
     let item = lookup_item(id, data);
@@ -688,7 +692,7 @@ fn get_class_members(cdata: cmd, id: ast::node_id,
     for ebml::tagged_docs(item, tag_item_field) |an_item| {
        let f = item_family(an_item);
        if p(f) {
-          let name = item_name(an_item);
+          let name = item_name(intr, an_item);
           let did = item_def_id(an_item, cdata);
           let mt = field_mutability(an_item);
           vec::push(result, {ident: name, id: did, vis:
@@ -708,8 +712,9 @@ pure fn family_to_visibility(family: char) -> ast::visibility {
 }
 
 /* 'g' for public field, 'j' for private field, 'N' for inherited field */
-fn get_class_fields(cdata: cmd, id: ast::node_id) -> ~[ty::field_ty] {
-    get_class_members(cdata, id, |f| f == 'g' || f == 'j' || f == 'N')
+fn get_class_fields(intr: ident_interner, cdata: cmd, id: ast::node_id)
+    -> ~[ty::field_ty] {
+    get_class_members(intr, cdata, id, |f| f == 'g' || f == 'j' || f == 'N')
 }
 
 fn family_has_type_params(fam_ch: char) -> bool {
@@ -774,7 +779,7 @@ fn get_meta_items(md: ebml::doc) -> ~[@ast::meta_item] {
     for ebml::tagged_docs(md, tag_meta_item_word) |meta_item_doc| {
         let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
         let n = str::from_bytes(ebml::doc_data(nd));
-        vec::push(items, attr::mk_word_item(@n));
+        vec::push(items, attr::mk_word_item(n));
     };
     for ebml::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| {
         let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
@@ -783,13 +788,13 @@ fn get_meta_items(md: ebml::doc) -> ~[@ast::meta_item] {
         let v = str::from_bytes(ebml::doc_data(vd));
         // FIXME (#623): Should be able to decode meta_name_value variants,
         // but currently the encoder just drops them
-        vec::push(items, attr::mk_name_value_item_str(@n, v));
+        vec::push(items, attr::mk_name_value_item_str(n, v));
     };
     for ebml::tagged_docs(md, tag_meta_item_list) |meta_item_doc| {
         let nd = ebml::get_doc(meta_item_doc, tag_meta_item_name);
         let n = str::from_bytes(ebml::doc_data(nd));
         let subitems = get_meta_items(meta_item_doc);
-        vec::push(items, attr::mk_list_item(@n, subitems));
+        vec::push(items, attr::mk_list_item(n, subitems));
     };
     return items;
 }
@@ -815,17 +820,19 @@ fn get_attributes(md: ebml::doc) -> ~[ast::attribute] {
     return attrs;
 }
 
-fn list_meta_items(meta_items: ebml::doc, out: io::Writer) {
+fn list_meta_items(intr: ident_interner,
+                   meta_items: ebml::doc, out: io::Writer) {
     for get_meta_items(meta_items).each |mi| {
-        out.write_str(fmt!{"%s\n", pprust::meta_item_to_str(*mi)});
+        out.write_str(fmt!{"%s\n", pprust::meta_item_to_str(*mi, intr)});
     }
 }
 
-fn list_crate_attributes(md: ebml::doc, hash: @~str, out: io::Writer) {
-    out.write_str(fmt!{"=Crate Attributes (%s)=\n", *hash});
+fn list_crate_attributes(intr: ident_interner, md: ebml::doc, hash: ~str,
+                         out: io::Writer) {
+    out.write_str(fmt!{"=Crate Attributes (%s)=\n", hash});
 
     for get_attributes(md).each |attr| {
-        out.write_str(fmt!{"%s\n", pprust::attribute_to_str(attr)});
+        out.write_str(fmt!{"%s\n", pprust::attribute_to_str(attr, intr)});
     }
 
     out.write_str(~"\n\n");
@@ -836,9 +843,9 @@ fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] {
 }
 
 type crate_dep = {cnum: ast::crate_num, name: ast::ident,
-                  vers: @~str, hash: @~str};
+                  vers: ~str, hash: ~str};
 
-fn get_crate_deps(data: @~[u8]) -> ~[crate_dep] {
+fn get_crate_deps(intr: ident_interner, data: @~[u8]) -> ~[crate_dep] {
     let mut deps: ~[crate_dep] = ~[];
     let cratedoc = ebml::doc(data);
     let depsdoc = ebml::get_doc(cratedoc, tag_crate_deps);
@@ -848,42 +855,44 @@ fn get_crate_deps(data: @~[u8]) -> ~[crate_dep] {
     }
     for ebml::tagged_docs(depsdoc, tag_crate_dep) |depdoc| {
         vec::push(deps, {cnum: crate_num,
-                  name: @docstr(depdoc, tag_crate_dep_name),
-                  vers: @docstr(depdoc, tag_crate_dep_vers),
-                  hash: @docstr(depdoc, tag_crate_dep_hash)});
+                  name: intr.intern(@docstr(depdoc, tag_crate_dep_name)),
+                  vers: docstr(depdoc, tag_crate_dep_vers),
+                  hash: docstr(depdoc, tag_crate_dep_hash)});
         crate_num += 1;
     };
     return deps;
 }
 
-fn list_crate_deps(data: @~[u8], out: io::Writer) {
+fn list_crate_deps(intr: ident_interner, data: @~[u8], out: io::Writer) {
     out.write_str(~"=External Dependencies=\n");
 
-    for get_crate_deps(data).each |dep| {
-        out.write_str(fmt!{"%d %s-%s-%s\n",
-                           dep.cnum, *dep.name, *dep.hash, *dep.vers});
+    for get_crate_deps(intr, data).each |dep| {
+        out.write_str(
+            fmt!{"%d %s-%s-%s\n",
+                 dep.cnum, *intr.get(dep.name), dep.hash, dep.vers});
     }
 
     out.write_str(~"\n");
 }
 
-fn get_crate_hash(data: @~[u8]) -> @~str {
+fn get_crate_hash(data: @~[u8]) -> ~str {
     let cratedoc = ebml::doc(data);
     let hashdoc = ebml::get_doc(cratedoc, tag_crate_hash);
-    return @str::from_bytes(ebml::doc_data(hashdoc));
+    return str::from_bytes(ebml::doc_data(hashdoc));
 }
 
-fn get_crate_vers(data: @~[u8]) -> @~str {
+fn get_crate_vers(data: @~[u8]) -> ~str {
     let attrs = decoder::get_crate_attributes(data);
     return match attr::last_meta_item_value_str_by_name(
         attr::find_linkage_metas(attrs), ~"vers") {
       some(ver) => ver,
-      none => @~"0.0"
+      none => ~"0.0"
     };
 }
 
-fn iter_crate_items(cdata: cmd, proc: fn(~str, ast::def_id)) {
-    for each_path(cdata) |path_entry| {
+fn iter_crate_items(intr: ident_interner,
+                    cdata: cmd, proc: fn(~str, ast::def_id)) {
+    for each_path(intr, cdata) |path_entry| {
         match path_entry.def_like {
             dl_impl(*) | dl_field => {}
             dl_def(def) => {
@@ -893,7 +902,8 @@ fn iter_crate_items(cdata: cmd, proc: fn(~str, ast::def_id)) {
     }
 }
 
-fn get_crate_module_paths(cdata: cmd) -> ~[(ast::def_id, ~str)] {
+fn get_crate_module_paths(intr: ident_interner, cdata: cmd)
+                                    -> ~[(ast::def_id, ~str)] {
     fn mod_of_path(p: ~str) -> ~str {
         str::connect(vec::init(str::split_str(p, ~"::")), ~"::")
     }
@@ -902,7 +912,7 @@ fn get_crate_module_paths(cdata: cmd) -> ~[(ast::def_id, ~str)] {
     // fowarded path due to renamed import or reexport
     let mut res = ~[];
     let mods = map::str_hash();
-    do iter_crate_items(cdata) |path, did| {
+    do iter_crate_items(intr, cdata) |path, did| {
         let m = mod_of_path(path);
         if str::is_not_empty(m) {
             // if m has a sub-item, it must be a module
@@ -919,11 +929,12 @@ fn get_crate_module_paths(cdata: cmd) -> ~[(ast::def_id, ~str)] {
     }
 }
 
-fn list_crate_metadata(bytes: @~[u8], out: io::Writer) {
+fn list_crate_metadata(intr: ident_interner, bytes: @~[u8],
+                       out: io::Writer) {
     let hash = get_crate_hash(bytes);
     let md = ebml::doc(bytes);
-    list_crate_attributes(md, hash, out);
-    list_crate_deps(bytes, out);
+    list_crate_attributes(intr, md, hash, out);
+    list_crate_deps(intr, bytes, out);
 }
 
 // Translates a def_id from an external crate to a def_id for the current
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index 2389f43b5d5..e14e64ddd0c 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -71,8 +71,8 @@ fn reachable(ecx: @encode_ctxt, id: node_id) -> bool {
     ecx.reachable.contains_key(id)
 }
 
-fn encode_name(ebml_w: ebml::writer, name: ident) {
-    ebml_w.wr_tagged_str(tag_paths_data_name, *name);
+fn encode_name(ecx: @encode_ctxt, ebml_w: ebml::writer, name: ident) {
+    ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
 }
 
 fn encode_def_id(ebml_w: ebml::writer, id: def_id) {
@@ -97,13 +97,15 @@ fn encode_mutability(ebml_w: ebml::writer, mt: class_mutability) {
 
 type entry<T> = {val: T, pos: uint};
 
-fn add_to_index(ebml_w: ebml::writer, path: &[ident], &index: ~[entry<~str>],
-                name: ident) {
+fn add_to_index(ecx: @encode_ctxt, ebml_w: ebml::writer, path: &[ident],
+                &index: ~[entry<~str>], name: ident) {
     let mut full_path = ~[];
     vec::push_all(full_path, path);
     vec::push(full_path, name);
-    vec::push(index, {val: ast_util::path_name_i(full_path),
-                      pos: ebml_w.writer.tell()});
+    vec::push(index,
+              {val: ast_util::path_name_i(full_path,
+                                          ecx.tcx.sess.parse_sess.interner),
+               pos: ebml_w.writer.tell()});
 }
 
 fn encode_trait_ref(ebml_w: ebml::writer, ecx: @encode_ctxt, t: @trait_ref) {
@@ -209,7 +211,7 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, local_def(variant.node.id));
         encode_family(ebml_w, 'v');
-        encode_name(ebml_w, variant.node.name);
+        encode_name(ecx, ebml_w, variant.node.name);
         encode_parent_item(ebml_w, local_def(id));
         encode_type(ecx, ebml_w,
                     node_id_to_type(ecx.tcx, variant.node.id));
@@ -227,29 +229,29 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
             disr_val = vi[i].disr_val;
         }
         encode_type_param_bounds(ebml_w, ecx, ty_params);
-        encode_path(ebml_w, path, ast_map::path_name(variant.node.name));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(variant.node.name));
         ebml_w.end_tag();
         disr_val += 1;
         i += 1;
     }
 }
 
-fn encode_path(ebml_w: ebml::writer,
-               path: ast_map::path,
+fn encode_path(ecx: @encode_ctxt, ebml_w: ebml::writer, path: ast_map::path,
                name: ast_map::path_elt) {
-    fn encode_path_elt(ebml_w: ebml::writer, elt: ast_map::path_elt) {
+    fn encode_path_elt(ecx: @encode_ctxt, ebml_w: ebml::writer,
+                       elt: ast_map::path_elt) {
         let (tag, name) = match elt {
           ast_map::path_mod(name) => (tag_path_elt_mod, name),
           ast_map::path_name(name) => (tag_path_elt_name, name)
         };
 
-        ebml_w.wr_tagged_str(tag, *name);
+        ebml_w.wr_tagged_str(tag, ecx.tcx.sess.str_of(name));
     }
 
     do ebml_w.wr_tag(tag_path) {
         ebml_w.wr_tagged_u32(tag_path_len, (vec::len(path) + 1u) as u32);
-        do vec::iter(path) |pe| { encode_path_elt(ebml_w, pe); }
-        encode_path_elt(ebml_w, name);
+        do vec::iter(path) |pe| { encode_path_elt(ecx, ebml_w, pe); }
+        encode_path_elt(ecx, ebml_w, name);
     }
 }
 
@@ -258,7 +260,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
     ebml_w.start_tag(tag_items_data_item);
     encode_def_id(ebml_w, local_def(id));
     encode_family(ebml_w, 'm');
-    encode_name(ebml_w, name);
+    encode_name(ecx, ebml_w, name);
     debug!{"(encoding info for module) encoding info for module ID %d", id};
 
     // Encode info about all the module children.
@@ -268,10 +270,11 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
                 let (ident, did) = (item.ident, item.id);
                 debug!{"(encoding info for module) ... encoding impl %s \
                         (%?/%?), exported? %?",
-                       *ident,
-                       did,
-                       ast_map::node_id_to_str(ecx.tcx.items, did),
-                       ast_util::is_exported(ident, md)};
+                        ecx.tcx.sess.str_of(ident),
+                        did,
+                        ast_map::node_id_to_str(ecx.tcx.items, did, ecx.tcx
+                                                .sess.parse_sess.interner),
+                        ast_util::is_exported(ident, md)};
 
                 ebml_w.start_tag(tag_mod_impl);
                 ebml_w.wr_str(def_to_str(local_def(did)));
@@ -281,7 +284,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
         }
     }
 
-    encode_path(ebml_w, path, ast_map::path_mod(name));
+    encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
 
     // Encode the reexports of this module.
     debug!("(encoding info for module) encoding reexports for %d", id);
@@ -371,10 +374,11 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
                 vec::push(*global_index, {val: id,
                                           pos: ebml_w.writer.tell()});
                 ebml_w.start_tag(tag_items_data_item);
-                debug!{"encode_info_for_class: doing %s %d", *nm, id};
+                debug!{"encode_info_for_class: doing %s %d",
+                       tcx.sess.str_of(nm), id};
                 encode_visibility(ebml_w, vis);
-                encode_name(ebml_w, nm);
-                encode_path(ebml_w, path, ast_map::path_name(nm));
+                encode_name(ecx, ebml_w, nm);
+                encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
                 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
                 encode_mutability(ebml_w, mt);
                 encode_def_id(ebml_w, local_def(id));
@@ -392,7 +396,8 @@ fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
                           {val: m.id, pos: ebml_w.writer.tell()});
                 let impl_path = vec::append_one(path,
                                                 ast_map::path_name(m.ident));
-                debug!{"encode_info_for_class: doing %s %d", *m.ident, m.id};
+                debug!{"encode_info_for_class: doing %s %d",
+                       ecx.tcx.sess.str_of(m.ident), m.id};
                 encode_info_for_method(ecx, ebml_w, impl_path,
                                        should_inline(m.attrs), id, m,
                                        vec::append(class_tps, m.tps));
@@ -409,15 +414,16 @@ fn encode_info_for_fn(ecx: @encode_ctxt, ebml_w: ebml::writer,
                       item: option<inlined_item>, tps: ~[ty_param],
                       decl: fn_decl) {
         ebml_w.start_tag(tag_items_data_item);
-        encode_name(ebml_w, ident);
+        encode_name(ecx, ebml_w, ident);
         encode_def_id(ebml_w, local_def(id));
         encode_family(ebml_w, purity_fn_family(decl.purity));
         encode_type_param_bounds(ebml_w, ecx, tps);
         let its_ty = node_id_to_type(ecx.tcx, id);
-        debug!{"fn name = %s ty = %s its node id = %d", *ident,
+        debug!{"fn name = %s ty = %s its node id = %d",
+               ecx.tcx.sess.str_of(ident),
                util::ppaux::ty_to_str(ecx.tcx, its_ty), id};
         encode_type(ecx, ebml_w, its_ty);
-        encode_path(ebml_w, path, ast_map::path_name(ident));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(ident));
         match item {
            some(it) => {
              ecx.encode_inlined_item(ecx, ebml_w, path, it);
@@ -433,14 +439,15 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::writer,
                           impl_path: ast_map::path, should_inline: bool,
                           parent_id: node_id,
                           m: @method, all_tps: ~[ty_param]) {
-    debug!{"encode_info_for_method: %d %s %u", m.id, *m.ident, all_tps.len()};
+    debug!{"encode_info_for_method: %d %s %u", m.id,
+           ecx.tcx.sess.str_of(m.ident), all_tps.len()};
     ebml_w.start_tag(tag_items_data_item);
     encode_def_id(ebml_w, local_def(m.id));
     encode_family(ebml_w, purity_fn_family(m.decl.purity));
     encode_type_param_bounds(ebml_w, ecx, all_tps);
     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
-    encode_name(ebml_w, m.ident);
-    encode_path(ebml_w, impl_path, ast_map::path_name(m.ident));
+    encode_name(ecx, ebml_w, m.ident);
+    encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
     encode_self_type(ebml_w, m.self_ty.node);
     if all_tps.len() > 0u || should_inline {
         ecx.encode_inlined_item(
@@ -504,7 +511,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_family(ebml_w, 'c');
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
         encode_symbol(ecx, ebml_w, item.id);
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         ebml_w.end_tag();
       }
       item_fn(decl, tps, _) => {
@@ -514,7 +521,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_family(ebml_w, purity_fn_family(decl.purity));
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         if tps.len() > 0u || should_inline(item.attrs) {
             ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
         } else {
@@ -531,8 +538,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, local_def(item.id));
         encode_family(ebml_w, 'n');
-        encode_name(ebml_w, item.ident);
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_name(ecx, ebml_w, item.ident);
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         ebml_w.end_tag();
       }
       item_ty(_, tps) => {
@@ -542,8 +549,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_family(ebml_w, 'y');
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
-        encode_name(ebml_w, item.ident);
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_name(ecx, ebml_w, item.ident);
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         encode_region_param(ecx, ebml_w, item);
         ebml_w.end_tag();
       }
@@ -554,12 +561,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
             encode_family(ebml_w, 't');
             encode_type_param_bounds(ebml_w, ecx, tps);
             encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
-            encode_name(ebml_w, item.ident);
+            encode_name(ecx, ebml_w, item.ident);
             for enum_definition.variants.each |v| {
                 encode_variant_id(ebml_w, local_def(v.node.id));
             }
             ecx.encode_inlined_item(ecx, ebml_w, path, ii_item(item));
-            encode_path(ebml_w, path, ast_map::path_name(item.ident));
+            encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
             encode_region_param(ecx, ebml_w, item);
         }
         encode_enum_variant_info(ecx, ebml_w, item.id,
@@ -576,10 +583,12 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         /* Encode the dtor */
         do option::iter(struct_def.dtor) |dtor| {
             vec::push(*index, {val: dtor.node.id, pos: ebml_w.writer.tell()});
-          encode_info_for_fn(ecx, ebml_w, dtor.node.id, @(*item.ident
-                             + ~"_dtor"), path, if tps.len() > 0u {
-                               some(ii_dtor(dtor, item.ident, tps,
-                                            local_def(item.id))) }
+          encode_info_for_fn(ecx, ebml_w, dtor.node.id,
+                             ecx.tcx.sess.ident_of(
+                                 ecx.tcx.sess.str_of(item.ident) + ~"_dtor"),
+                             path, if tps.len() > 0u {
+                                 some(ii_dtor(dtor, item.ident, tps,
+                                              local_def(item.id))) }
                              else { none }, tps, ast_util::dtor_dec());
         }
 
@@ -596,8 +605,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
 
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
-        encode_name(ebml_w, item.ident);
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_name(ecx, ebml_w, item.ident);
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         encode_region_param(ecx, ebml_w, item);
         for struct_def.traits.each |t| {
            encode_trait_ref(ebml_w, ecx, t);
@@ -618,7 +627,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                 named_field(ident, mutability, vis) => {
                    ebml_w.start_tag(tag_item_field);
                    encode_visibility(ebml_w, vis);
-                   encode_name(ebml_w, ident);
+                   encode_name(ecx, ebml_w, ident);
                    encode_def_id(ebml_w, local_def(f.node.id));
                    ebml_w.end_tag();
                 }
@@ -634,7 +643,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                    as a trait */
                 ebml_w.start_tag(tag_item_trait_method);
                 encode_family(ebml_w, purity_fn_family(m.decl.purity));
-                encode_name(ebml_w, m.ident);
+                encode_name(ecx, ebml_w, m.ident);
                 encode_type_param_bounds(ebml_w, ecx, m.tps);
                 encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
                 encode_def_id(ebml_w, local_def(m.id));
@@ -655,8 +664,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
 
         /* Encode the constructor */
         for struct_def.ctor.each |ctor| {
-            debug!{"encoding info for ctor %s %d", *item.ident,
-                   ctor.node.id};
+            debug!{"encoding info for ctor %s %d",
+                   ecx.tcx.sess.str_of(item.ident), ctor.node.id};
             vec::push(*index, {
                 val: ctor.node.id,
                 pos: ebml_w.writer.tell()
@@ -676,7 +685,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_region_param(ecx, ebml_w, item);
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
-        encode_name(ebml_w, item.ident);
+        encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         for methods.each |m| {
             ebml_w.start_tag(tag_item_impl_method);
@@ -689,7 +698,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         for traits.each |associated_trait| {
            encode_trait_ref(ebml_w, ecx, associated_trait)
         }
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         ebml_w.end_tag();
 
         let impl_path = vec::append_one(path,
@@ -709,7 +718,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
         encode_region_param(ecx, ebml_w, item);
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
-        encode_name(ebml_w, item.ident);
+        encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         let mut i = 0u;
         for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| {
@@ -717,7 +726,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
               required(ty_m) => {
                 ebml_w.start_tag(tag_item_trait_method);
                 encode_def_id(ebml_w, local_def(ty_m.id));
-                encode_name(ebml_w, mty.ident);
+                encode_name(ecx, ebml_w, mty.ident);
                 encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
                 encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
                 encode_family(ebml_w, purity_fn_family(mty.purity));
@@ -732,7 +741,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
             }
             i += 1u;
         }
-        encode_path(ebml_w, path, ast_map::path_name(item.ident));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         for traits.each |associated_trait| {
            encode_trait_ref(ebml_w, ecx, associated_trait)
         }
@@ -750,13 +759,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
 
             ebml_w.start_tag(tag_items_data_item);
             encode_def_id(ebml_w, local_def(ty_m.id));
-            encode_name(ebml_w, ty_m.ident);
+            encode_name(ecx, ebml_w, ty_m.ident);
             encode_family(ebml_w,
                           purity_static_method_family(ty_m.decl.purity));
             let polyty = ecx.tcx.tcache.get(local_def(ty_m.id));
             encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds);
             encode_type(ecx, ebml_w, polyty.ty);
-            encode_path(ebml_w, path, ast_map::path_name(ty_m.ident));
+            encode_path(ecx, ebml_w, path, ast_map::path_name(ty_m.ident));
             ebml_w.end_tag();
         }
 
@@ -786,7 +795,7 @@ fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
         } else {
             encode_symbol(ecx, ebml_w, nitem.id);
         }
-        encode_path(ebml_w, path, ast_map::path_name(nitem.ident));
+        encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
       }
     }
     ebml_w.end_tag();
@@ -798,7 +807,8 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
     ebml_w.start_tag(tag_items_data);
     vec::push(*index, {val: crate_node_id, pos: ebml_w.writer.tell()});
     encode_info_for_mod(ecx, ebml_w, crate.node.module,
-                        crate_node_id, ~[], @~"");
+                        crate_node_id, ~[],
+                        syntax::parse::token::special_idents::invalid);
     visit::visit_crate(*crate, (), visit::mk_vt(@{
         visit_expr: |_e, _cx, _v| { },
         visit_item: |i, cx, v, copy ebml_w| {
@@ -883,7 +893,7 @@ fn encode_meta_item(ebml_w: ebml::writer, mi: meta_item) {
       meta_word(name) => {
         ebml_w.start_tag(tag_meta_item_word);
         ebml_w.start_tag(tag_meta_item_name);
-        ebml_w.writer.write(str::bytes(*name));
+        ebml_w.writer.write(str::bytes(name));
         ebml_w.end_tag();
         ebml_w.end_tag();
       }
@@ -892,7 +902,7 @@ fn encode_meta_item(ebml_w: ebml::writer, mi: meta_item) {
           lit_str(value) => {
             ebml_w.start_tag(tag_meta_item_name_value);
             ebml_w.start_tag(tag_meta_item_name);
-            ebml_w.writer.write(str::bytes(*name));
+            ebml_w.writer.write(str::bytes(name));
             ebml_w.end_tag();
             ebml_w.start_tag(tag_meta_item_value);
             ebml_w.writer.write(str::bytes(*value));
@@ -905,7 +915,7 @@ fn encode_meta_item(ebml_w: ebml::writer, mi: meta_item) {
       meta_list(name, items) => {
         ebml_w.start_tag(tag_meta_item_list);
         ebml_w.start_tag(tag_meta_item_name);
-        ebml_w.writer.write(str::bytes(*name));
+        ebml_w.writer.write(str::bytes(name));
         ebml_w.end_tag();
         for items.each |inner_item| {
             encode_meta_item(ebml_w, *inner_item);
@@ -934,22 +944,22 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] {
     fn synthesize_link_attr(ecx: @encode_ctxt, items: ~[@meta_item]) ->
        attribute {
 
-        assert (*ecx.link_meta.name != ~"");
-        assert (*ecx.link_meta.vers != ~"");
+        assert (ecx.link_meta.name != ~"");
+        assert (ecx.link_meta.vers != ~"");
 
         let name_item =
-            attr::mk_name_value_item_str(@~"name", *ecx.link_meta.name);
+            attr::mk_name_value_item_str(~"name", ecx.link_meta.name);
         let vers_item =
-            attr::mk_name_value_item_str(@~"vers", *ecx.link_meta.vers);
+            attr::mk_name_value_item_str(~"vers", ecx.link_meta.vers);
 
         let other_items =
             {
-                let tmp = attr::remove_meta_items_by_name(items, @~"name");
-                attr::remove_meta_items_by_name(tmp, @~"vers")
+                let tmp = attr::remove_meta_items_by_name(items, ~"name");
+                attr::remove_meta_items_by_name(tmp, ~"vers")
             };
 
         let meta_items = vec::append(~[name_item, vers_item], other_items);
-        let link_item = attr::mk_list_item(@~"link", meta_items);
+        let link_item = attr::mk_list_item(~"link", meta_items);
 
         return attr::mk_attr(link_item);
     }
@@ -959,7 +969,7 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] {
     for crate.node.attrs.each |attr| {
         vec::push(
             attrs,
-            if *attr::get_attr_name(attr) != ~"link" {
+            if attr::get_attr_name(attr) != ~"link" {
                 attr
             } else {
                 match attr.node.value.node {
@@ -977,16 +987,19 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] {
     return attrs;
 }
 
-fn encode_crate_deps(ebml_w: ebml::writer, cstore: cstore::cstore) {
+fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::writer,
+                     cstore: cstore::cstore) {
+
+    fn get_ordered_deps(ecx: @encode_ctxt, cstore: cstore::cstore)
+        -> ~[decoder::crate_dep] {
 
-    fn get_ordered_deps(cstore: cstore::cstore) -> ~[decoder::crate_dep] {
         type hashkv = @{key: crate_num, val: cstore::crate_metadata};
         type numdep = decoder::crate_dep;
 
         // Pull the cnums and name,vers,hash out of cstore
         let mut deps: ~[mut numdep] = ~[mut];
         do cstore::iter_crate_data(cstore) |key, val| {
-            let dep = {cnum: key, name: @val.name,
+            let dep = {cnum: key, name: ecx.tcx.sess.ident_of(val.name),
                        vers: decoder::get_crate_vers(val.data),
                        hash: decoder::get_crate_hash(val.data)};
             vec::push(deps, dep);
@@ -1014,22 +1027,23 @@ fn encode_crate_deps(ebml_w: ebml::writer, cstore: cstore::cstore) {
     // 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);
-    for get_ordered_deps(cstore).each |dep| {
-        encode_crate_dep(ebml_w, dep);
+    for get_ordered_deps(ecx, cstore).each |dep| {
+        encode_crate_dep(ecx, ebml_w, dep);
     }
     ebml_w.end_tag();
 }
 
-fn encode_crate_dep(ebml_w: ebml::writer, dep: decoder::crate_dep) {
+fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: ebml::writer,
+                    dep: decoder::crate_dep) {
     ebml_w.start_tag(tag_crate_dep);
     ebml_w.start_tag(tag_crate_dep_name);
-    ebml_w.writer.write(str::bytes(*dep.name));
+    ebml_w.writer.write(str::bytes(ecx.tcx.sess.str_of(dep.name)));
     ebml_w.end_tag();
     ebml_w.start_tag(tag_crate_dep_vers);
-    ebml_w.writer.write(str::bytes(*dep.vers));
+    ebml_w.writer.write(str::bytes(dep.vers));
     ebml_w.end_tag();
     ebml_w.start_tag(tag_crate_dep_hash);
-    ebml_w.writer.write(str::bytes(*dep.hash));
+    ebml_w.writer.write(str::bytes(dep.hash));
     ebml_w.end_tag();
     ebml_w.end_tag();
 }
@@ -1064,7 +1078,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
     let crate_attrs = synthesize_crate_attrs(ecx, crate);
     encode_attributes(ebml_w, crate_attrs);
 
-    encode_crate_deps(ebml_w, ecx.cstore);
+    encode_crate_deps(ecx, ebml_w, ecx.cstore);
 
     // Encode and index the items.
     ebml_w.start_tag(tag_items);
diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs
index d1e24642927..d4b66a7e4ec 100644
--- a/src/rustc/metadata/loader.rs
+++ b/src/rustc/metadata/loader.rs
@@ -7,6 +7,7 @@ import syntax::codemap::span;
 import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
 import filesearch::filesearch;
 import io::WriterUtil;
+import syntax::parse::token::ident_interner;
 
 export os;
 export os_macos, os_win32, os_linux, os_freebsd;
@@ -33,7 +34,8 @@ type ctxt = {
     metas: ~[@ast::meta_item],
     hash: ~str,
     os: os,
-    static: bool
+    static: bool,
+    intr: ident_interner
 };
 
 fn load_library_crate(cx: ctxt) -> {ident: ~str, data: @~[u8]} {
@@ -41,7 +43,8 @@ fn load_library_crate(cx: ctxt) -> {ident: ~str, data: @~[u8]} {
       some(t) => return t,
       none => {
         cx.diag.span_fatal(
-            cx.span, fmt!{"can't find crate for `%s`", *cx.ident});
+            cx.span, fmt!{"can't find crate for `%s`",
+                          *cx.intr.get(cx.ident)});
       }
     }
 }
@@ -66,7 +69,7 @@ fn find_library_crate_aux(cx: ctxt,
                           filesearch: filesearch::filesearch) ->
    option<{ident: ~str, data: @~[u8]}> {
     let crate_name = crate_name_from_metas(cx.metas);
-    let prefix: ~str = nn.prefix + *crate_name + ~"-";
+    let prefix: ~str = nn.prefix + crate_name + ~"-";
     let suffix: ~str = nn.suffix;
 
     let mut matches = ~[];
@@ -104,19 +107,19 @@ fn find_library_crate_aux(cx: ctxt,
         some(matches[0])
     } else {
         cx.diag.span_err(
-            cx.span, fmt!{"multiple matching crates for `%s`", *crate_name});
+            cx.span, fmt!{"multiple matching crates for `%s`", crate_name});
         cx.diag.handler().note(~"candidates:");
         for matches.each |match_| {
             cx.diag.handler().note(fmt!{"path: %s", match_.ident});
             let attrs = decoder::get_crate_attributes(match_.data);
-            note_linkage_attrs(cx.diag, attrs);
+            note_linkage_attrs(cx.intr, cx.diag, attrs);
         }
         cx.diag.handler().abort_if_errors();
         none
     }
 }
 
-fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> @~str {
+fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> ~str {
     let name_items = attr::find_meta_items_by_name(metas, ~"name");
     match vec::last_opt(name_items) {
       some(i) => {
@@ -131,9 +134,10 @@ fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> @~str {
     }
 }
 
-fn note_linkage_attrs(diag: span_handler, attrs: ~[ast::attribute]) {
+fn note_linkage_attrs(intr: ident_interner, diag: span_handler,
+                      attrs: ~[ast::attribute]) {
     for attr::find_linkage_attrs(attrs).each |attr| {
-        diag.handler().note(fmt!{"meta: %s", pprust::attr_to_str(attr)});
+        diag.handler().note(fmt!{"meta: %s", pprust::attr_to_str(attr,intr)});
     }
 }
 
@@ -143,7 +147,7 @@ fn crate_matches(crate_data: @~[u8], metas: ~[@ast::meta_item],
     let linkage_metas = attr::find_linkage_metas(attrs);
     if hash.is_not_empty() {
         let chash = decoder::get_crate_hash(crate_data);
-        if *chash != hash { return false; }
+        if chash != hash { return false; }
     }
     metadata_matches(linkage_metas, metas)
 }
@@ -154,15 +158,8 @@ fn metadata_matches(extern_metas: ~[@ast::meta_item],
     debug!{"matching %u metadata requirements against %u items",
            vec::len(local_metas), vec::len(extern_metas)};
 
-    debug!{"crate metadata:"};
-    for extern_metas.each |have| {
-        debug!{"  %s", pprust::meta_item_to_str(*have)};
-    }
-
     for local_metas.each |needed| {
-        debug!{"looking for %s", pprust::meta_item_to_str(*needed)};
         if !attr::contains(extern_metas, needed) {
-            debug!{"missing %s", pprust::meta_item_to_str(*needed)};
             return false;
         }
     }
@@ -206,9 +203,10 @@ fn meta_section_name(os: os) -> ~str {
 }
 
 // A diagnostic function for dumping crate metadata to an output stream
-fn list_file_metadata(os: os, path: ~str, out: io::Writer) {
+fn list_file_metadata(intr: ident_interner, os: os, path: ~str,
+                      out: io::Writer) {
     match get_metadata_section(os, path) {
-      option::some(bytes) => decoder::list_crate_metadata(bytes, out),
+      option::some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
       option::none => {
         out.write_str(~"could not find metadata in " + path + ~".\n");
       }
diff --git a/src/rustc/metadata/tydecode.rs b/src/rustc/metadata/tydecode.rs
index a61e111cca9..5b76e0da7f5 100644
--- a/src/rustc/metadata/tydecode.rs
+++ b/src/rustc/metadata/tydecode.rs
@@ -46,7 +46,7 @@ fn parse_ident_(st: @pstate, is_last: fn@(char) -> bool) ->
     while !is_last(peek(st)) {
         rslt += str::from_byte(next_byte(st));
     }
-    return @rslt;
+    return st.tcx.sess.ident_of(rslt);
 }
 
 
@@ -133,7 +133,7 @@ fn parse_bound_region(st: @pstate) -> ty::bound_region {
         assert next(st) == '|';
         ty::br_anon(id)
       }
-      '[' => ty::br_named(@parse_str(st, ']')),
+      '[' => ty::br_named(st.tcx.sess.ident_of(parse_str(st, ']'))),
       'c' => {
         let id = parse_int(st);
         assert next(st) == '|';
@@ -249,7 +249,7 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         assert (next(st) == '[');
         let mut fields: ~[ty::field] = ~[];
         while peek(st) != ']' {
-            let name = @parse_str(st, '=');
+            let name = st.tcx.sess.ident_of(parse_str(st, '='));
             vec::push(fields, {ident: name, mt: parse_mt(st, conv)});
         }
         st.pos = st.pos + 1u;
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index 68fe7fc4d65..4158656aa54 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -126,14 +126,14 @@ fn enc_region(w: io::Writer, cx: @ctxt, r: ty::region) {
     match r {
       ty::re_bound(br) => {
         w.write_char('b');
-        enc_bound_region(w, br);
+        enc_bound_region(w, cx, br);
       }
       ty::re_free(id, br) => {
         w.write_char('f');
         w.write_char('[');
         w.write_int(id);
         w.write_char('|');
-        enc_bound_region(w, br);
+        enc_bound_region(w, cx, br);
         w.write_char(']');
       }
       ty::re_scope(nid) => {
@@ -151,7 +151,7 @@ fn enc_region(w: io::Writer, cx: @ctxt, r: ty::region) {
     }
 }
 
-fn enc_bound_region(w: io::Writer, br: ty::bound_region) {
+fn enc_bound_region(w: io::Writer, cx: @ctxt, br: ty::bound_region) {
     match br {
       ty::br_self => w.write_char('s'),
       ty::br_anon(idx) => {
@@ -161,14 +161,14 @@ fn enc_bound_region(w: io::Writer, br: ty::bound_region) {
       }
       ty::br_named(s) => {
         w.write_char('[');
-        w.write_str(*s);
+        w.write_str(cx.tcx.sess.str_of(s));
         w.write_char(']')
       }
       ty::br_cap_avoid(id, br) => {
         w.write_char('c');
         w.write_int(id);
         w.write_char('|');
-        enc_bound_region(w, *br);
+        enc_bound_region(w, cx, *br);
       }
     }
 }
@@ -265,7 +265,7 @@ fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) {
       ty::ty_rec(fields) => {
         w.write_str(&"R[");
         for fields.each |field| {
-            w.write_str(*field.ident);
+            w.write_str(cx.tcx.sess.str_of(field.ident));
             w.write_char('=');
             enc_mt(w, cx, field.mt);
         }