about summary refs log tree commit diff
path: root/src/libsyntax
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/libsyntax
parent22c34f3c4cddea33b916eb92f8d7286b02b865a7 (diff)
downloadrust-a02b10a0621adfe36eb3cc2e46f45fc7ccdb7ea2.tar.gz
rust-a02b10a0621adfe36eb3cc2e46f45fc7ccdb7ea2.zip
Refactored ast_map and friends, mainly to have Paths without storing them.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs5
-rw-r--r--src/libsyntax/ast_map.rs778
-rw-r--r--src/libsyntax/ast_util.rs21
-rw-r--r--src/libsyntax/ext/base.rs3
-rw-r--r--src/libsyntax/ext/concat_idents.rs3
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs11
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs11
-rw-r--r--src/libsyntax/ext/deriving/generic.rs8
-rw-r--r--src/libsyntax/ext/deriving/show.rs4
-rw-r--r--src/libsyntax/ext/deriving/to_str.rs6
-rw-r--r--src/libsyntax/ext/expand.rs51
-rw-r--r--src/libsyntax/ext/format.rs2
-rw-r--r--src/libsyntax/ext/log_syntax.rs6
-rw-r--r--src/libsyntax/ext/quote.rs15
-rw-r--r--src/libsyntax/ext/source_util.rs8
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs29
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs10
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs21
-rw-r--r--src/libsyntax/fold.rs35
-rw-r--r--src/libsyntax/parse/comments.rs3
-rw-r--r--src/libsyntax/parse/common.rs8
-rw-r--r--src/libsyntax/parse/obsolete.rs3
-rw-r--r--src/libsyntax/parse/parser.rs37
-rw-r--r--src/libsyntax/parse/token.rs221
-rw-r--r--src/libsyntax/print/pprust.rs112
-rw-r--r--src/libsyntax/util/interner.rs18
-rw-r--r--src/libsyntax/visit.rs2
27 files changed, 743 insertions, 688 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index a5a49b78906..72330bb7f31 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -125,10 +125,9 @@ pub type Name = u32;
 /// A mark represents a unique id associated with a macro expansion
 pub type Mrk = u32;
 
