diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 8d6cad62e75..771cc8e6fea 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -2121,121 +2121,81 @@ pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
 /* Memory-managed object interface to type handles. */
 
 pub struct TypeNames {
-    type_names: @mut HashMap<TypeRef, @str>,
-    named_types: @mut HashMap<@str, TypeRef>
+    type_names: HashMap<TypeRef, @str>,
+    named_types: HashMap<@str, TypeRef>
 }
 
-pub fn associate_type(tn: @TypeNames, s: @str, t: TypeRef) {
-    assert!(tn.type_names.insert(t, s));
-    assert!(tn.named_types.insert(s, t));
-}
-
-pub fn type_has_name(tn: @TypeNames, t: TypeRef) -> Option<@str> {
-    return tn.type_names.find(&t).map_consume(|x| *x);
-}
-
-pub fn name_has_type(tn: @TypeNames, s: @str) -> Option<TypeRef> {
-    return tn.named_types.find(&s).map_consume(|x| *x);
-}
-
-pub fn mk_type_names() -> @TypeNames {
-    @TypeNames {
-        type_names: @mut HashMap::new(),
-        named_types: @mut HashMap::new()
+impl TypeNames {
+    pub fn new() -> TypeNames {
+        TypeNames {
+            type_names: HashMap::new(),
+            named_types: HashMap::new()
+        }
     }
-}
 
-pub fn type_to_str(names: @TypeNames, ty: TypeRef) -> @str {
-    return type_to_str_inner(names, [], ty);
-}
+    pub fn associate_type(&mut self, s: @str, t: TypeRef) {
+        assert!(self.type_names.insert(t, s));
+        assert!(self.named_types.insert(s, t));
+    }
 
-pub fn type_to_str_inner(names: @TypeNames, outer0: &[TypeRef], ty: TypeRef)
-                      -> @str {
-    unsafe {
-        match type_has_name(names, ty) {
-          option::Some(n) => return n,
-          _ => {}
+    pub fn find_name(&self, ty: &TypeRef) -> Option<@str> {
+        self.type_names.find_copy(ty)
+    }
+
+    pub fn find_type(&self, s: &str) -> Option<TypeRef> {
+        self.named_types.find_equiv(s).map_consume(|x| *x)
+    }
+
+    pub fn type_to_str(&self, ty: TypeRef) -> ~str {
+        match self.find_name(&ty) {
+            option::Some(name) => return name.to_owned(),
+            None => ()
         }
 
-        let outer = vec::append_one(outer0.to_owned(), ty);
+        unsafe {
+            let kind = llvm::LLVMGetTypeKind(ty);
 
-        let kind = llvm::LLVMGetTypeKind(ty);
+            match kind {
+                Void => ~"Void",
+                Half => ~"Half",
+                Double => ~"Double",
+                X86_FP80 => ~"X86_FP80",
+                FP128 => ~"FP128",
+                PPC_FP128 => ~"PPC_FP128",
+                Label => ~"Label",
+                Vector => ~"Vector",
+                Metadata => ~"Metadata",
+                X86_MMX => ~"X86_MMAX",
+                Integer => {
+                    fmt!("i%d", llvm::LLVMGetIntTypeWidth(ty) as int)
+                }
+                Function => {
+                    let out_ty = llvm::LLVMGetReturnType(ty);
+                    let n_args = llvm::LLVMCountParamTypes(ty) as uint;
+                    let args = vec::from_elem(n_args, 0 as TypeRef);
+                    llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args));
 
-        fn tys_str(names: @TypeNames, outer: &[TypeRef],
-                   tys: ~[TypeRef]) -> @str {
-            let mut s = ~"";
-            let mut first: bool = true;
-            for tys.each |t| {
-                if first { first = false; } else { s += ", "; }
-                s += type_to_str_inner(names, outer, *t);
-            }
-            // [Note at-str] FIXME #2543: Could rewrite this without the copy,
-            // but need better @str support.
-            return s.to_managed();
-        }
-
-        match kind {
-          Void => return @"Void",
-          Half => return @"Half",
-          Float => return @"Float",
-          Double => return @"Double",
-          X86_FP80 => return @"X86_FP80",
-          FP128 => return @"FP128",
-          PPC_FP128 => return @"PPC_FP128",
-          Label => return @"Label",
-          Integer => {
-            // See [Note at-str]
-            return fmt!("i%d", llvm::LLVMGetIntTypeWidth(ty)
-                        as int).to_managed();
-          }
-          Function => {
-            let out_ty: TypeRef = llvm::LLVMGetReturnType(ty);
-            let n_args = llvm::LLVMCountParamTypes(ty) as uint;
-            let args = vec::from_elem(n_args, 0 as TypeRef);
-            llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args));
-            // See [Note at-str]
-            return fmt!("fn(%s) -> %s",
-                        tys_str(names, outer, args),
-                        type_to_str_inner(names, outer, out_ty)).to_managed();
-          }
-          Struct => {
-            let elts = struct_tys(ty);
-            // See [Note at-str]
-            return fmt!("{%s}", tys_str(names, outer, elts)).to_managed();
-          }
-          Array => {
-            let el_ty = llvm::LLVMGetElementType(ty);
-            // See [Note at-str]
-            return fmt!("[%s@ x %u", type_to_str_inner(names, outer, el_ty),
-                llvm::LLVMGetArrayLength(ty) as uint).to_managed();
-          }
-          Pointer => {
-            let mut i = 0;
-            for outer0.each |tout| {
-                i += 1;
-                if *tout as int == ty as int {
-                    let n = outer0.len() - i;
-                    // See [Note at-str]
-                    return fmt!("*\\%d", n as int).to_managed();
+                    let args = args.map(|&ty| self.type_to_str(ty)).connect(", ");
+                    let out_ty = self.type_to_str(out_ty);
+                    fmt!("fn(%s) -> %s", args, out_ty)
+                }
+                Struct => {
+                    let tys = struct_tys(ty);
+                    let tys = tys.map(|ty| self.type_to_str(ty)).connect(", ");
+                    fmt!("{%s}", tys)
+                }
+                Array => {
+                    let el_ty = llvm::LLVMGetElementType(ty);
+                    let el_ty = self.type_to_str(el_ty);
+                    let len = llvm::LLVMGetArrayLength(ty) as uint;
+                    fmt!("[%s x %u]", el_ty, len)
+                }
+                Pointer => {
+                    let el_ty = llvm::LLVMGetElementType(ty);
+                    let el_ty = self.type_to_str(el_ty);
+                    fmt!("*%s", el_ty)
                 }
             }
-            let addrstr = {
-                let addrspace = llvm::LLVMGetPointerAddressSpace(ty) as uint;
-                if addrspace == 0 {
-                    ~""
-                } else {
-                    fmt!("addrspace(%u)", addrspace)
-                }
-            };
-            // See [Note at-str]
-            return fmt!("%s*%s", addrstr, type_to_str_inner(names,
-                        outer,
-                        llvm::LLVMGetElementType(ty))).to_managed();
-          }
-          Vector => return @"Vector",
-          Metadata => return @"Metadata",
-          X86_MMX => return @"X86_MMAX",
-          _ => fail!()
         }
     }
 }
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index d6c7472424f..8391ff95599 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -46,7 +46,7 @@ pub struct CrateContext {
      llmod: ModuleRef,
      llcx: ContextRef,
      td: TargetData,
-     tn: @TypeNames,
+     tn: TypeNames,
      externs: ExternMap,
      intrinsics: HashMap<&'static str, ValueRef>,
      item_vals: HashMap<ast::node_id, ValueRef>,
@@ -136,8 +136,10 @@ impl CrateContext {
             str::as_c_str(data_layout, |buf| llvm::LLVMSetDataLayout(llmod, buf));
             str::as_c_str(targ_triple, |buf| llvm::LLVMSetTarget(llmod, buf));
             let targ_cfg = sess.targ_cfg;
+
             let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
-            let tn = mk_type_names();
+            let tn = TypeNames::new();
+
             let mut intrinsics = base::declare_intrinsics(llmod);
             if sess.opts.extra_debuginfo {
                 base::declare_dbg_intrinsics(llmod, &mut intrinsics);
@@ -145,7 +147,7 @@ impl CrateContext {
             let int_type = T_int(targ_cfg);
             let float_type = T_float(targ_cfg);
             let tydesc_type = T_tydesc(targ_cfg);
-            lib::llvm::associate_type(tn, @"tydesc", tydesc_type);
+            tn.associate_type(@"tydesc", tydesc_type);
             let crate_map = decl_crate_map(sess, link_meta, llmod);
             let dbg_cx = if sess.opts.debuginfo {
                 Some(debuginfo::DebugContext::new(llmod, name.to_owned()))