diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index f334b104191..18a7e65a6dd 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -39,7 +39,6 @@ use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
 use syntax::attr;
 use syntax::attr::{AttrMetaMethods};
 use syntax::print::pprust;
-use syntax::parse::token;
 
 #[deriving(Clone, Eq)]
 pub enum output_type {
@@ -678,8 +677,8 @@ pub fn symbol_hash(tcx: ty::ctxt,
     write_string(symbol_hasher, "-");
     write_string(symbol_hasher, encoder::encoded_ty(tcx, t));
     let mut hash = truncated_hash_result(symbol_hasher);
-    // Prefix with _ so that it never blends into adjacent digits
-    hash.unshift_char('_');
+    // Prefix with 'h' so that it never blends into adjacent digits
+    hash.unshift_char('h');
     // tjc: allocation is unfortunate; need to change std::hash
     hash.to_managed()
 }
@@ -722,7 +721,7 @@ pub fn sanitize(s: &str) -> ~str {
             'a' .. 'z'
             | 'A' .. 'Z'
             | '0' .. '9'
-            | '_' | '.' => result.push_char(c),
+            | '_' | '.' | '$' => result.push_char(c),
 
             _ => {
                 let mut tstr = ~"";
@@ -847,9 +846,9 @@ pub fn mangle_internal_name_by_type_and_seq(ccx: &mut CrateContext,
                                             name: &str) -> ~str {
     let s = ppaux::ty_to_str(ccx.tcx, t);
     let hash = get_symbol_hash(ccx, t);
+    let (_, name) = gensym_name(name);
     return mangle(ccx.sess,
-                  ~[path_name(ccx.sess.ident_of(s)),
-                    path_name(gensym_name(name))],
+                  ~[path_name(ccx.sess.ident_of(s)), name],
                   Some(hash.as_slice()),
                   None);
 }
@@ -857,7 +856,8 @@ pub fn mangle_internal_name_by_type_and_seq(ccx: &mut CrateContext,
 pub fn mangle_internal_name_by_path_and_seq(ccx: &mut CrateContext,
                                             mut path: path,
                                             flav: &str) -> ~str {
-    path.push(path_name(gensym_name(flav)));
+    let (_, name) = gensym_name(flav);
+    path.push(name);
     mangle(ccx.sess, path, None, None)
 }
 
@@ -865,10 +865,6 @@ pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str
     mangle(ccx.sess, path, None, None)
 }
 
-pub fn mangle_internal_name_by_seq(_ccx: &mut CrateContext, flav: &str) -> ~str {
-    return fmt!("%s_%u", flav, token::gensym(flav));
-}
-
 
 pub fn output_dll_filename(os: session::Os, lm: LinkMeta) -> ~str {
     let (dll_prefix, dll_suffix) = match os {
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index fb52963f4fc..d1eb959055b 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -1063,12 +1063,13 @@ fn encode_info_for_item(ecx: &EncodeContext,
             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
         }
-        encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
+        let elt = ast_map::impl_pretty_name(opt_trait, ty, item.ident);
+        encode_path(ecx, ebml_w, path, elt);
         ebml_w.end_tag();
 
         // >:-<
         let mut impl_path = vec::append(~[], path);
-        impl_path.push(ast_map::path_name(item.ident));
+        impl_path.push(elt);
 
         // Iterate down the methods, emitting them. We rely on the
         // assumption that all of the actually implemented methods
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 6e4928857f8..bbdb9730e95 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -39,15 +39,17 @@ use std::hashmap::{HashMap};
 use std::libc::{c_uint, c_longlong, c_ulonglong, c_char};
 use std::vec;
 use syntax::ast::Ident;
-use syntax::ast_map::{path, path_elt};
+use syntax::ast_map::{path, path_elt, path_pretty_name};
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::{ast, ast_map};
 
 pub use middle::trans::context::CrateContext;
 
-pub fn gensym_name(name: &str) -> Ident {
-    token::str_to_ident(fmt!("%s_%u", name, token::gensym(name)))
+pub fn gensym_name(name: &str) -> (Ident, path_elt) {
+    let name = token::gensym(name);
+    let ident = Ident::new(name);
+    (ident, path_pretty_name(ident, name as u64))
 }
 
 pub struct tydesc_info {
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index e4879ef4a11..21bde8e388b 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -69,6 +69,7 @@ use std::ptr;
 use std::vec;
 use syntax::codemap::Span;
 use syntax::{ast, codemap, ast_util, ast_map, opt_vec};
+use syntax::parse::token;
 use syntax::parse::token::special_idents;
 
 static DW_LANG_RUST: c_uint = 0x9000;
@@ -513,7 +514,8 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
         ast_map::node_expr(ref expr) => {
             match expr.node {
                 ast::ExprFnBlock(ref fn_decl, ref top_level_block) => {
-                    let name = gensym_name("fn");
+                    let name = fmt!("fn%u", token::gensym("fn"));
+                    let name = token::str_to_ident(name);
                     (name, fn_decl,
                         // This is not quite right. It should actually inherit the generics of the
                         // enclosing function.
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index e49265a99a9..06d88f66323 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -37,6 +37,7 @@ use std::vec;
 use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
 use syntax::ast_util;
 use syntax::{ast, ast_map};
+use syntax::parse::token;
 use syntax::visit;
 
 /**
@@ -568,8 +569,8 @@ pub fn make_vtable(ccx: &mut CrateContext,
         }
 
         let tbl = C_struct(components);
-        let vtable = ccx.sess.str_of(gensym_name("vtable"));
-        let vt_gvar = do vtable.with_c_str |buf| {
+        let sym = token::gensym("vtable");
+        let vt_gvar = do fmt!("vtable%u", sym).with_c_str |buf| {
             llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
         };
         llvm::LLVMSetInitializer(vt_gvar, tbl);
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 0c0d3b7275b..2bdff6c8567 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -31,7 +31,6 @@ use util::ppaux::{Repr,ty_to_str};
 
 use syntax::ast;
 use syntax::ast_map;
-use syntax::ast_map::path_name;
 use syntax::ast_util::local_def;
 
 pub fn monomorphic_fn(ccx: @mut CrateContext,
@@ -194,7 +193,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
     }
     ccx.monomorphizing.insert(fn_id, depth + 1);
 
-    let elt = path_name(gensym_name(ccx.sess.str_of(name)));
+    let (_, elt) = gensym_name(ccx.sess.str_of(name));
     let mut pt = (*pt).clone();
     pt.push(elt);
     let s = mangle_exported_name(ccx, pt.clone(), mono_ty);
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index dd991b065e9..16e80560cc8 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -72,6 +72,28 @@ pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
     }
 }
 
+pub fn impl_pretty_name(trait_ref: &Option<trait_ref>,
+                        ty: &Ty, default: Ident) -> path_elt {
+    let itr = get_ident_interner();
+    let ty_ident = match ty.node {
+        ty_path(ref path, _, _) => path.segments.last().identifier,
+        _ => default
+    };
+    let hash = (trait_ref, ty).hash();
+    match *trait_ref {
+        None => path_pretty_name(ty_ident, hash),
+        Some(ref trait_ref) => {
+            // XXX: this dollar sign is 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.
+            let s = fmt!("%s$%s",
+                         itr.get(trait_ref.path.segments.last().identifier.name),
+                         itr.get(ty_ident.name));
+            path_pretty_name(Ident::new(itr.gensym(s)), hash)
+        }
+    }
+}
+
 #[deriving(Clone)]
 pub enum ast_node {
     node_item(@item, @path),
@@ -216,28 +238,6 @@ impl Ctx {
 
         visit::walk_pat(self, pat, ());
     }
-
-    fn impl_pretty_name(&self, trait_ref: &Option<trait_ref>,
-                        ty: &Ty, default: Ident) -> path_elt {
-        let itr = get_ident_interner();
-        let ty_ident = match ty.node {
-            ty_path(ref path, _, _) => path.segments.last().identifier,
-            _ => default
-        };
-        let hash = (trait_ref, ty).hash();
-        match *trait_ref {
-            None => path_pretty_name(ty_ident, hash),
-            Some(ref trait_ref) => {
-                // XXX: this dollar sign is 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.
-                let s = fmt!("%s$%s",
-                             itr.get(trait_ref.path.segments.last().identifier.name),
-                             itr.get(ty_ident.name));
-                path_pretty_name(Ident::new(itr.gensym(s)), hash)
-            }
-        }
-    }
 }
 
 impl Visitor<()> for Ctx {
@@ -250,7 +250,7 @@ impl Visitor<()> for Ctx {
                 // Right now the ident on impls is __extensions__ which isn't
                 // very pretty when debugging, so attempt to select a better
                 // name to use.
-                let elt = self.impl_pretty_name(maybe_trait, ty, i.ident);
+                let elt = impl_pretty_name(maybe_trait, ty, i.ident);
 
                 let impl_did = ast_util::local_def(i.id);
                 for m in ms.iter() {
diff --git a/src/test/compile-fail/ambig_impl_2_exe.rs b/src/test/compile-fail/ambig_impl_2_exe.rs
index 0f5bac795e7..8cbad27ff49 100644
--- a/src/test/compile-fail/ambig_impl_2_exe.rs
+++ b/src/test/compile-fail/ambig_impl_2_exe.rs
@@ -17,4 +17,4 @@ trait me {
 }
 impl me for uint { fn me(&self) -> uint { *self } } //~ NOTE is `me$uint::me`
 fn main() { 1u.me(); } //~ ERROR multiple applicable methods in scope
-//~^ NOTE is `ambig_impl_2_lib::__extensions__::me`
+//~^ NOTE is `ambig_impl_2_lib::me$uint::me`