-impl<S:Encoder> Encodable<S> for Ident {
+impl<S: Encoder> Encodable<S> for Ident {
     fn encode(&self, s: &mut S) {
-        let string = token::get_ident(self.name);
-        s.emit_str(string.get());
+        s.emit_str(token::get_ident(*self).get());
     }
 }
 
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 9d3fe4f0c4d..26c4b07fc96 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -10,161 +10,93 @@
 
 use abi::AbiSet;
 use ast::*;
-use ast;
 use ast_util;
 use codemap::Span;
-use diagnostic::SpanHandler;
 use fold::Folder;
 use fold;
-use parse::token::{get_ident_interner, IdentInterner};
+use parse::token;
 use print::pprust;
 use util::small_vector::SmallVector;
 
 use std::logging;
 use std::cell::RefCell;
-use collections::SmallIntMap;
+use std::iter;
+use std::vec;
 
 #[deriving(Clone, Eq)]
 pub enum PathElem {
-    PathMod(Ident),
-    PathName(Ident),
-
-    // A pretty name can come from an `impl` block. We attempt to select a
-    // reasonable name for debuggers to see, but to guarantee uniqueness with
-    // other paths the hash should also be taken into account during symbol
-    // generation.
-    PathPrettyName(Ident, u64),
+    PathMod(Name),
+    PathName(Name)
 }
 
 impl PathElem {
-    pub fn ident(&self) -> Ident {
+    pub fn name(&self) -> Name {
         match *self {
-            PathMod(ident)            |
-            PathName(ident)           |
-            PathPrettyName(ident, _) => ident
+            PathMod(name) | PathName(name) => name
         }
     }
 }
 
-pub type Path = ~[PathElem];
-
-pub fn path_to_str_with_sep(p: &[PathElem], sep: &str, itr: @IdentInterner)
-                            -> ~str {
-    let strs = p.map(|e| {
-        match *e {
-            PathMod(s) | PathName(s) | PathPrettyName(s, _) => {
-                itr.get(s.name)
-            }
-        }
-    });
-    strs.connect(sep)
-}
-
-pub fn path_ident_to_str(p: &Path, i: Ident, itr: @IdentInterner) -> ~str {
-    if p.is_empty() {
-        itr.get(i.name).into_owned()
-    } else {
-        let string = itr.get(i.name);
-        format!("{}::{}", path_to_str(*p, itr), string.as_slice())
+impl ToStr for PathElem {
+    fn to_str(&self) -> ~str {
+        token::get_name(self.name()).get().to_str()
     }
 }
 
-pub fn path_to_str(p: &[PathElem], itr: @IdentInterner) -> ~str {
-    path_to_str_with_sep(p, "::", itr)
+#[deriving(Clone)]
+struct LinkedPathNode<'a> {
+    node: PathElem,
+    next: LinkedPath<'a>,
 }
 
-pub fn path_elem_to_str(pe: PathElem, itr: @IdentInterner) -> ~str {
-    match pe {
-        PathMod(s) | PathName(s) | PathPrettyName(s, _) => {
-            itr.get(s.name).into_owned()
-        }
-    }
-}
+type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>;
 
-/// write a "pretty" version of `ty` to `out`. This is designed so
-/// that symbols of `impl`'d methods give some hint of where they came
-/// from, even if it's hard to read (previously they would all just be
-/// listed as `__extensions__::method_name::hash`, with no indication
-/// of the type).
-// FIXME: these dollar signs and the names in general are actually a
-//      relic of $ being one of the very few valid symbol names on
-//      unix. These kinds of details shouldn't be exposed way up here
-//      in the ast.
-fn pretty_ty(ty: &Ty, itr: @IdentInterner, out: &mut ~str) {
-    let (prefix, subty) = match ty.node {
-        TyUniq(ty) => ("$UP$", &*ty),
-        TyBox(ty) => ("$SP$", &*ty),
-        TyPtr(MutTy { ty, mutbl }) => (if mutbl == MutMutable {"$RPmut$"} else {"$RP$"},
-                                       &*ty),
-        TyRptr(_, MutTy { ty, mutbl }) => (if mutbl == MutMutable {"$BPmut$"} else {"$BP$"},
-                                           &*ty),
-
-        TyVec(ty) => ("$VEC$", &*ty),
-        TyFixedLengthVec(ty, _) => ("$FIXEDVEC$", &*ty),
-
-        // these can't be represented as <prefix><contained ty>, so
-        // need custom handling.
-        TyNil => { out.push_str("$NIL$"); return }
-        TyPath(ref path, _, _) => {
-            out.push_str(itr.get(path.segments
-                                     .last()
-                                     .unwrap()
-                                     .identifier
-                                     .name).as_slice());
-            return
-        }
-        TyTup(ref tys) => {
-            out.push_str(format!("$TUP_{}$", tys.len()));
-            for subty in tys.iter() {
-                pretty_ty(*subty, itr, out);
-                out.push_char('$');
+impl<'a> Iterator<PathElem> for LinkedPath<'a> {
+    fn next(&mut self) -> Option<PathElem> {
+        match *self {
+            Some(node) => {
+                *self = node.next;
+                Some(node.node)
             }
-            return
+            None => None
         }
+    }
+}
 
-        // meh, better than nothing.
-        TyBot => { out.push_str("$BOT$"); return }
-        TyClosure(..) => { out.push_str("$CLOSURE$"); return }
-        TyBareFn(..) => { out.push_str("$FN$"); return }
-        TyTypeof(..) => { out.push_str("$TYPEOF$"); return }
-        TyInfer(..) => { out.push_str("$INFER$"); return }
-
-    };
+// HACK(eddyb) move this into libstd (value wrapper for vec::Items).
+#[deriving(Clone)]
+pub struct Values<'a, T>(vec::Items<'a, T>);
 
-    out.push_str(prefix);
-    pretty_ty(subty, itr, out);
+impl<'a, T: Pod> Iterator<T> for Values<'a, T> {
+    fn next(&mut self) -> Option<T> {
+        let &Values(ref mut items) = self;
+        items.next().map(|&x| x)
+    }
 }
 
-pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> PathElem {
-    let itr = get_ident_interner();
+/// The type of the iterator used by with_path.
+pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>;
 
-    let hash = (trait_ref, ty).hash();
-    let mut pretty;
-    match *trait_ref {
-        None => pretty = ~"",
-        Some(ref trait_ref) => {
-            pretty = itr.get(trait_ref.path.segments.last().unwrap().identifier.name)
-                        .into_owned();
-            pretty.push_char('$');
-        }
-    };
-    pretty_ty(ty, itr, &mut pretty);
+pub fn path_to_str<PI: Iterator<PathElem>>(mut path: PI) -> ~str {
+    let itr = token::get_ident_interner();
 
-    PathPrettyName(Ident::new(itr.gensym(pretty)), hash)
+    path.fold(~"", |mut s, e| {
+        let e = itr.get(e.name());
+        if !s.is_empty() {
+            s.push_str("::");
+        }
+        s.push_str(e.as_slice());
+        s
+    })
 }
 
 #[deriving(Clone)]
 pub enum Node {
-    NodeItem(@Item, @Path),
-    NodeForeignItem(@ForeignItem, AbiSet, Visibility, @Path),
-    NodeTraitMethod(@TraitMethod, DefId /* trait did */,
-                    @Path /* path to the trait */),
-    NodeMethod(@Method, DefId /* impl did */, @Path /* path to the impl */),
-
-    /// NodeVariant represents a variant of an enum, e.g., for
-    /// `enum A { B, C, D }`, there would be a NodeItem for `A`, and a
-    /// NodeVariant item for each of `B`, `C`, and `D`.
-    NodeVariant(P<Variant>, @Item, @Path),
+    NodeItem(@Item),
+    NodeForeignItem(@ForeignItem),
+    NodeTraitMethod(@TraitMethod),
+    NodeMethod(@Method),
+    NodeVariant(P<Variant>),
     NodeExpr(@Expr),
     NodeStmt(@Stmt),
     NodeArg(@Pat),
@@ -172,27 +104,76 @@ pub enum Node {
     NodeBlock(P<Block>),
 
     /// NodeStructCtor represents a tuple struct.
-    NodeStructCtor(@StructDef, @Item, @Path),
-    NodeCalleeScope(@Expr)
+    NodeStructCtor(@StructDef),
+    NodeCalleeScope(@Expr),
 }
 
-impl Node {
-    pub fn with_attrs<T>(&self, f: |Option<&[Attribute]>| -> T) -> T {
-        let attrs = match *self {
-            NodeItem(i, _) => Some(i.attrs.as_slice()),
-            NodeForeignItem(fi, _, _, _) => Some(fi.attrs.as_slice()),
-            NodeTraitMethod(tm, _, _) => match *tm {
-                Required(ref type_m) => Some(type_m.attrs.as_slice()),
-                Provided(m) => Some(m.attrs.as_slice())
-            },
-            NodeMethod(m, _, _) => Some(m.attrs.as_slice()),
-            NodeVariant(ref v, _, _) => Some(v.node.attrs.as_slice()),
-            // unit/tuple structs take the attributes straight from
-            // the struct definition.
-            NodeStructCtor(_, strct, _) => Some(strct.attrs.as_slice()),
-            _ => None
-        };
-        f(attrs)
+// The odd layout is to bring down the total size.
+#[deriving(Clone)]
+enum MapEntry {
+    // Placeholder for holes in the map.
+    NotPresent,
+
+    // All the node types, with a parent ID.
+    EntryItem(NodeId, @Item),
+    EntryForeignItem(NodeId, @ForeignItem),
+    EntryTraitMethod(NodeId, @TraitMethod),
+    EntryMethod(NodeId, @Method),
+    EntryVariant(NodeId, P<Variant>),
+    EntryExpr(NodeId, @Expr),
+    EntryStmt(NodeId, @Stmt),
+    EntryArg(NodeId, @Pat),
+    EntryLocal(NodeId, @Pat),
+    EntryBlock(NodeId, P<Block>),
+    EntryStructCtor(NodeId, @StructDef),
+    EntryCalleeScope(NodeId, @Expr),
+
+    // Roots for node trees.
+    RootCrate,
+    RootInlinedParent(P<InlinedParent>)
+}
+
+struct InlinedParent {
+    path: ~[PathElem],
+    // Required by NodeTraitMethod and NodeMethod.
+    def_id: DefId
+}
+
+impl MapEntry {
+    fn parent(&self) -> Option<NodeId> {
+        Some(match *self {
+            EntryItem(id, _) => id,
+            EntryForeignItem(id, _) => id,
+            EntryTraitMethod(id, _) => id,
+            EntryMethod(id, _) => id,
+            EntryVariant(id, _) => id,
+            EntryExpr(id, _) => id,
+            EntryStmt(id, _) => id,
+            EntryArg(id, _) => id,
+            EntryLocal(id, _) => id,
+            EntryBlock(id, _) => id,
+            EntryStructCtor(id, _) => id,
+            EntryCalleeScope(id, _) => id,
+            _ => return None
+        })
+    }
+
+    fn to_node(&self) -> Option<Node> {
+        Some(match *self {
+            EntryItem(_, p) => NodeItem(p),
+            EntryForeignItem(_, p) => NodeForeignItem(p),
+            EntryTraitMethod(_, p) => NodeTraitMethod(p),
+            EntryMethod(_, p) => NodeMethod(p),
+            EntryVariant(_, p) => NodeVariant(p),
+            EntryExpr(_, p) => NodeExpr(p),
+            EntryStmt(_, p) => NodeStmt(p),
+            EntryArg(_, p) => NodeArg(p),
+            EntryLocal(_, p) => NodeLocal(p),
+            EntryBlock(_, p) => NodeBlock(p),
+            EntryStructCtor(_, p) => NodeStructCtor(p),
+            EntryCalleeScope(_, p) => NodeCalleeScope(p),
+            _ => return None
+        })
     }
 }
 
@@ -202,33 +183,201 @@ pub struct Map {
     /// a NodeId is in the map, but empirically the occupancy is about
     /// 75-80%, so there's not too much overhead (certainly less than
     /// a hashmap, since they (at the time of writing) have a maximum
-    /// of 75% occupancy). (The additional overhead of the Option<>
-    /// inside the SmallIntMap could be removed by adding an extra
-    /// empty variant to Node and storing a vector here, but that was
-    /// found to not make much difference.)
+    /// of 75% occupancy).
     ///
     /// Also, indexing is pretty quick when you've got a vector and
     /// plain old integers.
-    priv map: @RefCell<SmallIntMap<Node>>
+    priv map: RefCell<~[MapEntry]>
 }
 
 impl Map {
+    fn find_entry(&self, id: NodeId) -> Option<MapEntry> {
+        let map = self.map.borrow();
+        map.get().get(id as uint).map(|x| *x)
+    }
+
     /// Retrieve the Node corresponding to `id`, failing if it cannot
     /// be found.
-    pub fn get(&self, id: ast::NodeId) -> Node {
-        let map = self.map.borrow();
-        *map.get().get(&(id as uint))
+    pub fn get(&self, id: NodeId) -> Node {
+        match self.find(id) {
+            Some(node) => node,
+            None => fail!("couldn't find node id {} in the AST map", id)
+        }
     }
+
     /// Retrieve the Node corresponding to `id`, returning None if
     /// cannot be found.
-    pub fn find(&self, id: ast::NodeId) -> Option<Node> {
-        let map = self.map.borrow();
-        map.get().find(&(id as uint)).map(|&n| n)
+    pub fn find(&self, id: NodeId) -> Option<Node> {
+        self.find_entry(id).and_then(|x| x.to_node())
+    }
+
+    pub fn get_parent(&self, id: NodeId) -> NodeId {
+        self.find_entry(id).and_then(|x| x.parent()).unwrap_or(id)
+    }
+
+    pub fn get_parent_did(&self, id: NodeId) -> DefId {
+        let parent = self.get_parent(id);
+        match self.find_entry(parent) {
+            Some(RootInlinedParent(data)) => data.def_id,
+            _ => ast_util::local_def(parent)
+        }
+    }
+
+    pub fn get_foreign_abis(&self, id: NodeId) -> AbiSet {
+        let parent = self.get_parent(id);
+        let abis = match self.find_entry(parent) {
+            Some(EntryItem(_, i)) => match i.node {
+                ItemForeignMod(ref nm) => Some(nm.abis),
+                _ => None
+            },
+            // Wrong but OK, because the only inlined foreign items are intrinsics.
+            Some(RootInlinedParent(_)) => Some(AbiSet::Intrinsic()),
+            _ => None
+        };
+        match abis {
+            Some(abis) => abis,
+            None => fail!("expected foreign mod or inlined parent, found {}",
+                          self.node_to_str(parent))
+        }
+    }
+
+    pub fn get_foreign_vis(&self, id: NodeId) -> Visibility {
+        let vis = self.expect_foreign_item(id).vis;
+        match self.find(self.get_parent(id)) {
+            Some(NodeItem(i)) => vis.inherit_from(i.vis),
+            _ => vis
+        }
+    }
+
+    pub fn expect_item(&self, id: NodeId) -> @Item {
+        match self.find(id) {
+            Some(NodeItem(item)) => item,
+            _ => fail!("expected item, found {}", self.node_to_str(id))
+        }
+    }
+
+    pub fn expect_foreign_item(&self, id: NodeId) -> @ForeignItem {
+        match self.find(id) {
+            Some(NodeForeignItem(item)) => item,
+            _ => fail!("expected foreign item, found {}", self.node_to_str(id))
+        }
+    }
+
+    pub fn get_path_elem(&self, id: NodeId) -> PathElem {
+        match self.get(id) {
+            NodeItem(item) => {
+                match item.node {
+                    ItemMod(_) | ItemForeignMod(_) => {
+                        PathMod(item.ident.name)
+                    }
+                    _ => PathName(item.ident.name)
+                }
+            }
+            NodeForeignItem(i) => PathName(i.ident.name),
+            NodeMethod(m) => PathName(m.ident.name),
+            NodeTraitMethod(tm) => match *tm {
+                Required(ref m) => PathName(m.ident.name),
+                Provided(ref m) => PathName(m.ident.name)
+            },
+            NodeVariant(v) => PathName(v.node.name.name),
+            node => fail!("no path elem for {:?}", node)
+        }
+    }
+
+    pub fn with_path<T>(&self, id: NodeId, f: |PathElems| -> T) -> T {
+        self.with_path_next(id, None, f)
+    }
+
+    pub fn path_to_str(&self, id: NodeId) -> ~str {
+        self.with_path(id, |path| path_to_str(path))
+    }
+
+    fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> ~str {
+        self.with_path(id, |path| {
+            path_to_str(path.chain(Some(PathName(i.name)).move_iter()))
+        })
+    }
+
+    fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T {
+        let parent = self.get_parent(id);
+        let parent = match self.find_entry(id) {
+            Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => {
+                // Anonymous extern items, enum variants and struct ctors
+                // go in the parent scope.
+                self.get_parent(parent)
+            }
+            // But tuple struct ctors don't have names, so use the path of its
+            // parent, the struct item. Similarly with closure expressions.
+            Some(EntryStructCtor(..)) | Some(EntryExpr(..)) => {
+                return self.with_path_next(parent, next, f);
+            }
+            _ => parent
+        };
+        if parent == id {
+            match self.find_entry(id) {
+                Some(RootInlinedParent(data)) => {
+                    f(Values(data.path.iter()).chain(next))
+                }
+                _ => f(Values([].iter()).chain(next))
+            }
+        } else {
+            self.with_path_next(parent, Some(&LinkedPathNode {
+                node: self.get_path_elem(id),
+                next: next
+            }), f)
+        }
+    }
+
+    pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T {
+        let attrs = match self.get(id) {
+            NodeItem(i) => Some(i.attrs.as_slice()),
+            NodeForeignItem(fi) => Some(fi.attrs.as_slice()),
+            NodeTraitMethod(tm) => match *tm {
+                Required(ref type_m) => Some(type_m.attrs.as_slice()),
+                Provided(m) => Some(m.attrs.as_slice())
+            },
+            NodeMethod(m) => Some(m.attrs.as_slice()),
+            NodeVariant(ref v) => Some(v.node.attrs.as_slice()),
+            // unit/tuple structs take the attributes straight from
+            // the struct definition.
+            // FIXME(eddyb) make this work again (requires access to the map).
+            NodeStructCtor(_) => {
+                return self.with_attrs(self.get_parent(id), f);
+            }
+            _ => None
+        };
+        f(attrs)
+    }
+
+    pub fn span(&self, id: NodeId) -> Span {
+        match self.find(id) {
+            Some(NodeItem(item)) => item.span,
+            Some(NodeForeignItem(foreign_item)) => foreign_item.span,
+            Some(NodeTraitMethod(trait_method)) => {
+                match *trait_method {
+                    Required(ref type_method) => type_method.span,
+                    Provided(ref method) => method.span,
+                }
+            }
+            Some(NodeMethod(method)) => method.span,
+            Some(NodeVariant(variant)) => variant.span,
+            Some(NodeExpr(expr)) => expr.span,
+            Some(NodeStmt(stmt)) => stmt.span,
+            Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
+            Some(NodeBlock(block)) => block.span,
+            Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
+            Some(NodeCalleeScope(expr)) => expr.span,
+            _ => fail!("node_span: could not find span for id {}", id),
+        }
+    }
+
+    pub fn node_to_str(&self, id: NodeId) -> ~str {
+        node_id_to_str(self, id)
     }
 }
 
 pub trait FoldOps {
-    fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
+    fn new_id(&self, id: NodeId) -> NodeId {
         id
     }
     fn new_span(&self, span: Span) -> Span {
@@ -236,23 +385,28 @@ pub trait FoldOps {
     }
 }
 
-pub struct Ctx<F> {
-    map: Map,
-    path: Path,
-    diag: @SpanHandler,
+pub struct Ctx<'a, F> {
+    map: &'a Map,
+    // The node in which we are currently mapping (an item or a method).
+    // When equal to DUMMY_NODE_ID, the next mapped node becomes the parent.
+    parent: NodeId,
     fold_ops: F
 }
 
-impl<F> Ctx<F> {
-    fn insert(&self, id: ast::NodeId, node: Node) {
+impl<'a, F> Ctx<'a, F> {
+    fn insert(&self, id: NodeId, entry: MapEntry) {
         let mut map = self.map.map.borrow_mut();
-        map.get().insert(id as uint, node);
+        map.get().grow_set(id as uint, &NotPresent, entry);
     }
 }
 
-impl<F: FoldOps> Folder for Ctx<F> {
-    fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
-        self.fold_ops.new_id(id)
+impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
+    fn new_id(&mut self, id: NodeId) -> NodeId {
+        let id = self.fold_ops.new_id(id);
+        if self.parent == DUMMY_NODE_ID {
+            self.parent = id;
+        }
+        id
     }
 
     fn new_span(&mut self, span: Span) -> Span {
@@ -260,75 +414,52 @@ impl<F: FoldOps> Folder for Ctx<F> {
     }
 
     fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
-        // clone is FIXME #2543
-        let item_path = @self.path.clone();
-        self.path.push(match i.node {
-            ItemImpl(_, ref maybe_trait, ty, _) => {
-                // Right now the ident on impls is __extensions__ which isn't
-                // very pretty when debugging, so attempt to select a better
-                // name to use.
-                impl_pretty_name(maybe_trait, ty)
-            }
-            ItemMod(_) | ItemForeignMod(_) => PathMod(i.ident),
-            _ => PathName(i.ident)
-        });
+        let parent = self.parent;
+        self.parent = DUMMY_NODE_ID;
 
         let i = fold::noop_fold_item(i, self).expect_one("expected one item");
-        self.insert(i.id, NodeItem(i, item_path));
+        assert_eq!(self.parent, i.id);
 
         match i.node {
             ItemImpl(_, _, _, ref ms) => {
-                // clone is FIXME #2543
-                let p = @self.path.clone();
-                let impl_did = ast_util::local_def(i.id);
                 for &m in ms.iter() {
-                    self.insert(m.id, NodeMethod(m, impl_did, p));
+                    self.insert(m.id, EntryMethod(self.parent, m));
                 }
-
             }
             ItemEnum(ref enum_definition, _) => {
-                // clone is FIXME #2543
-                let p = @self.path.clone();
                 for &v in enum_definition.variants.iter() {
-                    self.insert(v.node.id, NodeVariant(v, i, p));
+                    self.insert(v.node.id, EntryVariant(self.parent, v));
                 }
             }
             ItemForeignMod(ref nm) => {
-                for nitem in nm.items.iter() {
-                    // Compute the visibility for this native item.
-                    let visibility = nitem.vis.inherit_from(i.vis);
-
-                    self.insert(nitem.id,
-                                // Anonymous extern mods go in the parent scope.
-                                NodeForeignItem(*nitem, nm.abis, visibility, item_path));
+                for &nitem in nm.items.iter() {
+                    self.insert(nitem.id, EntryForeignItem(self.parent, nitem));
                 }
             }
             ItemStruct(struct_def, _) => {
                 // If this is a tuple-like struct, register the constructor.
                 match struct_def.ctor_id {
-                    None => {}
                     Some(ctor_id) => {
-                        // clone is FIXME #2543
-                        let p = @self.path.clone();
-                        self.insert(ctor_id, NodeStructCtor(struct_def, i, p));
+                        self.insert(ctor_id, EntryStructCtor(self.parent,
+                                                             struct_def));
                     }
+                    None => {}
                 }
             }
             ItemTrait(_, ref traits, ref methods) => {
                 for t in traits.iter() {
-                    self.insert(t.ref_id, NodeItem(i, item_path));
+                    self.insert(t.ref_id, EntryItem(self.parent, i));
                 }
 
-                // clone is FIXME #2543
-                let p = @self.path.clone();
                 for tm in methods.iter() {
-                    let d_id = ast_util::local_def(i.id);
                     match *tm {
                         Required(ref m) => {
-                            self.insert(m.id, NodeTraitMethod(@(*tm).clone(), d_id, p));
+                            self.insert(m.id, EntryTraitMethod(self.parent,
+                                                               @(*tm).clone()));
                         }
                         Provided(m) => {
-                            self.insert(m.id, NodeTraitMethod(@Provided(m), d_id, p));
+                            self.insert(m.id, EntryTraitMethod(self.parent,
+                                                               @Provided(m)));
                         }
                     }
                 }
@@ -336,7 +467,8 @@ impl<F: FoldOps> Folder for Ctx<F> {
             _ => {}
         }
 
-        self.path.pop().unwrap();
+        self.parent = parent;
+        self.insert(i.id, EntryItem(self.parent, i));
 
         SmallVector::one(i)
     }
@@ -346,7 +478,7 @@ impl<F: FoldOps> Folder for Ctx<F> {
         match pat.node {
             PatIdent(..) => {
                 // Note: this is at least *potentially* a pattern...
-                self.insert(pat.id, NodeLocal(pat));
+                self.insert(pat.id, EntryLocal(self.parent, pat));
             }
             _ => {}
         }
@@ -357,14 +489,11 @@ impl<F: FoldOps> Folder for Ctx<F> {
     fn fold_expr(&mut self, expr: @Expr) -> @Expr {
         let expr = fold::noop_fold_expr(expr, self);
 
-        self.insert(expr.id, NodeExpr(expr));
+        self.insert(expr.id, EntryExpr(self.parent, expr));
 
         // Expressions which are or might be calls:
-        {
-            let r = expr.get_callee_id();
-            for callee_id in r.iter() {
-                self.insert(*callee_id, NodeCalleeScope(expr));
-            }
+        for callee_id in expr.get_callee_id().iter() {
+            self.insert(*callee_id, EntryCalleeScope(self.parent, expr));
         }
 
         expr
@@ -372,196 +501,173 @@ impl<F: FoldOps> Folder for Ctx<F> {
 
     fn fold_stmt(&mut self, stmt: &Stmt) -> SmallVector<@Stmt> {
         let stmt = fold::noop_fold_stmt(stmt, self).expect_one("expected one statement");
-        self.insert(ast_util::stmt_id(stmt), NodeStmt(stmt));
+        self.insert(ast_util::stmt_id(stmt), EntryStmt(self.parent, stmt));
         SmallVector::one(stmt)
     }
 
     fn fold_method(&mut self, m: @Method) -> @Method {
-        self.path.push(PathName(m.ident));
+        let parent = self.parent;
+        self.parent = DUMMY_NODE_ID;
         let m = fold::noop_fold_method(m, self);
-        self.path.pop();
+        assert_eq!(self.parent, m.id);
+        self.parent = parent;
         m
     }
 
     fn fold_fn_decl(&mut self, decl: &FnDecl) -> P<FnDecl> {
         let decl = fold::noop_fold_fn_decl(decl, self);
         for a in decl.inputs.iter() {
-            self.insert(a.id, NodeArg(a.pat));
+            self.insert(a.id, EntryArg(self.parent, a.pat));
         }
         decl
     }
 
     fn fold_block(&mut self, block: P<Block>) -> P<Block> {
         let block = fold::noop_fold_block(block, self);
-        self.insert(block.id, NodeBlock(block));
+        self.insert(block.id, EntryBlock(self.parent, block));
         block
     }
 }
 
-pub fn map_crate<F: 'static + FoldOps>(diag: @SpanHandler, c: Crate,
-                                       fold_ops: F) -> (Crate, Map) {
-    let mut cx = Ctx {
-        map: Map { map: @RefCell::new(SmallIntMap::new()) },
-        path: ~[],
-        diag: diag,
-        fold_ops: fold_ops
+pub fn map_crate<F: FoldOps>(krate: Crate, fold_ops: F) -> (Crate, Map) {
+    let map = Map { map: RefCell::new(~[]) };
+    let krate = {
+        let mut cx = Ctx {
+            map: &map,
+            parent: CRATE_NODE_ID,
+            fold_ops: fold_ops
+        };
+        cx.insert(CRATE_NODE_ID, RootCrate);
+        cx.fold_crate(krate)
     };
-    let krate = cx.fold_crate(c);
 
     if log_enabled!(logging::DEBUG) {
-        let map = cx.map.map.borrow();
-        // this only makes sense for ordered stores; note the
+        let map = map.map.borrow();
+        // This only makes sense for ordered stores; note the
         // enumerate to count the number of entries.
-        let (entries_less_1, (largest_id, _)) =
-            map.get().iter().enumerate().last().expect("AST map was empty after folding?");
+        let (entries_less_1, _) = map.get().iter().filter(|&x| {
+            match *x {
+                NotPresent => false,
+                _ => true
+            }
+        }).enumerate().last().expect("AST map was empty after folding?");
 
         let entries = entries_less_1 + 1;
-        let vector_length = largest_id + 1;
+        let vector_length = map.get().len();
         debug!("The AST map has {} entries with a maximum of {}: occupancy {:.1}%",
               entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
     }
 
-    (krate, cx.map)
+    (krate, map)
 }
 
 // Used for items loaded from external crate that are being inlined into this
 // crate.  The `path` should be the path to the item but should not include
 // the item itself.
-pub fn map_decoded_item<F: 'static + FoldOps>(diag: @SpanHandler,
-                                              map: Map,
-                                              path: Path,
-                                              fold_ops: F,
-                                              fold_ii: |&mut Ctx<F>| -> InlinedItem)
-                                              -> InlinedItem {
-    // I believe it is ok for the local IDs of inlined items from other crates
-    // to overlap with the local ids from this crate, so just generate the ids
-    // starting from 0.
+pub fn map_decoded_item<F: FoldOps>(map: &Map,
+                                    path: ~[PathElem],
+                                    fold_ops: F,
+                                    fold: |&mut Ctx<F>| -> InlinedItem)
+                                    -> InlinedItem {
     let mut cx = Ctx {
         map: map,
-        path: path.clone(),
-        diag: diag,
+        parent: DUMMY_NODE_ID,
         fold_ops: fold_ops
     };
 
-    let ii = fold_ii(&mut cx);
+    // Generate a NodeId for the RootInlinedParent inserted below.
+    cx.new_id(DUMMY_NODE_ID);
 
     // Methods get added to the AST map when their impl is visited.  Since we
     // don't decode and instantiate the impl, but just the method, we have to
     // add it to the table now. Likewise with foreign items.
+    let mut def_id = DefId { krate: LOCAL_CRATE, node: DUMMY_NODE_ID };
+    let ii = fold(&mut cx);
     match ii {
-        IIItem(..) => {} // fallthrough
-        IIForeign(i) => {
-            cx.insert(i.id, NodeForeignItem(i,
-                                            AbiSet::Intrinsic(),
-                                            i.vis,    // Wrong but OK
-                                            @path));
-        }
+        IIItem(_) => {}
         IIMethod(impl_did, is_provided, m) => {
             let entry = if is_provided {
-                NodeTraitMethod(@Provided(m), impl_did, @path)
+                EntryTraitMethod(cx.parent, @Provided(m))
             } else {
-                NodeMethod(m, impl_did, @path)
+                EntryMethod(cx.parent, m)
             };
             cx.insert(m.id, entry);
+            def_id = impl_did;
+        }
+        IIForeign(i) => {
+            cx.insert(i.id, EntryForeignItem(cx.parent, i));
         }
     }
 
+    cx.insert(cx.parent, RootInlinedParent(P(InlinedParent {
+        path: path,
+        def_id: def_id
+    })));
+
     ii
 }
 
-pub fn node_id_to_str(map: Map, id: NodeId, itr: @IdentInterner) -> ~str {
+fn node_id_to_str(map: &Map, id: NodeId) -> ~str {
     match map.find(id) {
-      None => {
-        format!("unknown node (id={})", id)
-      }
-      Some(NodeItem(item, path)) => {
-        let path_str = path_ident_to_str(path, item.ident, itr);
-        let item_str = match item.node {
-            ItemStatic(..) => ~"static",
-            ItemFn(..) => ~"fn",
-            ItemMod(..) => ~"mod",
-            ItemForeignMod(..) => ~"foreign mod",
-            ItemTy(..) => ~"ty",
-            ItemEnum(..) => ~"enum",
-            ItemStruct(..) => ~"struct",
-            ItemTrait(..) => ~"trait",
-            ItemImpl(..) => ~"impl",
-            ItemMac(..) => ~"macro"
-        };
-        format!("{} {} (id={})", item_str, path_str, id)
-      }
-      Some(NodeForeignItem(item, abi, _, path)) => {
-        format!("foreign item {} with abi {:?} (id={})",
-             path_ident_to_str(path, item.ident, itr), abi, id)
-      }
-      Some(NodeMethod(m, _, path)) => {
-        let name = itr.get(m.ident.name);
-        format!("method {} in {} (id={})",
-             name.as_slice(), path_to_str(*path, itr), id)
-      }
-      Some(NodeTraitMethod(ref tm, _, path)) => {
-        let m = ast_util::trait_method_to_ty_method(&**tm);
-        let name = itr.get(m.ident.name);
-        format!("method {} in {} (id={})",
-             name.as_slice(), path_to_str(*path, itr), id)
-      }
-      Some(NodeVariant(ref variant, _, path)) => {
-        let name = itr.get(variant.node.name.name);
-        format!("variant {} in {} (id={})",
-             name.as_slice(),
-             path_to_str(*path, itr), id)
-      }
-      Some(NodeExpr(expr)) => {
-        format!("expr {} (id={})", pprust::expr_to_str(expr, itr), id)
-      }
-      Some(NodeCalleeScope(expr)) => {
-        format!("callee_scope {} (id={})", pprust::expr_to_str(expr, itr), id)
-      }
-      Some(NodeStmt(stmt)) => {
-        format!("stmt {} (id={})",
-             pprust::stmt_to_str(stmt, itr), id)
-      }
-      Some(NodeArg(pat)) => {
-        format!("arg {} (id={})", pprust::pat_to_str(pat, itr), id)
-      }
-      Some(NodeLocal(pat)) => {
-        format!("local {} (id={})", pprust::pat_to_str(pat, itr), id)
-      }
-      Some(NodeBlock(block)) => {
-        format!("block {} (id={})", pprust::block_to_str(block, itr), id)
-      }
-      Some(NodeStructCtor(_, _, path)) => {
-        format!("struct_ctor {} (id={})", path_to_str(*path, itr), id)
-      }
-    }
-}
-
-pub fn node_item_query<Result>(items: Map, id: NodeId, query: |@Item| -> Result, error_msg: ~str)
-                       -> Result {
-    match items.find(id) {
-        Some(NodeItem(it, _)) => query(it),
-        _ => fail!("{}", error_msg)
-    }
-}
-
-pub fn node_span(items: Map, id: ast::NodeId) -> Span {
-    match items.find(id) {
-        Some(NodeItem(item, _)) => item.span,
-        Some(NodeForeignItem(foreign_item, _, _, _)) => foreign_item.span,
-        Some(NodeTraitMethod(trait_method, _, _)) => {
-            match *trait_method {
-                Required(ref type_method) => type_method.span,
-                Provided(ref method) => method.span,
-            }
+        Some(NodeItem(item)) => {
+            let path_str = map.path_to_str_with_ident(id, item.ident);
+            let item_str = match item.node {
+                ItemStatic(..) => "static",
+                ItemFn(..) => "fn",
+                ItemMod(..) => "mod",
+                ItemForeignMod(..) => "foreign mod",
+                ItemTy(..) => "ty",
+                ItemEnum(..) => "enum",
+                ItemStruct(..) => "struct",
+                ItemTrait(..) => "trait",
+                ItemImpl(..) => "impl",
+                ItemMac(..) => "macro"
+            };
+            format!("{} {} (id={})", item_str, path_str, id)
+        }
+        Some(NodeForeignItem(item)) => {
+            let path_str = map.path_to_str_with_ident(id, item.ident);
+            format!("foreign item {} (id={})", path_str, id)
+        }
+        Some(NodeMethod(m)) => {
+            format!("method {} in {} (id={})",
+                    token::get_ident(m.ident),
+                    map.path_to_str(id), id)
+        }
+        Some(NodeTraitMethod(ref tm)) => {
+            let m = ast_util::trait_method_to_ty_method(&**tm);
+            format!("method {} in {} (id={})",
+                    token::get_ident(m.ident),
+                    map.path_to_str(id), id)
+        }
+        Some(NodeVariant(ref variant)) => {
+            format!("variant {} in {} (id={})",
+                    token::get_ident(variant.node.name),
+                    map.path_to_str(id), id)
+        }
+        Some(NodeExpr(expr)) => {
+            format!("expr {} (id={})", pprust::expr_to_str(expr), id)
+        }
+        Some(NodeCalleeScope(expr)) => {
+            format!("callee_scope {} (id={})", pprust::expr_to_str(expr), id)
+        }
+        Some(NodeStmt(stmt)) => {
+            format!("stmt {} (id={})", pprust::stmt_to_str(stmt), id)
+        }
+        Some(NodeArg(pat)) => {
+            format!("arg {} (id={})", pprust::pat_to_str(pat), id)
+        }
+        Some(NodeLocal(pat)) => {
+            format!("local {} (id={})", pprust::pat_to_str(pat), id)
+        }
+        Some(NodeBlock(block)) => {
+            format!("block {} (id={})", pprust::block_to_str(block), id)
+        }
+        Some(NodeStructCtor(_)) => {
+            format!("struct_ctor {} (id={})", map.path_to_str(id), id)
+        }
+        None => {
+            format!("unknown node (id={})", id)
         }
-        Some(NodeMethod(method, _, _)) => method.span,
-        Some(NodeVariant(variant, _, _)) => variant.span,
-        Some(NodeExpr(expr)) => expr.span,
-        Some(NodeStmt(stmt)) => stmt.span,
-        Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
-        Some(NodeBlock(block)) => block.span,
-        Some(NodeStructCtor(_, item, _)) => item.span,
-        Some(NodeCalleeScope(expr)) => expr.span,
-        None => fail!("node_span: could not find id {}", id),
     }
 }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 56f690f0e2b..790f3927352 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -14,6 +14,7 @@ use ast_util;
 use codemap::Span;
 use opt_vec;
 use parse::token;
+use print::pprust;
 use visit::Visitor;
 use visit;
 
@@ -26,8 +27,7 @@ use std::local_data;
 pub fn path_name_i(idents: &[Ident]) -> ~str {
     // FIXME: Bad copies (#2543 -- same for everything else that says "bad")
     idents.map(|i| {
-        let string = token::get_ident(i.name);
-        string.get().to_str()
+        token::get_ident(*i).get().to_str()
     }).connect("::")
 }
 
@@ -246,6 +246,23 @@ pub fn unguarded_pat(a: &Arm) -> Option<~[@Pat]> {
     }
 }
 
+/// Generate a "pretty" name for an `impl` from its type and trait.
+/// This is designed so that symbols of `impl`'d methods give some
+/// hint of where they came from, (previously they would all just be
+/// listed as `__extensions__::method_name::hash`, with no indication
+/// of the type).
+pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
+    let mut pretty = pprust::ty_to_str(ty);
+    match *trait_ref {
+        Some(ref trait_ref) => {
+            pretty.push_char('.');
+            pretty.push_str(pprust::path_to_str(&trait_ref.path));
+        }
+        None => {}
+    }
+    token::gensym_ident(pretty)
+}
+
 pub fn public_methods(ms: ~[@Method]) -> ~[@Method] {
     ms.move_iter().filter(|m| {
         match m.vis {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 7ac66ecaa37..0900eca1ad1 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -440,8 +440,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt,
         match tts[0] {
             ast::TTTok(_, token::LIT_STR(ident))
             | ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => {
-                let interned_str = token::get_ident(ident.name);
-                return Some(interned_str.get().to_str())
+                return Some(token::get_ident(ident).get().to_str())
             }
             _ => cx.span_err(sp, format!("{} requires a string.", name)),
         }
diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs
index e0d53add648..15e9d31daa0 100644
--- a/src/libsyntax/ext/concat_idents.rs
+++ b/src/libsyntax/ext/concat_idents.rs
@@ -31,8 +31,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
         } else {
             match *e {
                 ast::TTTok(_, token::IDENT(ident,_)) => {
-                    let interned_str = token::get_ident(ident.name);
-                    res_str.push_str(interned_str.get())
+                    res_str.push_str(token::get_ident(ident).get())
                 }
                 _ => {
                     cx.span_err(sp, "concat_idents! requires ident args.");
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index fdf1ef17d53..c1a6b41db9d 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -86,8 +86,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                 decoder,
                                 cx.ident_of("read_struct"),
                                 ~[
-                cx.expr_str(trait_span,
-                            token::get_ident(substr.type_ident.name)),
+                cx.expr_str(trait_span, token::get_ident(substr.type_ident)),
                 cx.expr_uint(trait_span, nfields),
                 cx.lambda_expr_1(trait_span, result, blkarg)
             ])
@@ -100,8 +99,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             let rvariant_arg = cx.ident_of("read_enum_variant_arg");
 
             for (i, &(name, v_span, ref parts)) in fields.iter().enumerate() {
-                variants.push(cx.expr_str(v_span,
-                                          token::get_ident(name.name)));
+                variants.push(cx.expr_str(v_span, token::get_ident(name)));
 
                 let decoded = decode_static_fields(cx,
                                                    v_span,
@@ -130,8 +128,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                 decoder,
                                 cx.ident_of("read_enum"),
                                 ~[
-                cx.expr_str(trait_span,
-                            token::get_ident(substr.type_ident.name)),
+                cx.expr_str(trait_span, token::get_ident(substr.type_ident)),
                 cx.lambda_expr_1(trait_span, result, blkarg)
             ])
         }
@@ -166,7 +163,7 @@ fn decode_static_fields(cx: &mut ExtCtxt,
         Named(ref fields) => {
             // use the field's span to get nicer error messages.
             let fields = fields.iter().enumerate().map(|(i, &(name, span))| {
-                let arg = getarg(cx, span, token::get_ident(name.name), i);
+                let arg = getarg(cx, span, token::get_ident(name), i);
                 cx.field_imm(span, name, arg)
             }).collect();
             cx.expr_struct_ident(trait_span, outer_pat_ident, fields)
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 43edf6006b4..f35cdab972c 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -132,7 +132,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                     ..
                 }) in fields.iter().enumerate() {
                 let name = match name {
-                    Some(id) => token::get_ident(id.name),
+                    Some(id) => token::get_ident(id),
                     None => {
                         token::intern_and_get_ident(format!("_field{}", i))
                     }
@@ -152,8 +152,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                 encoder,
                                 cx.ident_of("emit_struct"),
                                 ~[
-                cx.expr_str(trait_span,
-                            token::get_ident(substr.type_ident.name)),
+                cx.expr_str(trait_span, token::get_ident(substr.type_ident)),
                 cx.expr_uint(trait_span, fields.len()),
                 blk
             ])
@@ -179,8 +178,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             }
 
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
-            let name = cx.expr_str(trait_span,
-                                   token::get_ident(variant.node.name.name));
+            let name = cx.expr_str(trait_span, token::get_ident(variant.node.name));
             let call = cx.expr_method_call(trait_span, blkencoder,
                                            cx.ident_of("emit_enum_variant"),
                                            ~[name,
@@ -192,8 +190,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                                           encoder,
                                           cx.ident_of("emit_enum"),
                                           ~[
-                cx.expr_str(trait_span,
-                            token::get_ident(substr.type_ident.name)),
+                cx.expr_str(trait_span, token::get_ident(substr.type_ident)),
                 blk
             ]);
             cx.expr_block(cx.block(trait_span, ~[me], Some(ret)))
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 9d290c93c64..a9fdb15fdd4 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -178,7 +178,7 @@ StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span
 
 use ast;
 use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
-
+use ast_util;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
 use codemap;
@@ -405,11 +405,13 @@ impl<'a> TraitDef<'a> {
                                ast::LitStr(token::intern_and_get_ident(
                                                "Automatically derived."),
                                            ast::CookedStr)));
+        let opt_trait_ref = Some(trait_ref);
+        let ident = ast_util::impl_pretty_name(&opt_trait_ref, self_type);
         cx.item(
             self.span,
-            ::parse::token::special_idents::clownshoes_extensions,
+            ident,
             ~[doc_attr],
-            ast::ItemImpl(trait_generics, Some(trait_ref),
+            ast::ItemImpl(trait_generics, opt_trait_ref,
                           self_type, methods.map(|x| *x)))
     }
 
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
index e2d507f3035..68fad460a34 100644
--- a/src/libsyntax/ext/deriving/show.rs
+++ b/src/libsyntax/ext/deriving/show.rs
@@ -67,7 +67,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
         }
     };
 
-    let mut format_string = token::get_ident(name.name).get().to_owned();
+    let mut format_string = token::get_ident(name).get().to_owned();
     // the internal fields we're actually formatting
     let mut exprs = ~[];
 
@@ -99,7 +99,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
                 for (i, field) in fields.iter().enumerate() {
                     if i != 0 { format_string.push_str(","); }
 
-                    let name = token::get_ident(field.name.unwrap().name);
+                    let name = token::get_ident(field.name.unwrap());
                     format_string.push_str(" ");
                     format_string.push_str(name.get());
                     format_string.push_str(": {}");
diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs
index e5145fb15f7..8453d0f0312 100644
--- a/src/libsyntax/ext/deriving/to_str.rs
+++ b/src/libsyntax/ext/deriving/to_str.rs
@@ -57,10 +57,10 @@ fn to_str_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure)
                 name: ast::Ident,
                 fields: &[FieldInfo]| {
         if fields.len() == 0 {
-            cx.expr_str_uniq(span, token::get_ident(name.name))
+            cx.expr_str_uniq(span, token::get_ident(name))
         } else {
             let buf = cx.ident_of("buf");
-            let interned_str = token::get_ident(name.name);
+            let interned_str = token::get_ident(name);
             let start =
                 token::intern_and_get_ident(interned_str.get() + start);
             let init = cx.expr_str_uniq(span, start);
@@ -81,7 +81,7 @@ fn to_str_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure)
                     match name {
                         None => {}
                         Some(id) => {
-                            let interned_id = token::get_ident(id.name);
+                            let interned_id = token::get_ident(id);
                             let name = interned_id.get() + ": ";
                             push(cx.expr_str(span,
                                              token::intern_and_get_ident(name)));
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index d96fc27f3dd..380178191b7 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -54,8 +54,8 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                         // let compilation continue
                         return e;
                     }
-                    let extname = &pth.segments[0].identifier;
-                    let extnamestr = token::get_ident(extname.name);
+                    let extname = pth.segments[0].identifier;
+                    let extnamestr = token::get_ident(extname);
                     // leaving explicit deref here to highlight unbox op:
                     let marked_after = match fld.extsbox.find(&extname.name) {
                         None => {
@@ -297,26 +297,25 @@ pub fn expand_item_mac(it: @ast::Item, fld: &mut MacroExpander)
         _ => fld.cx.span_bug(it.span, "invalid item macro invocation")
     };
 
-    let extname = &pth.segments[0].identifier;
-    let extnamestr = token::get_ident(extname.name);
+    let extname = pth.segments[0].identifier;
+    let extnamestr = token::get_ident(extname);
     let fm = fresh_mark();
     let expanded = match fld.extsbox.find(&extname.name) {
         None => {
             fld.cx.span_err(pth.span,
                             format!("macro undefined: '{}!'",
-                                    extnamestr.get()));
+                                    extnamestr));
             // let compilation continue
             return SmallVector::zero();
         }
 
         Some(&NormalTT(ref expander, span)) => {
             if it.ident.name != parse::token::special_idents::invalid.name {
-                let string = token::get_ident(it.ident.name);
                 fld.cx.span_err(pth.span,
                                 format!("macro {}! expects no ident argument, \
                                         given '{}'",
-                                        extnamestr.get(),
-                                        string.get()));
+                                        extnamestr,
+                                        token::get_ident(it.ident)));
                 return SmallVector::zero();
             }
             fld.cx.bt_push(ExpnInfo {
@@ -418,13 +417,10 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
     let MacroCrate { lib, cnum } = fld.cx.loader.load_crate(krate);
 
     let crate_name = match krate.node {
-        ast::ViewItemExternMod(ref name, _, _) => {
-            let string = token::get_ident(name.name);
-            string.get().to_str()
-        },
-        _ => unreachable!(),
+        ast::ViewItemExternMod(name, _, _) => name,
+        _ => unreachable!()
     };
-    let name = format!("<{} macros>", crate_name);
+    let name = format!("<{} macros>", token::get_ident(crate_name));
 
     let exported_macros = fld.cx.loader.get_exported_macros(cnum);
     for source in exported_macros.iter() {
@@ -496,12 +492,11 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
         fld.cx.span_err(pth.span, "expected macro name without module separators");
         return SmallVector::zero();
     }
-    let extname = &pth.segments[0].identifier;
-    let extnamestr = token::get_ident(extname.name);
+    let extname = pth.segments[0].identifier;
+    let extnamestr = token::get_ident(extname);
     let marked_after = match fld.extsbox.find(&extname.name) {
         None => {
-            fld.cx.span_err(pth.span, format!("macro undefined: '{}'",
-                                              extnamestr.get()));
+            fld.cx.span_err(pth.span, format!("macro undefined: '{}'", extnamestr));
             return SmallVector::zero();
         }
 
@@ -535,7 +530,7 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
                 _ => {
                     fld.cx.span_err(pth.span,
                                     format!("non-stmt macro in stmt pos: {}",
-                                            extnamestr.get()));
+                                            extnamestr));
                     return SmallVector::zero();
                 }
             };
@@ -545,7 +540,7 @@ pub fn expand_stmt(s: &Stmt, fld: &mut MacroExpander) -> SmallVector<@Stmt> {
 
         _ => {
             fld.cx.span_err(pth.span, format!("'{}' is not a tt-style macro",
-                                              extnamestr.get()));
+                                              extnamestr));
             return SmallVector::zero();
         }
     };
@@ -1186,9 +1181,7 @@ mod test {
                         println!("uh oh, matches but shouldn't:");
                         println!("varref: {:?}",varref);
                         // good lord, you can't make a path with 0 segments, can you?
-                        let string = token::get_ident(varref.segments[0]
-                                                            .identifier
-                                                            .name);
+                        let string = token::get_ident(varref.segments[0].identifier);
                         println!("varref's first segment's uint: {}, and string: \"{}\"",
                                  varref.segments[0].identifier.name,
                                  string.get());
@@ -1213,10 +1206,7 @@ foo_module!()
         let bindings = name_finder.ident_accumulator;
 
         let cxbinds: ~[&ast::Ident] =
-            bindings.iter().filter(|b| {
-                let string = token::get_ident(b.name);
-                "xx" == string.get()
-            }).collect();
+            bindings.iter().filter(|b| "xx" == token::get_ident(**b).get()).collect();
         let cxbind = match cxbinds {
             [b] => b,
             _ => fail!("expected just one binding for ext_cx")
@@ -1228,12 +1218,9 @@ foo_module!()
         let varrefs = path_finder.path_accumulator;
 
         // the xx binding should bind all of the xx varrefs:
-        for (idx,v) in varrefs.iter().filter(|p|{
+        for (idx,v) in varrefs.iter().filter(|p| {
             p.segments.len() == 1
-            && {
-                let string = token::get_ident(p.segments[0].identifier.name);
-                "xx" == string.get()
-            }
+            && "xx" == token::get_ident(p.segments[0].identifier).get()
         }).enumerate() {
             if mtwt_resolve(v.segments[0].identifier) != resolved_binding {
                 println!("uh oh, xx binding didn't match xx varref:");
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 3eacce5eb1d..01d348595b8 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -112,7 +112,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span,
                     return (extra, None);
                 }
             };
-            let interned_name = token::get_ident(ident.name);
+            let interned_name = token::get_ident(ident);
             let name = interned_name.get();
             p.expect(&token::EQ);
             let e = p.parse_expr();
diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs
index 947e8271f88..5ee4084d207 100644
--- a/src/libsyntax/ext/log_syntax.rs
+++ b/src/libsyntax/ext/log_syntax.rs
@@ -13,7 +13,6 @@ use codemap;
 use ext::base::*;
 use ext::base;
 use print;
-use parse::token::{get_ident_interner};
 
 pub fn expand_syntax_ext(cx: &mut ExtCtxt,
                          sp: codemap::Span,
@@ -21,10 +20,7 @@ pub fn expand_syntax_ext(cx: &mut ExtCtxt,
                       -> base::MacResult {
 
     cx.print_backtrace();
-    println!("{}",
-        print::pprust::tt_to_str(
-            &ast::TTDelim(@tt.to_owned()),
-            get_ident_interner()));
+    println!("{}", print::pprust::tt_to_str(&ast::TTDelim(@tt.to_owned())));
 
     //trivial expression
     MRExpr(@ast::Expr {
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index e9832209904..35a5cbd235a 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -71,14 +71,13 @@ pub mod rt {
 
     impl ToSource for ast::Ident {
         fn to_source(&self) -> ~str {
-            let this = get_ident(self.name);
-            this.get().to_owned()
+            get_ident(*self).get().to_str()
         }
     }
 
     impl ToSource for @ast::Item {
         fn to_source(&self) -> ~str {
-            pprust::item_to_str(*self, get_ident_interner())
+            pprust::item_to_str(*self)
         }
     }
 
@@ -90,7 +89,7 @@ pub mod rt {
 
     impl ToSource for ast::Ty {
         fn to_source(&self) -> ~str {
-            pprust::ty_to_str(self, get_ident_interner())
+            pprust::ty_to_str(self)
         }
     }
 
@@ -102,19 +101,19 @@ pub mod rt {
 
     impl ToSource for Generics {
         fn to_source(&self) -> ~str {
-            pprust::generics_to_str(self, get_ident_interner())
+            pprust::generics_to_str(self)
         }
     }
 
     impl ToSource for @ast::Expr {
         fn to_source(&self) -> ~str {
-            pprust::expr_to_str(*self, get_ident_interner())
+            pprust::expr_to_str(*self)
         }
     }
 
     impl ToSource for ast::Block {
         fn to_source(&self) -> ~str {
-            pprust::block_to_str(self, get_ident_interner())
+            pprust::block_to_str(self)
         }
     }
 
@@ -349,7 +348,7 @@ fn id_ext(str: &str) -> ast::Ident {
 
 // Lift an ident to the expr that evaluates to that ident.
 fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> @ast::Expr {
-    let e_str = cx.expr_str(sp, token::get_ident(ident.name));
+    let e_str = cx.expr_str(sp, token::get_ident(ident));
     cx.expr_method_call(sp,
                         cx.expr_ident(sp, id_ext("ext_cx")),
                         id_ext("ident_of"),
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 52010b39a54..150f054b2af 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -16,7 +16,6 @@ use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
 use parse;
-use parse::token::get_ident_interner;
 use parse::token;
 use print::pprust;
 
@@ -64,7 +63,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
 pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     -> base::MacResult {
-    let s = pprust::tts_to_str(tts, get_ident_interner());
+    let s = pprust::tts_to_str(tts);
     base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(s)))
 }
 
@@ -72,10 +71,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     -> base::MacResult {
     base::check_zero_tts(cx, sp, tts, "module_path!");
     let string = cx.mod_path()
-                   .map(|x| {
-                        let interned_str = token::get_ident(x.name);
-                        interned_str.get().to_str()
-                    })
+                   .map(|x| token::get_ident(*x).get().to_str())
                    .connect("::");
     base::MRExpr(cx.expr_str(sp, token::intern_and_get_ident(string)))
 }
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 92bc204e2c1..c2d005da74e 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -18,7 +18,7 @@ use parse::lexer::*; //resolve bug?
 use parse::ParseSess;
 use parse::attr::ParserAttr;
 use parse::parser::{LifetimeAndTypesWithoutColons, Parser};
-use parse::token::{Token, EOF, to_str, Nonterminal, get_ident_interner};
+use parse::token::{Token, EOF, Nonterminal};
 use parse::token;
 
 use std::hashmap::HashMap;
@@ -180,14 +180,15 @@ pub fn nameize(p_s: @ParseSess, ms: &[Matcher], res: &[@NamedMatch])
             };
           }
           codemap::Spanned {
-                node: MatchNonterminal(ref bind_name, _, idx), span: sp
+                node: MatchNonterminal(bind_name, _, idx),
+                span
           } => {
-            if ret_val.contains_key(bind_name) {
-                let string = token::get_ident(bind_name.name);
+            if ret_val.contains_key(&bind_name) {
+                let string = token::get_ident(bind_name);
                 p_s.span_diagnostic
-                   .span_fatal(sp, "duplicated bind name: " + string.get())
+                   .span_fatal(span, "duplicated bind name: " + string.get())
             }
-            ret_val.insert(*bind_name, res[idx]);
+            ret_val.insert(bind_name, res[idx]);
           }
         }
     }
@@ -364,12 +365,10 @@ pub fn parse<R: Reader>(sess: @ParseSess,
                 || bb_eis.len() > 1u {
                 let nts = bb_eis.map(|ei| {
                     match ei.elts[ei.idx].node {
-                      MatchNonterminal(ref bind,ref name,_) => {
-                        let bind_string = token::get_ident(bind.name);
-                        let name_string = token::get_ident(name.name);
+                      MatchNonterminal(bind, name, _) => {
                         format!("{} ('{}')",
-                                name_string.get(),
-                                bind_string.get())
+                                token::get_ident(name),
+                                token::get_ident(bind))
                       }
                       _ => fail!()
                     } }).connect(" or ");
@@ -379,7 +378,7 @@ pub fn parse<R: Reader>(sess: @ParseSess,
                     nts, next_eis.len()));
             } else if bb_eis.len() == 0u && next_eis.len() == 0u {
                 return Failure(sp, format!("no rules expected the token `{}`",
-                            to_str(get_ident_interner(), &tok)));
+                            token::to_str(&tok)));
             } else if next_eis.len() > 0u {
                 /* Now process the next token */
                 while next_eis.len() > 0u {
@@ -391,8 +390,8 @@ pub fn parse<R: Reader>(sess: @ParseSess,
 
                 let mut ei = bb_eis.pop().unwrap();
                 match ei.elts[ei.idx].node {
-                  MatchNonterminal(_, ref name, idx) => {
-                    let name_string = token::get_ident(name.name);
+                  MatchNonterminal(_, name, idx) => {
+                    let name_string = token::get_ident(name);
                     ei.matches[idx].push(@MatchedNonterminal(
                         parse_nt(&mut rust_parser, name_string.get())));
                     ei.idx += 1u;
@@ -426,7 +425,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
       "ident" => match p.token {
         token::IDENT(sn,b) => { p.bump(); token::NtIdent(~sn,b) }
         _ => {
-            let token_str = token::to_str(get_ident_interner(), &p.token);
+            let token_str = token::to_str(&p.token);
             p.fatal(~"expected ident, found " + token_str)
         }
       },
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index e196bdccfe3..45fe24ebf68 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -21,7 +21,7 @@ use ext::tt::macro_parser::{parse, parse_or_else};
 use parse::lexer::new_tt_reader;
 use parse::parser::Parser;
 use parse::attr::ParserAttr;
-use parse::token::{get_ident_interner, special_idents, gensym_ident};
+use parse::token::{special_idents, gensym_ident};
 use parse::token::{FAT_ARROW, SEMI, NtMatchers, NtTT, EOF};
 use parse::token;
 use print;
@@ -113,11 +113,9 @@ fn generic_extension(cx: &ExtCtxt,
                      rhses: &[@NamedMatch])
                      -> MacResult {
     if cx.trace_macros() {
-        let interned_name = token::get_ident(name.name);
         println!("{}! \\{ {} \\}",
-                 interned_name.get(),
-                 print::pprust::tt_to_str(&TTDelim(@arg.to_owned()),
-                                          get_ident_interner()));
+                 token::get_ident(name),
+                 print::pprust::tt_to_str(&TTDelim(@arg.to_owned())));
     }
 
     // Which arm's failure should we report? (the one furthest along)
@@ -231,7 +229,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
     };
 
     return MRDef(MacroDef {
-        name: token::get_ident(name.name).get().to_str(),
+        name: token::get_ident(name).get().to_str(),
         ext: NormalTT(exp, Some(sp))
     });
 }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index fccbc57f12c..fb2aae9b8c1 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -19,7 +19,6 @@ use parse::lexer::TokenAndSpan;
 
 use std::cell::{Cell, RefCell};
 use std::hashmap::HashMap;
-use std::option;
 
 ///an unzipping of `TokenTree`s
 struct TtFrame {
@@ -57,7 +56,7 @@ pub fn new_tt_reader(sp_diag: @SpanHandler,
             idx: Cell::new(0u),
             dotdotdoted: false,
             sep: None,
-            up: option::None
+            up: None
         }),
         interpolations: match interp { /* just a convienience */
             None => RefCell::new(HashMap::new()),
@@ -122,10 +121,9 @@ fn lookup_cur_matched(r: &TtReader, name: Ident) -> @NamedMatch {
     match matched_opt {
         Some(s) => lookup_cur_matched_by_matched(r, s),
         None => {
-            let name_string = token::get_ident(name.name);
             r.sp_diag.span_fatal(r.cur_span.get(),
                                  format!("unknown macro variable `{}`",
-                                         name_string.get()));
+                                         token::get_ident(name)));
         }
     }
 }
@@ -141,16 +139,16 @@ fn lis_merge(lhs: LockstepIterSize, rhs: LockstepIterSize) -> LockstepIterSize {
     match lhs {
         LisUnconstrained => rhs.clone(),
         LisContradiction(_) => lhs.clone(),
-        LisConstraint(l_len, ref l_id) => match rhs {
+        LisConstraint(l_len, l_id) => match rhs {
             LisUnconstrained => lhs.clone(),
             LisContradiction(_) => rhs.clone(),
             LisConstraint(r_len, _) if l_len == r_len => lhs.clone(),
-            LisConstraint(r_len, ref r_id) => {
-                let l_n = token::get_ident(l_id.name);
-                let r_n = token::get_ident(r_id.name);
+            LisConstraint(r_len, r_id) => {
+                let l_n = token::get_ident(l_id);
+                let r_n = token::get_ident(r_id);
                 LisContradiction(format!("inconsistent lockstep iteration: \
                                           '{}' has {} items, but '{}' has {}",
-                                          l_n.get(), l_len, r_n.get(), r_len))
+                                          l_n, l_len, r_n, r_len))
             }
         }
     }
@@ -240,7 +238,7 @@ pub fn tt_next_token(r: &TtReader) -> TokenAndSpan {
                 idx: Cell::new(0u),
                 dotdotdoted: false,
                 sep: None,
-                up: option::Some(r.stack.get())
+                up: Some(r.stack.get())
             });
             // if this could be 0-length, we'd need to potentially recur here
           }
@@ -314,11 +312,10 @@ pub fn tt_next_token(r: &TtReader) -> TokenAndSpan {
                 return ret_val;
               }
               MatchedSeq(..) => {
-                let string = token::get_ident(ident.name);
                 r.sp_diag.span_fatal(
                     r.cur_span.get(), /* blame the macro writer */
                     format!("variable '{}' is still repeating at this depth",
-                            string.get()));
+                            token::get_ident(ident)));
               }
             }
           }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 1b14bd72382..6fb66a66f18 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -10,6 +10,7 @@
 
 use ast::*;
 use ast;
+use ast_util;
 use codemap::{respan, Span, Spanned};
 use parse::token;
 use opt_vec::OptVec;
@@ -261,10 +262,10 @@ pub trait Folder {
 
     fn fold_local(&mut self, l: @Local) -> @Local {
         @Local {
+            id: self.new_id(l.id), // Needs to be first, for ast_map.
             ty: self.fold_ty(l.ty),
             pat: self.fold_pat(l.pat),
             init: l.init.map(|e| self.fold_expr(e)),
-            id: self.new_id(l.id),
             span: self.new_span(l.span),
         }
     }
@@ -344,9 +345,9 @@ fn fold_attribute_<T: Folder>(at: Attribute, fld: &mut T) -> Attribute {
 //used in noop_fold_foreign_item and noop_fold_fn_decl
 fn fold_arg_<T: Folder>(a: &Arg, fld: &mut T) -> Arg {
     Arg {
+        id: fld.new_id(a.id), // Needs to be first, for ast_map.
         ty: fld.fold_ty(a.ty),
         pat: fld.fold_pat(a.pat),
-        id: fld.new_id(a.id),
     }
 }
 
@@ -514,10 +515,10 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
     let view_items = b.view_items.map(|x| folder.fold_view_item(x));
     let stmts = b.stmts.iter().flat_map(|s| folder.fold_stmt(*s).move_iter()).collect();
     P(Block {
+        id: folder.new_id(b.id), // Needs to be first, for ast_map.
         view_items: view_items,
         stmts: stmts,
         expr: b.expr.map(|x| folder.fold_expr(x)),
-        id: folder.new_id(b.id),
         rules: b.rules,
         span: folder.new_span(b.span),
     })
@@ -579,13 +580,13 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
 
 pub fn noop_fold_type_method<T: Folder>(m: &TypeMethod, fld: &mut T) -> TypeMethod {
     TypeMethod {
+        id: fld.new_id(m.id), // Needs to be first, for ast_map.
         ident: fld.fold_ident(m.ident),
         attrs: m.attrs.map(|a| fold_attribute_(*a, fld)),
         purity: m.purity,
         decl: fld.fold_fn_decl(m.decl),
         generics: fold_generics(&m.generics, fld),
         explicit_self: fld.fold_explicit_self(&m.explicit_self),
-        id: fld.new_id(m.id),
         span: fld.new_span(m.span),
     }
 }
@@ -609,11 +610,21 @@ pub fn noop_fold_crate<T: Folder>(c: Crate, folder: &mut T) -> Crate {
 }
 
 pub fn noop_fold_item<T: Folder>(i: &Item, folder: &mut T) -> SmallVector<@Item> {
+    let id = folder.new_id(i.id); // Needs to be first, for ast_map.
+    let node = folder.fold_item_underscore(&i.node);
+    let ident = match node {
+        // The node may have changed, recompute the "pretty" impl name.
+        ItemImpl(_, ref maybe_trait, ty, _) => {
+            ast_util::impl_pretty_name(maybe_trait, ty)
+        }
+        _ => i.ident
+    };
+
     SmallVector::one(@Item {
-        ident: folder.fold_ident(i.ident),
+        id: id,
+        ident: folder.fold_ident(ident),
         attrs: i.attrs.map(|e| fold_attribute_(*e, folder)),
-        id: folder.new_id(i.id),
-        node: folder.fold_item_underscore(&i.node),
+        node: node,
         vis: i.vis,
         span: folder.new_span(i.span)
     })
@@ -621,6 +632,7 @@ pub fn noop_fold_item<T: Folder>(i: &Item, folder: &mut T) -> SmallVector<@Item>
 
 pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem, folder: &mut T) -> @ForeignItem {
     @ForeignItem {
+        id: folder.new_id(ni.id), // Needs to be first, for ast_map.
         ident: folder.fold_ident(ni.ident),
         attrs: ni.attrs.map(|x| fold_attribute_(*x, folder)),
         node: match ni.node {
@@ -636,7 +648,6 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem, folder: &mut T) -> @F
                 ForeignItemStatic(folder.fold_ty(t), m)
             }
         },
-        id: folder.new_id(ni.id),
         span: folder.new_span(ni.span),
         vis: ni.vis,
     }
@@ -644,6 +655,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem, folder: &mut T) -> @F
 
 pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> @Method {
     @Method {
+        id: folder.new_id(m.id), // Needs to be first, for ast_map.
         ident: folder.fold_ident(m.ident),
         attrs: m.attrs.map(|a| fold_attribute_(*a, folder)),
         generics: fold_generics(&m.generics, folder),
@@ -651,7 +663,6 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> @Method {
         purity: m.purity,
         decl: folder.fold_fn_decl(m.decl),
         body: folder.fold_block(m.body),
-        id: folder.new_id(m.id),
         span: folder.new_span(m.span),
         vis: m.vis
     }
@@ -894,8 +905,7 @@ mod test {
             ~"#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}");
         assert_pred!(matches_codepattern,
                      "matches_codepattern",
-                     pprust::to_str(&mut zz_fold.fold_crate(ast),fake_print_crate,
-                                    token::get_ident_interner()),
+                     pprust::to_str(&mut zz_fold.fold_crate(ast),fake_print_crate),
                      ~"#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}");
     }
 
@@ -907,8 +917,7 @@ mod test {
               (g $(d $d $e)+))} ");
         assert_pred!(matches_codepattern,
                      "matches_codepattern",
-                     pprust::to_str(&mut zz_fold.fold_crate(ast),fake_print_crate,
-                                    token::get_ident_interner()),
+                     pprust::to_str(&mut zz_fold.fold_crate(ast),fake_print_crate),
                      ~"zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))");
     }
 }
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index 138f9d71640..e0ae9ce2812 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -16,7 +16,6 @@ use parse::lexer::{StringReader, bump, is_eof, nextch_is, TokenAndSpan};
 use parse::lexer::{is_line_non_doc_comment, is_block_non_doc_comment};
 use parse::lexer;
 use parse::token;
-use parse::token::{get_ident_interner};
 
 use std::io;
 use std::str;
@@ -385,7 +384,7 @@ pub fn gather_comments_and_literals(span_diagnostic:
                 literals.push(Literal {lit: s.to_owned(), pos: sp.lo});
             })
         } else {
-            debug!("tok: {}", token::to_str(get_ident_interner(), &tok));
+            debug!("tok: {}", token::to_str(&tok));
         }
         first_read = false;
     }
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index 12e32731fcc..460ad76cffe 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use parse::token;
-use parse::token::{get_ident_interner};
 
 // SeqSep : a sequence separator (token)
 // and whether a trailing separator is allowed.
@@ -36,10 +35,3 @@ pub fn seq_sep_none() -> SeqSep {
         trailing_sep_allowed: false,
     }
 }
-
-// maps any token back to a string. not necessary if you know it's
-// an identifier....
-pub fn token_to_str(token: &token::Token) -> ~str {
-    token::to_str(get_ident_interner(), token)
-}
-
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 24227dea531..accffd374a9 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -175,8 +175,7 @@ impl ParserObsoleteMethods for Parser {
     fn is_obsolete_ident(&mut self, ident: &str) -> bool {
         match self.token {
             token::IDENT(sid, _) => {
-                let interned_string = token::get_ident(sid.name);
-                interned_string.equiv(&ident)
+                token::get_ident(sid).equiv(&ident)
             }
             _ => false
         }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 15608a0f28e..674d41e9dbe 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -71,9 +71,9 @@ use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed};
 use parse::lexer::Reader;
 use parse::lexer::TokenAndSpan;
 use parse::obsolete::*;
-use parse::token::{INTERPOLATED, InternedString, can_begin_expr, get_ident};
-use parse::token::{get_ident_interner, is_ident, is_ident_or_path};
-use parse::token::{is_plain_ident, keywords, special_idents, token_to_binop};
+use parse::token::{INTERPOLATED, InternedString, can_begin_expr};
+use parse::token::{is_ident, is_ident_or_path, is_plain_ident};
+use parse::token::{keywords, special_idents, token_to_binop};
 use parse::token;
 use parse::{new_sub_parser_from_file, ParseSess};
 use opt_vec;
@@ -288,7 +288,6 @@ struct ParsedItemsAndViewItems {
 pub fn Parser(sess: @ParseSess, cfg: ast::CrateConfig, rdr: ~Reader:)
               -> Parser {
     let tok0 = rdr.next_token();
-    let interner = get_ident_interner();
     let span = tok0.sp;
     let placeholder = TokenAndSpan {
         tok: token::UNDERSCORE,
@@ -297,7 +296,7 @@ pub fn Parser(sess: @ParseSess, cfg: ast::CrateConfig, rdr: ~Reader:)
 
     Parser {
         reader: rdr,
-        interner: interner,
+        interner: token::get_ident_interner(),
         sess: sess,
         cfg: cfg,
         token: tok0.tok,
@@ -359,7 +358,7 @@ fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
 impl Parser {
     // convert a token to a string using self's reader
     pub fn token_to_str(token: &token::Token) -> ~str {
-        token::to_str(get_ident_interner(), token)
+        token::to_str(token)
     }
 
     // convert the current token to a string using self's reader
@@ -531,12 +530,10 @@ impl Parser {
     // otherwise, eat it.
     pub fn expect_keyword(&mut self, kw: keywords::Keyword) {
         if !self.eat_keyword(kw) {
-            let id_ident = kw.to_ident();
-            let id_interned_str = token::get_ident(id_ident.name);
+            let id_interned_str = token::get_ident(kw.to_ident());
             let token_str = self.this_token_to_str();
             self.fatal(format!("expected `{}`, found `{}`",
-                               id_interned_str.get(),
-                               token_str))
+                               id_interned_str, token_str))
         }
     }
 
@@ -804,7 +801,7 @@ impl Parser {
     }
 
     pub fn id_to_interned_str(&mut self, id: Ident) -> InternedString {
-        get_ident(id.name)
+        token::get_ident(id)
     }
 
     // Is the current token one of the keywords that signals a bare function
@@ -3425,8 +3422,7 @@ impl Parser {
         loop {
             match self.token {
                 token::LIFETIME(lifetime) => {
-                    let lifetime_interned_string =
-                        token::get_ident(lifetime.name);
+                    let lifetime_interned_string = token::get_ident(lifetime);
                     if lifetime_interned_string.equiv(&("static")) {
                         result.push(RegionTyParamBound);
                     } else {
@@ -3876,10 +3872,6 @@ impl Parser {
         // First, parse type parameters if necessary.
         let generics = self.parse_generics();
 
-        // This is a new-style impl declaration.
-        // FIXME: clownshoes
-        let ident = special_idents::clownshoes_extensions;
-
         // Special case: if the next identifier that follows is '(', don't
         // allow this to be parsed as a trait.
         let could_be_trait = self.token != token::LPAREN;
@@ -3923,6 +3915,8 @@ impl Parser {
             method_attrs = None;
         }
 
+        let ident = ast_util::impl_pretty_name(&opt_trait, ty);
+
         (ident, ItemImpl(generics, opt_trait, ty, meths), Some(inner_attrs))
     }
 
@@ -3959,9 +3953,8 @@ impl Parser {
                 fields.push(self.parse_struct_decl_field());
             }
             if fields.len() == 0 {
-                let string = get_ident_interner().get(class_name.name);
                 self.fatal(format!("unit-like struct definition should be written as `struct {};`",
-                                   string.as_slice()));
+                                   token::get_ident(class_name)));
             }
             self.bump();
         } else if self.token == token::LPAREN {
@@ -4159,7 +4152,7 @@ impl Parser {
                 outer_attrs, "path") {
             Some(d) => dir_path.join(d),
             None => {
-                let mod_string = token::get_ident(id.name);
+                let mod_string = token::get_ident(id);
                 let mod_name = mod_string.get().to_owned();
                 let default_path_str = mod_name + ".rs";
                 let secondary_path_str = mod_name + "/mod.rs";
@@ -4378,7 +4371,7 @@ impl Parser {
 
         let item = self.mk_item(lo,
                                 self.last_span.hi,
-                                special_idents::clownshoes_foreign_mod,
+                                special_idents::invalid,
                                 ItemForeignMod(m),
                                 visibility,
                                 maybe_append(attrs, Some(inner)));
@@ -4498,7 +4491,7 @@ impl Parser {
             token::LIT_STR(s)
             | token::LIT_STR_RAW(s, _) => {
                 self.bump();
-                let identifier_string = token::get_ident(s.name);
+                let identifier_string = token::get_ident(s);
                 let the_string = identifier_string.get();
                 let mut abis = AbiSet::empty();
                 for word in the_string.words() {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 423ddb82808..b264e8d7467 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use ast;
-use ast::{P, Name, Mrk};
+use ast::{P, Ident, Name, Mrk};
 use ast_util;
 use parse::token;
 use util::interner::{RcStr, StrInterner};
@@ -133,7 +133,7 @@ pub fn binop_to_str(o: BinOp) -> ~str {
     }
 }
 
-pub fn to_str(input: @IdentInterner, t: &Token) -> ~str {
+pub fn to_str(t: &Token) -> ~str {
     match *t {
       EQ => ~"=",
       LT => ~"<",
@@ -187,50 +187,42 @@ pub fn to_str(input: @IdentInterner, t: &Token) -> ~str {
           u.to_str() + ast_util::uint_ty_to_str(t)
       }
       LIT_INT_UNSUFFIXED(i) => { i.to_str() }
-      LIT_FLOAT(ref s, t) => {
-        let body_string = get_ident(s.name);
-        let mut body = body_string.get().to_str();
+      LIT_FLOAT(s, t) => {
+        let mut body = get_ident(s).get().to_str();
         if body.ends_with(".") {
             body.push_char('0');  // `10.f` is not a float literal
         }
         body + ast_util::float_ty_to_str(t)
       }
-      LIT_FLOAT_UNSUFFIXED(ref s) => {
-        let body_string = get_ident(s.name);
-        let mut body = body_string.get().to_owned();
+      LIT_FLOAT_UNSUFFIXED(s) => {
+        let mut body = get_ident(s).get().to_str();
         if body.ends_with(".") {
             body.push_char('0');  // `10.f` is not a float literal
         }
         body
       }
-      LIT_STR(ref s) => {
-          let literal_string = get_ident(s.name);
-          format!("\"{}\"", literal_string.get().escape_default())
+      LIT_STR(s) => {
+          format!("\"{}\"", get_ident(s).get().escape_default())
       }
-      LIT_STR_RAW(ref s, n) => {
-          let literal_string = get_ident(s.name);
+      LIT_STR_RAW(s, n) => {
           format!("r{delim}\"{string}\"{delim}",
-                  delim="#".repeat(n), string=literal_string.get())
+                  delim="#".repeat(n), string=get_ident(s))
       }
 
       /* Name components */
-      IDENT(s, _) => input.get(s.name).into_owned(),
+      IDENT(s, _) => get_ident(s).get().to_str(),
       LIFETIME(s) => {
-          let name = input.get(s.name);
-          format!("'{}", name.as_slice())
+          format!("'{}", get_ident(s))
       }
       UNDERSCORE => ~"_",
 
       /* Other */
-      DOC_COMMENT(ref s) => {
-          let comment_string = get_ident(s.name);
-          comment_string.get().to_str()
-      }
+      DOC_COMMENT(s) => get_ident(s).get().to_str(),
       EOF => ~"<eof>",
       INTERPOLATED(ref nt) => {
         match nt {
-            &NtExpr(e) => ::print::pprust::expr_to_str(e, input),
-            &NtAttr(e) => ::print::pprust::attribute_to_str(e, input),
+            &NtExpr(e) => ::print::pprust::expr_to_str(e),
+            &NtAttr(e) => ::print::pprust::attribute_to_str(e),
             _ => {
                 ~"an interpolated " +
                     match *nt {
@@ -398,7 +390,7 @@ macro_rules! declare_special_idents_and_keywords {(
         }
     }
 
-    fn mk_fresh_ident_interner() -> @IdentInterner {
+    fn mk_fresh_ident_interner() -> IdentInterner {
         // The indices here must correspond to the numbers in
         // special_idents, in Keyword to_ident(), and in static
         // constants below.
@@ -408,92 +400,85 @@ macro_rules! declare_special_idents_and_keywords {(
             $( $rk_str, )*
         ];
 
-        @interner::StrInterner::prefill(init_vec)
+        interner::StrInterner::prefill(init_vec)
     }
 }}
 
 // If the special idents get renumbered, remember to modify these two as appropriate
-static SELF_KEYWORD_NAME: Name = 3;
-static STATIC_KEYWORD_NAME: Name = 10;
+static SELF_KEYWORD_NAME: Name = 1;
+static STATIC_KEYWORD_NAME: Name = 2;
 
 declare_special_idents_and_keywords! {
     pub mod special_idents {
         // These ones are statics
-
-        (0,                          anon,                   "anon");
-        (1,                          invalid,                "");       // ''
-        (2,                          clownshoes_extensions,  "__extensions__");
-
-        (super::SELF_KEYWORD_NAME,   self_,                  "self"); // 'self'
+        (0,                          invalid,                "");
+        (super::SELF_KEYWORD_NAME,   self_,                  "self");
+        (super::STATIC_KEYWORD_NAME, statik,                 "static");
 
         // for matcher NTs
-        (4,                          tt,                     "tt");
-        (5,                          matchers,               "matchers");
+        (3,                          tt,                     "tt");
+        (4,                          matchers,               "matchers");
 
         // outside of libsyntax
-        (6,                          arg,                    "arg");
-        (7,                          clownshoe_abi,          "__rust_abi");
-        (8,                          main,                   "main");
-        (9,                          opaque,                 "<opaque>");
-        (super::STATIC_KEYWORD_NAME, statik,                 "static");
-        (11,                         clownshoes_foreign_mod, "__foreign_mod__");
-        (12,                         unnamed_field,          "<unnamed_field>");
-        (13,                         type_self,              "Self"); // `Self`
+        (5,                          clownshoe_abi,          "__rust_abi");
+        (6,                          opaque,                 "<opaque>");
+        (7,                          unnamed_field,          "<unnamed_field>");
+        (8,                          type_self,              "Self");
     }
 
     pub mod keywords {
         // These ones are variants of the Keyword enum
 
         'strict:
-        (14,                         As,         "as");
-        (15,                         Break,      "break");
-        (16,                         Const,      "const");
-        (17,                         Else,       "else");
-        (18,                         Enum,       "enum");
-        (19,                         Extern,     "extern");
-        (20,                         False,      "false");
-        (21,                         Fn,         "fn");
-        (22,                         For,        "for");
-        (23,                         If,         "if");
-        (24,                         Impl,       "impl");
-        (25,                         In,         "in");
-        (26,                         Let,        "let");
-        (27,                         __LogLevel, "__log_level");
-        (28,                         Loop,       "loop");
-        (29,                         Match,      "match");
-        (30,                         Mod,        "mod");
-        (31,                         Crate,      "crate");
-        (32,                         Mut,        "mut");
-        (33,                         Once,       "once");
-        (34,                         Priv,       "priv");
-        (35,                         Pub,        "pub");
-        (36,                         Ref,        "ref");
-        (37,                         Return,     "return");
+        (9,                          As,         "as");
+        (10,                         Break,      "break");
+        (11,                         Const,      "const");
+        (12,                         Crate,      "crate");
+        (13,                         Else,       "else");
+        (14,                         Enum,       "enum");
+        (15,                         Extern,     "extern");
+        (16,                         False,      "false");
+        (17,                         Fn,         "fn");
+        (18,                         For,        "for");
+        (19,                         If,         "if");
+        (20,                         Impl,       "impl");
+        (21,                         In,         "in");
+        (22,                         Let,        "let");
+        (23,                         __LogLevel, "__log_level");
+        (24,                         Loop,       "loop");
+        (25,                         Match,      "match");
+        (26,                         Mod,        "mod");
+        (27,                         Mut,        "mut");
+        (28,                         Once,       "once");
+        (29,                         Priv,       "priv");
+        (30,                         Pub,        "pub");
+        (31,                         Ref,        "ref");
+        (32,                         Return,     "return");
         // Static and Self are also special idents (prefill de-dupes)
         (super::STATIC_KEYWORD_NAME, Static,     "static");
         (super::SELF_KEYWORD_NAME,   Self,       "self");
-        (38,                         Struct,     "struct");
-        (39,                         Super,      "super");
-        (40,                         True,       "true");
-        (41,                         Trait,      "trait");
-        (42,                         Type,       "type");
-        (43,                         Unsafe,     "unsafe");
-        (44,                         Use,        "use");
-        (45,                         While,      "while");
-        (46,                         Continue,   "continue");
-        (47,                         Proc,       "proc");
-        (48,                         Box,        "box");
+        (33,                         Struct,     "struct");
+        (34,                         Super,      "super");
+        (35,                         True,       "true");
+        (36,                         Trait,      "trait");
+        (37,                         Type,       "type");
+        (38,                         Unsafe,     "unsafe");
+        (39,                         Use,        "use");
+        (40,                         While,      "while");
+        (41,                         Continue,   "continue");
+        (42,                         Proc,       "proc");
+        (43,                         Box,        "box");
 
         'reserved:
-        (49,                         Alignof,    "alignof");
-        (50,                         Be,         "be");
-        (51,                         Offsetof,   "offsetof");
-        (52,                         Pure,       "pure");
-        (53,                         Sizeof,     "sizeof");
-        (54,                         Typeof,     "typeof");
-        (55,                         Unsized,    "unsized");
-        (56,                         Yield,      "yield");
-        (57,                         Do,         "do");
+        (44,                         Alignof,    "alignof");
+        (45,                         Be,         "be");
+        (46,                         Offsetof,   "offsetof");
+        (47,                         Pure,       "pure");
+        (48,                         Sizeof,     "sizeof");
+        (49,                         Typeof,     "typeof");
+        (50,                         Unsized,    "unsized");
+        (51,                         Yield,      "yield");
+        (52,                         Do,         "do");
     }
 }
 
@@ -531,12 +516,12 @@ pub type IdentInterner = StrInterner;
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
 pub fn get_ident_interner() -> @IdentInterner {
-    local_data_key!(key: @@::parse::token::IdentInterner)
+    local_data_key!(key: @::parse::token::IdentInterner)
     match local_data::get(key, |k| k.map(|k| *k)) {
-        Some(interner) => *interner,
+        Some(interner) => interner,
         None => {
-            let interner = mk_fresh_ident_interner();
-            local_data::set(key, @interner);
+            let interner = @mk_fresh_ident_interner();
+            local_data::set(key, interner);
             interner
         }
     }
@@ -603,8 +588,7 @@ impl<'a> Equiv<&'a str> for InternedString {
 
 impl<D:Decoder> Decodable<D> for InternedString {
     fn decode(d: &mut D) -> InternedString {
-        let interner = get_ident_interner();
-        get_ident(interner.intern(d.read_str()))
+        get_name(get_ident_interner().intern(d.read_str()))
     }
 }
 
@@ -614,54 +598,55 @@ impl<E:Encoder> Encodable<E> for InternedString {
     }
 }
 
+/// Returns the string contents of a name, using the task-local interner.
+#[inline]
+pub fn get_name(name: Name) -> InternedString {
+    let interner = get_ident_interner();
+    InternedString::new_from_rc_str(interner.get(name))
+}
+
 /// Returns the string contents of an identifier, using the task-local
 /// interner.
 #[inline]
-pub fn get_ident(idx: Name) -> InternedString {
-    let interner = get_ident_interner();
-    InternedString::new_from_rc_str(interner.get(idx))
+pub fn get_ident(ident: Ident) -> InternedString {
+    get_name(ident.name)
 }
 
 /// Interns and returns the string contents of an identifier, using the
 /// task-local interner.
 #[inline]
 pub fn intern_and_get_ident(s: &str) -> InternedString {
-    get_ident(intern(s))
-}
-
-/* for when we don't care about the contents; doesn't interact with TLD or
-   serialization */
-pub fn mk_fake_ident_interner() -> @IdentInterner {
-    @interner::StrInterner::new()
+    get_name(intern(s))
 }
 
-// maps a string to its interned representation
+/// Maps a string to its interned representation.
 #[inline]
-pub fn intern(str : &str) -> Name {
-    let interner = get_ident_interner();
-    interner.intern(str)
+pub fn intern(s: &str) -> Name {
+    get_ident_interner().intern(s)
 }
 
-// gensyms a new uint, using the current interner
-pub fn gensym(str : &str) -> Name {
-    let interner = get_ident_interner();
-    interner.gensym(str)
+/// gensym's a new uint, using the current interner.
+#[inline]
+pub fn gensym(s: &str) -> Name {
+    get_ident_interner().gensym(s)
 }
 
-// maps a string to an identifier with an empty syntax context
-pub fn str_to_ident(str : &str) -> ast::Ident {
-    ast::Ident::new(intern(str))
+/// Maps a string to an identifier with an empty syntax context.
+#[inline]
+pub fn str_to_ident(s: &str) -> ast::Ident {
+    ast::Ident::new(intern(s))
 }
 
-// maps a string to a gensym'ed identifier
-pub fn gensym_ident(str : &str) -> ast::Ident {
-    ast::Ident::new(gensym(str))
+/// Maps a string to a gensym'ed identifier.
+#[inline]
+pub fn gensym_ident(s: &str) -> ast::Ident {
+    ast::Ident::new(gensym(s))
 }
 
 // create a fresh name that maps to the same string as the old one.
 // note that this guarantees that str_ptr_eq(ident_to_str(src),interner_get(fresh_name(src)));
 // that is, that the new name and the old one are connected to ptr_eq strings.
-pub fn fresh_name(src : &ast::Ident) -> Name {
+pub fn fresh_name(src: &ast::Ident) -> Name {
     let interner = get_ident_interner();
     interner.gensym_copy(src.name)
     // following: debug version. Could work in final except that it's incompatible with
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 24aa30cb36b..85bc372b9c6 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -83,18 +83,15 @@ pub fn end(s: &mut State) -> io::IoResult<()> {
     pp::end(&mut s.s)
 }
 
-pub fn rust_printer(writer: ~io::Writer, intr: @IdentInterner) -> State<'static> {
-    rust_printer_annotated(writer, intr, &NoAnn)
+pub fn rust_printer(writer: ~io::Writer) -> State<'static> {
+    rust_printer_annotated(writer, &NoAnn)
 }
 
-pub fn rust_printer_annotated<'a>(writer: ~io::Writer,
-                                  intr: @IdentInterner,
-                                  ann: &'a PpAnn)
-                                  -> State<'a> {
+pub fn rust_printer_annotated<'a>(writer: ~io::Writer, ann: &'a PpAnn) -> State<'a> {
     State {
         s: pp::mk_printer(writer, default_columns),
         cm: None,
-        intr: intr,
+        intr: token::get_ident_interner(),
         comments: None,
         literals: None,
         cur_cmnt_and_lit: CurrentCommentAndLiteral {
@@ -114,7 +111,6 @@ pub static default_columns: uint = 78u;
 // it can scan the input text for comments and literals to
 // copy forward.
 pub fn print_crate(cm: @CodeMap,
-                   intr: @IdentInterner,
                    span_diagnostic: @diagnostic::SpanHandler,
                    krate: &ast::Crate,
                    filename: ~str,
@@ -130,7 +126,7 @@ pub fn print_crate(cm: @CodeMap,
     let mut s = State {
         s: pp::mk_printer(out, default_columns),
         cm: Some(cm),
-        intr: intr,
+        intr: token::get_ident_interner(),
         comments: Some(cmnts),
         // If the code is post expansion, don't use the table of
         // literals, since it doesn't correspond with the literals
@@ -157,52 +153,51 @@ pub fn print_crate_(s: &mut State, krate: &ast::Crate) -> io::IoResult<()> {
     Ok(())
 }
 
-pub fn ty_to_str(ty: &ast::Ty, intr: @IdentInterner) -> ~str {
-    to_str(ty, print_type, intr)
+pub fn ty_to_str(ty: &ast::Ty) -> ~str {
+    to_str(ty, print_type)
 }
 
-pub fn pat_to_str(pat: &ast::Pat, intr: @IdentInterner) -> ~str {
-    to_str(pat, print_pat, intr)
+pub fn pat_to_str(pat: &ast::Pat) -> ~str {
+    to_str(pat, print_pat)
 }
 
-pub fn expr_to_str(e: &ast::Expr, intr: @IdentInterner) -> ~str {
-    to_str(e, print_expr, intr)
+pub fn expr_to_str(e: &ast::Expr) -> ~str {
+    to_str(e, print_expr)
 }
 
-pub fn lifetime_to_str(e: &ast::Lifetime, intr: @IdentInterner) -> ~str {
-    to_str(e, print_lifetime, intr)
+pub fn lifetime_to_str(e: &ast::Lifetime) -> ~str {
+    to_str(e, print_lifetime)
 }
 
-pub fn tt_to_str(tt: &ast::TokenTree, intr: @IdentInterner) -> ~str {
-    to_str(tt, print_tt, intr)
+pub fn tt_to_str(tt: &ast::TokenTree) -> ~str {
+    to_str(tt, print_tt)
 }
 
-pub fn tts_to_str(tts: &[ast::TokenTree], intr: @IdentInterner) -> ~str {
-    to_str(&tts, print_tts, intr)
+pub fn tts_to_str(tts: &[ast::TokenTree]) -> ~str {
+    to_str(&tts, print_tts)
 }
 
-pub fn stmt_to_str(s: &ast::Stmt, intr: @IdentInterner) -> ~str {
-    to_str(s, print_stmt, intr)
+pub fn stmt_to_str(s: &ast::Stmt) -> ~str {
+    to_str(s, print_stmt)
 }
 
-pub fn item_to_str(i: &ast::Item, intr: @IdentInterner) -> ~str {
-    to_str(i, print_item, intr)
+pub fn item_to_str(i: &ast::Item) -> ~str {
+    to_str(i, print_item)
 }
 
-pub fn generics_to_str(generics: &ast::Generics,
-                       intr: @IdentInterner) -> ~str {
-    to_str(generics, print_generics, intr)
+pub fn generics_to_str(generics: &ast::Generics) -> ~str {
+    to_str(generics, print_generics)
 }
 
-pub fn path_to_str(p: &ast::Path, intr: @IdentInterner) -> ~str {
-    to_str(p, |a,b| print_path(a, b, false), intr)
+pub fn path_to_str(p: &ast::Path) -> ~str {
+    to_str(p, |a,b| print_path(a, b, false))
 }
 
 pub fn fun_to_str(decl: &ast::FnDecl, purity: ast::Purity, name: ast::Ident,
                   opt_explicit_self: Option<ast::ExplicitSelf_>,
-                  generics: &ast::Generics, intr: @IdentInterner) -> ~str {
+                  generics: &ast::Generics) -> ~str {
     let wr = ~MemWriter::new();
-    let mut s = rust_printer(wr as ~io::Writer, intr);
+    let mut s = rust_printer(wr as ~io::Writer);
     print_fn(&mut s, decl, Some(purity), AbiSet::Rust(),
              name, generics, opt_explicit_self, ast::Inherited).unwrap();
     end(&mut s).unwrap(); // Close the head box
@@ -213,9 +208,9 @@ pub fn fun_to_str(decl: &ast::FnDecl, purity: ast::Purity, name: ast::Ident,
     }
 }
 
-pub fn block_to_str(blk: &ast::Block, intr: @IdentInterner) -> ~str {
+pub fn block_to_str(blk: &ast::Block) -> ~str {
     let wr = ~MemWriter::new();
-    let mut s = rust_printer(wr as ~io::Writer, intr);
+    let mut s = rust_printer(wr as ~io::Writer);
     // containing cbox, will be closed by print-block at }
     cbox(&mut s, indent_unit).unwrap();
     // head-ibox, will be closed by print-block after {
@@ -227,16 +222,16 @@ pub fn block_to_str(blk: &ast::Block, intr: @IdentInterner) -> ~str {
     }
 }
 
-pub fn meta_item_to_str(mi: &ast::MetaItem, intr: @IdentInterner) -> ~str {
-    to_str(mi, print_meta_item, intr)
+pub fn meta_item_to_str(mi: &ast::MetaItem) -> ~str {
+    to_str(mi, print_meta_item)
 }
 
-pub fn attribute_to_str(attr: &ast::Attribute, intr: @IdentInterner) -> ~str {
-    to_str(attr, print_attribute, intr)
+pub fn attribute_to_str(attr: &ast::Attribute) -> ~str {
+    to_str(attr, print_attribute)
 }
 
-pub fn variant_to_str(var: &ast::Variant, intr: @IdentInterner) -> ~str {
-    to_str(var, print_variant, intr)
+pub fn variant_to_str(var: &ast::Variant) -> ~str {
+    to_str(var, print_variant)
 }
 
 pub fn cbox(s: &mut State, u: uint) -> io::IoResult<()> {
@@ -817,7 +812,7 @@ pub fn print_tt(s: &mut State, tt: &ast::TokenTree) -> io::IoResult<()> {
     match *tt {
         ast::TTDelim(ref tts) => print_tts(s, &(tts.as_slice())),
         ast::TTTok(_, ref tk) => {
-            word(&mut s.s, parse::token::to_str(s.intr, tk))
+            word(&mut s.s, parse::token::to_str(tk))
         }
         ast::TTSeq(_, ref tts, ref sep, zerok) => {
             if_ok!(word(&mut s.s, "$("));
@@ -827,7 +822,7 @@ pub fn print_tt(s: &mut State, tt: &ast::TokenTree) -> io::IoResult<()> {
             if_ok!(word(&mut s.s, ")"));
             match *sep {
                 Some(ref tk) => {
-                    if_ok!(word(&mut s.s, parse::token::to_str(s.intr, tk)));
+                    if_ok!(word(&mut s.s, parse::token::to_str(tk)));
                 }
                 None => ()
             }
@@ -1615,13 +1610,11 @@ pub fn print_decl(s: &mut State, decl: &ast::Decl) -> io::IoResult<()> {
 }
 
 pub fn print_ident(s: &mut State, ident: ast::Ident) -> io::IoResult<()> {
-    let string = token::get_ident(ident.name);
-    word(&mut s.s, string.get())
+    word(&mut s.s, token::get_ident(ident).get())
 }
 
 pub fn print_name(s: &mut State, name: ast::Name) -> io::IoResult<()> {
-    let string = token::get_ident(name);
-    word(&mut s.s, string.get())
+    word(&mut s.s, token::get_name(name).get())
 }
 
 pub fn print_for_decl(s: &mut State, loc: &ast::Local,
@@ -1692,15 +1685,14 @@ fn print_path_(s: &mut State,
     Ok(())
 }
 
-pub fn print_path(s: &mut State, path: &ast::Path,
-                  colons_before_params: bool) -> io::IoResult<()> {
+fn print_path(s: &mut State, path: &ast::Path,
+              colons_before_params: bool) -> io::IoResult<()> {
     print_path_(s, path, colons_before_params, &None)
 }
 
-pub fn print_bounded_path(s: &mut State, path: &ast::Path,
-                          bounds: &Option<OptVec<ast::TyParamBound>>)
-    -> io::IoResult<()>
-{
+fn print_bounded_path(s: &mut State, path: &ast::Path,
+                      bounds: &Option<OptVec<ast::TyParamBound>>)
+    -> io::IoResult<()> {
     print_path_(s, path, false, bounds)
 }
 
@@ -1818,11 +1810,10 @@ pub fn print_pat(s: &mut State, pat: &ast::Pat) -> io::IoResult<()> {
     Ok(())
 }
 
-pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_,
-                            intr: @IdentInterner) -> ~str {
+pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_) -> ~str {
     to_str(explicit_self, |a, &b| {
         print_explicit_self(a, b, ast::MutImmutable).map(|_| ())
-    }, intr)
+    })
 }
 
 // Returns whether it printed anything
@@ -2346,7 +2337,7 @@ pub fn print_literal(s: &mut State, lit: &ast::Lit) -> io::IoResult<()> {
 }
 
 pub fn lit_to_str(l: &ast::Lit) -> ~str {
-    return to_str(l, print_literal, parse::token::mk_fake_ident_interner());
+    to_str(l, print_literal)
 }
 
 pub fn next_lit(s: &mut State, pos: BytePos) -> Option<comments::Literal> {
@@ -2450,10 +2441,9 @@ unsafe fn get_mem_writer(writer: &mut ~io::Writer) -> ~str {
     result
 }
 
-pub fn to_str<T>(t: &T, f: |&mut State, &T| -> io::IoResult<()>,
-                 intr: @IdentInterner) -> ~str {
+pub fn to_str<T>(t: &T, f: |&mut State, &T| -> io::IoResult<()>) -> ~str {
     let wr = ~MemWriter::new();
-    let mut s = rust_printer(wr as ~io::Writer, intr);
+    let mut s = rust_printer(wr as ~io::Writer);
     f(&mut s, t).unwrap();
     eof(&mut s.s).unwrap();
     unsafe {
@@ -2600,7 +2590,7 @@ mod test {
         };
         let generics = ast_util::empty_generics();
         assert_eq!(&fun_to_str(&decl, ast::ImpureFn, abba_ident,
-                               None, &generics, token::get_ident_interner()),
+                               None, &generics),
                    &~"fn abba()");
     }
 
@@ -2618,7 +2608,7 @@ mod test {
             vis: ast::Public,
         });
 
-        let varstr = variant_to_str(&var,token::get_ident_interner());
+        let varstr = variant_to_str(&var);
         assert_eq!(&varstr,&~"pub principal_skinner");
     }
 }
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index fc3e55dcde2..aedff2d7854 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -21,16 +21,16 @@ use std::hashmap::HashMap;
 use std::rc::Rc;
 
 pub struct Interner<T> {
-    priv map: @RefCell<HashMap<T, Name>>,
-    priv vect: @RefCell<~[T]>,
+    priv map: RefCell<HashMap<T, Name>>,
+    priv vect: RefCell<~[T]>,
 }
 
 // when traits can extend traits, we should extend index<Name,T> to get []
 impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
-            map: @RefCell::new(HashMap::new()),
-            vect: @RefCell::new(~[]),
+            map: RefCell::new(HashMap::new()),
+            vect: RefCell::new(~[]),
         }
     }
 
@@ -123,18 +123,18 @@ impl RcStr {
 }
 
 // A StrInterner differs from Interner<String> in that it accepts
-// references rather than @ ones, resulting in less allocation.
+// &str rather than RcStr, resulting in less allocation.
 pub struct StrInterner {
-    priv map: @RefCell<HashMap<RcStr, Name>>,
-    priv vect: @RefCell<~[RcStr]>,
+    priv map: RefCell<HashMap<RcStr, Name>>,
+    priv vect: RefCell<~[RcStr]>,
 }
 
 // when traits can extend traits, we should extend index<Name,T> to get []
 impl StrInterner {
     pub fn new() -> StrInterner {
         StrInterner {
-            map: @RefCell::new(HashMap::new()),
-            vect: @RefCell::new(~[]),
+            map: RefCell::new(HashMap::new()),
+            vect: RefCell::new(~[]),
         }
     }
 
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index e1fe43b8e04..ce87c3d7591 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -43,7 +43,7 @@ pub enum FnKind<'a> {
 pub fn name_of_fn(fk: &FnKind) -> Ident {
     match *fk {
         FkItemFn(name, _, _, _) | FkMethod(name, _, _) => name,
-        FkFnBlock(..) => parse::token::special_idents::anon
+        FkFnBlock(..) => parse::token::special_idents::invalid
     }
 }