about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_data_structures/base_n.rs64
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_incremental/persist/fs.rs55
-rw-r--r--src/librustc_trans/base.rs12
-rw-r--r--src/librustc_trans/collector.rs20
-rw-r--r--src/librustc_trans/context.rs7
-rw-r--r--src/librustc_trans/trans_item.rs377
-rw-r--r--src/librustc_trans/type_of.rs30
8 files changed, 318 insertions, 248 deletions
diff --git a/src/librustc_data_structures/base_n.rs b/src/librustc_data_structures/base_n.rs
new file mode 100644
index 00000000000..bf3e682f86f
--- /dev/null
+++ b/src/librustc_data_structures/base_n.rs
@@ -0,0 +1,64 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Convert unsigned integers into a string representation with some base.
+/// Bases up to and including 36 can be used for case-insensitive things.
+
+use std::str;
+
+pub const MAX_BASE: u64 = 64;
+const BASE_64: &'static [u8; MAX_BASE as usize] =
+    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
+
+#[inline]
+pub fn push_str(mut n: u64, base: u64, output: &mut String) {
+    debug_assert!(base >= 2 && base <= MAX_BASE);
+    let mut s = [0u8; 64];
+    let mut index = 0;
+
+    loop {
+        s[index] = BASE_64[(n % base) as usize];
+        index += 1;
+        n /= base;
+
+        if n == 0 {
+            break;
+        }
+    }
+    &mut s[0..index].reverse();
+    output.push_str(str::from_utf8(&s[0..index]).unwrap());
+}
+
+#[inline]
+pub fn encode(n: u64, base: u64) -> String {
+    let mut s = String::with_capacity(13);
+    push_str(n, base, &mut s);
+    s
+}
+
+#[test]
+fn test_encode() {
+    fn test(n: u64, base: u64) {
+        assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base)[..], base as u32));
+    }
+
+    for base in 2..37 {
+        test(0, base);
+        test(1, base);
+        test(35, base);
+        test(36, base);
+        test(37, base);
+        test(u64::max_value(), base);
+
+        for i in 0 .. 1_000 {
+            test(i * 983, base);
+        }
+    }
+}
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 2e4206d2ee1..de13b9bf4be 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -47,6 +47,7 @@ extern crate libc;
 pub mod array_vec;
 pub mod accumulate_vec;
 pub mod small_vec;
+pub mod base_n;
 pub mod bitslice;
 pub mod blake2b;
 pub mod bitvec;
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index ca9c1192023..223200957cb 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -119,7 +119,7 @@ use rustc::hir::svh::Svh;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc::util::fs as fs_util;
-use rustc_data_structures::flock;
+use rustc_data_structures::{flock, base_n};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 
 use std::ffi::OsString;
@@ -135,6 +135,12 @@ const DEP_GRAPH_FILENAME: &'static str = "dep-graph.bin";
 const WORK_PRODUCTS_FILENAME: &'static str = "work-products.bin";
 const METADATA_HASHES_FILENAME: &'static str = "metadata.bin";
 
+// We encode integers using the following base, so they are shorter than decimal
+// or hexadecimal numbers (we want short file and directory names). Since these
+// numbers will be used in file names, we choose an encoding that is not
+// case-sensitive (as opposed to base64, for example).
+const INT_ENCODE_BASE: u64 = 36;
+
 pub fn dep_graph_path(sess: &Session) -> PathBuf {
     in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME)
 }
@@ -327,7 +333,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) {
     let mut new_sub_dir_name = String::from(&old_sub_dir_name[.. dash_indices[2] + 1]);
 
     // Append the svh
-    new_sub_dir_name.push_str(&encode_base_36(svh.as_u64()));
+    base_n::push_str(svh.as_u64(), INT_ENCODE_BASE, &mut new_sub_dir_name);
 
     // Create the full path
     let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name);
@@ -433,7 +439,8 @@ fn generate_session_dir_path(crate_dir: &Path) -> PathBuf {
 
     let directory_name = format!("s-{}-{}-working",
                                   timestamp,
-                                  encode_base_36(random_number as u64));
+                                  base_n::encode(random_number as u64,
+                                                 INT_ENCODE_BASE));
     debug!("generate_session_dir_path: directory_name = {}", directory_name);
     let directory_path = crate_dir.join(directory_name);
     debug!("generate_session_dir_path: directory_path = {}", directory_path.display());
@@ -562,27 +569,11 @@ fn extract_timestamp_from_session_dir(directory_name: &str)
     string_to_timestamp(&directory_name[dash_indices[0]+1 .. dash_indices[1]])
 }
 
-const BASE_36: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyz";
-
-fn encode_base_36(mut n: u64) -> String {
-    let mut s = Vec::with_capacity(13);
-    loop {
-        s.push(BASE_36[(n % 36) as usize]);
-        n /= 36;
-
-        if n == 0 {
-            break;
-        }
-    }
-    s.reverse();
-    String::from_utf8(s).unwrap()
-}
-
 fn timestamp_to_string(timestamp: SystemTime) -> String {
     let duration = timestamp.duration_since(UNIX_EPOCH).unwrap();
     let micros = duration.as_secs() * 1_000_000 +
                 (duration.subsec_nanos() as u64) / 1000;
-    encode_base_36(micros)
+    base_n::encode(micros, INT_ENCODE_BASE)
 }
 
 fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
@@ -629,7 +620,7 @@ pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option<PathBuf>
     };
 
     let target_svh = tcx.sess.cstore.crate_hash(cnum);
-    let target_svh = encode_base_36(target_svh.as_u64());
+    let target_svh = base_n::encode(target_svh.as_u64(), INT_ENCODE_BASE);
 
     let sub_dir = find_metadata_hashes_iter(&target_svh, dir_entries.filter_map(|e| {
         e.ok().map(|e| e.file_name().to_string_lossy().into_owned())
@@ -677,7 +668,9 @@ fn crate_path(sess: &Session,
     let mut hasher = DefaultHasher::new();
     crate_disambiguator.hash(&mut hasher);
 
-    let crate_name = format!("{}-{}", crate_name, encode_base_36(hasher.finish()));
+    let crate_name = format!("{}-{}",
+                             crate_name,
+                             base_n::encode(hasher.finish(), INT_ENCODE_BASE));
     incr_dir.join(crate_name)
 }
 
@@ -1049,21 +1042,3 @@ fn test_find_metadata_hashes_iter()
         None
     );
 }
-
-#[test]
-fn test_encode_base_36() {
-    fn test(n: u64) {
-        assert_eq!(Ok(n), u64::from_str_radix(&encode_base_36(n)[..], 36));
-    }
-
-    test(0);
-    test(1);
-    test(35);
-    test(36);
-    test(37);
-    test(u64::max_value());
-
-    for i in 0 .. 1_000 {
-        test(i * 983);
-    }
-}
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index c7cad6455bc..0c0b7fbf4af 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -74,7 +74,7 @@ use monomorphize::{self, Instance};
 use partitioning::{self, PartitioningStrategy, CodegenUnit};
 use symbol_map::SymbolMap;
 use symbol_names_test;
-use trans_item::TransItem;
+use trans_item::{TransItem, DefPathBasedNames};
 use type_::Type;
 use type_of;
 use value::Value;
@@ -1004,7 +1004,15 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
 }
 
 pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
-    let _s = StatRecorder::new(ccx, ccx.tcx().item_path_str(instance.def));
+    let _s = if ccx.sess().trans_stats() {
+        let mut instance_name = String::new();
+        DefPathBasedNames::new(ccx.tcx(), true, true)
+            .push_def_path(instance.def, &mut instance_name);
+        Some(StatRecorder::new(ccx, instance_name))
+    } else {
+        None
+    };
+
     // this is an info! to allow collecting monomorphization statistics
     // and to allow finding the last function before LLVM aborts from
     // release builds.
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 2728a666556..0fc6436e63c 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -213,7 +213,7 @@ use glue::{self, DropGlueKind};
 use monomorphize::{self, Instance};
 use util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
 
-use trans_item::{TransItem, type_to_string, def_id_to_string};
+use trans_item::{TransItem, DefPathBasedNames};
 
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
@@ -1234,3 +1234,21 @@ fn visit_mir_and_promoted<'tcx, V: MirVisitor<'tcx>>(mut visitor: V, mir: &mir::
         visitor.visit_mir(promoted);
     }
 }
+
+fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              def_id: DefId)
+                              -> String {
+    let mut output = String::new();
+    let printer = DefPathBasedNames::new(tcx, false, false);
+    printer.push_def_path(def_id, &mut output);
+    output
+}
+
+fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            ty: ty::Ty<'tcx>)
+                            -> String {
+    let mut output = String::new();
+    let printer = DefPathBasedNames::new(tcx, false, false);
+    printer.push_type_name(ty, &mut output);
+    output
+}
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 3930bcbdd9a..f7af2d6b855 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -26,6 +26,7 @@ use monomorphize::Instance;
 use partitioning::CodegenUnit;
 use trans_item::TransItem;
 use type_::Type;
+use rustc_data_structures::base_n;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use session::config::NoDebugInfo;
@@ -975,7 +976,11 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         self.local().local_gen_sym_counter.set(idx + 1);
         // Include a '.' character, so there can be no accidental conflicts with
         // user defined names
-        format!("{}.{}", prefix, idx)
+        let mut name = String::with_capacity(prefix.len() + 6);
+        name.push_str(prefix);
+        name.push_str(".");
+        base_n::push_str(idx as u64, base_n::MAX_BASE, &mut name);
+        name
     }
 }
 
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index c5a7dbbcf54..94a68de7f86 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -34,6 +34,7 @@ use type_of;
 use glue;
 use abi::{Abi, FnType};
 use back::symbol_names;
+use std::fmt::Write;
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum TransItem<'tcx> {
@@ -307,7 +308,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
                     DropGlueKind::Ty(_) => s.push_str("drop-glue "),
                     DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "),
                 };
-                push_unique_type_name(tcx, dg.ty(), &mut s);
+                let printer = DefPathBasedNames::new(tcx, false, false);
+                printer.push_type_name(dg.ty(), &mut s);
                 s
             }
             TransItem::Fn(instance) => {
@@ -326,7 +328,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
                                         -> String {
             let mut result = String::with_capacity(32);
             result.push_str(prefix);
-            push_instance_as_string(tcx, instance, &mut result);
+            let printer = DefPathBasedNames::new(tcx, false, false);
+            printer.push_instance_as_string(instance, &mut result);
             result
         }
     }
@@ -367,209 +370,219 @@ impl<'a, 'tcx> TransItem<'tcx> {
 
 /// Same as `unique_type_name()` but with the result pushed onto the given
 /// `output` parameter.
-pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                       t: Ty<'tcx>,
-                                       output: &mut String) {
-    match t.sty {
-        ty::TyBool              => output.push_str("bool"),
-        ty::TyChar              => output.push_str("char"),
-        ty::TyStr               => output.push_str("str"),
-        ty::TyNever             => output.push_str("!"),
-        ty::TyInt(ast::IntTy::Is)    => output.push_str("isize"),
-        ty::TyInt(ast::IntTy::I8)    => output.push_str("i8"),
-        ty::TyInt(ast::IntTy::I16)   => output.push_str("i16"),
-        ty::TyInt(ast::IntTy::I32)   => output.push_str("i32"),
-        ty::TyInt(ast::IntTy::I64)   => output.push_str("i64"),
-        ty::TyUint(ast::UintTy::Us)   => output.push_str("usize"),
-        ty::TyUint(ast::UintTy::U8)   => output.push_str("u8"),
-        ty::TyUint(ast::UintTy::U16)  => output.push_str("u16"),
-        ty::TyUint(ast::UintTy::U32)  => output.push_str("u32"),
-        ty::TyUint(ast::UintTy::U64)  => output.push_str("u64"),
-        ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
-        ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
-        ty::TyAdt(adt_def, substs) => {
-            push_item_name(tcx, adt_def.did, output);
-            push_type_params(tcx, substs, &[], output);
-        },
-        ty::TyTuple(component_types) => {
-            output.push('(');
-            for &component_type in component_types {
-                push_unique_type_name(tcx, component_type, output);
-                output.push_str(", ");
-            }
-            if !component_types.is_empty() {
-                output.pop();
-                output.pop();
-            }
-            output.push(')');
-        },
-        ty::TyBox(inner_type) => {
-            output.push_str("Box<");
-            push_unique_type_name(tcx, inner_type, output);
-            output.push('>');
-        },
-        ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
-            output.push('*');
-            match mutbl {
-                hir::MutImmutable => output.push_str("const "),
-                hir::MutMutable => output.push_str("mut "),
-            }
+pub struct DefPathBasedNames<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    omit_disambiguators: bool,
+    omit_local_crate_name: bool,
+}
 
-            push_unique_type_name(tcx, inner_type, output);
-        },
-        ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
-            output.push('&');
-            if mutbl == hir::MutMutable {
-                output.push_str("mut ");
-            }
+impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               omit_disambiguators: bool,
+               omit_local_crate_name: bool)
+               -> Self {
+        DefPathBasedNames {
+            tcx: tcx,
+            omit_disambiguators: omit_disambiguators,
+            omit_local_crate_name: omit_local_crate_name,
+        }
+    }
 
-            push_unique_type_name(tcx, inner_type, output);
-        },
-        ty::TyArray(inner_type, len) => {
-            output.push('[');
-            push_unique_type_name(tcx, inner_type, output);
-            output.push_str(&format!("; {}", len));
-            output.push(']');
-        },
-        ty::TySlice(inner_type) => {
-            output.push('[');
-            push_unique_type_name(tcx, inner_type, output);
-            output.push(']');
-        },
-        ty::TyTrait(ref trait_data) => {
-            push_item_name(tcx, trait_data.principal.def_id(), output);
-            push_type_params(tcx,
-                             trait_data.principal.skip_binder().substs,
-                             &trait_data.projection_bounds,
-                             output);
-        },
-        ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
-        ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
-            if unsafety == hir::Unsafety::Unsafe {
-                output.push_str("unsafe ");
-            }
+    pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
+        match t.sty {
+            ty::TyBool              => output.push_str("bool"),
+            ty::TyChar              => output.push_str("char"),
+            ty::TyStr               => output.push_str("str"),
+            ty::TyNever             => output.push_str("!"),
+            ty::TyInt(ast::IntTy::Is)    => output.push_str("isize"),
+            ty::TyInt(ast::IntTy::I8)    => output.push_str("i8"),
+            ty::TyInt(ast::IntTy::I16)   => output.push_str("i16"),
+            ty::TyInt(ast::IntTy::I32)   => output.push_str("i32"),
+            ty::TyInt(ast::IntTy::I64)   => output.push_str("i64"),
+            ty::TyUint(ast::UintTy::Us)   => output.push_str("usize"),
+            ty::TyUint(ast::UintTy::U8)   => output.push_str("u8"),
+            ty::TyUint(ast::UintTy::U16)  => output.push_str("u16"),
+            ty::TyUint(ast::UintTy::U32)  => output.push_str("u32"),
+            ty::TyUint(ast::UintTy::U64)  => output.push_str("u64"),
+            ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
+            ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
+            ty::TyAdt(adt_def, substs) => {
+                self.push_def_path(adt_def.did, output);
+                self.push_type_params(substs, &[], output);
+            },
+            ty::TyTuple(component_types) => {
+                output.push('(');
+                for &component_type in component_types {
+                    self.push_type_name(component_type, output);
+                    output.push_str(", ");
+                }
+                if !component_types.is_empty() {
+                    output.pop();
+                    output.pop();
+                }
+                output.push(')');
+            },
+            ty::TyBox(inner_type) => {
+                output.push_str("Box<");
+                self.push_type_name(inner_type, output);
+                output.push('>');
+            },
+            ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
+                output.push('*');
+                match mutbl {
+                    hir::MutImmutable => output.push_str("const "),
+                    hir::MutMutable => output.push_str("mut "),
+                }
 
-            if abi != ::abi::Abi::Rust {
-                output.push_str("extern \"");
-                output.push_str(abi.name());
-                output.push_str("\" ");
-            }
+                self.push_type_name(inner_type, output);
+            },
+            ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
+                output.push('&');
+                if mutbl == hir::MutMutable {
+                    output.push_str("mut ");
+                }
 
-            output.push_str("fn(");
+                self.push_type_name(inner_type, output);
+            },
+            ty::TyArray(inner_type, len) => {
+                output.push('[');
+                self.push_type_name(inner_type, output);
+                write!(output, "; {}", len).unwrap();
+                output.push(']');
+            },
+            ty::TySlice(inner_type) => {
+                output.push('[');
+                self.push_type_name(inner_type, output);
+                output.push(']');
+            },
+            ty::TyTrait(ref trait_data) => {
+                self.push_def_path(trait_data.principal.def_id(), output);
+                self.push_type_params(trait_data.principal.skip_binder().substs,
+                                      &trait_data.projection_bounds,
+                                      output);
+            },
+            ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
+            ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+                if unsafety == hir::Unsafety::Unsafe {
+                    output.push_str("unsafe ");
+                }
 
-            let sig = tcx.erase_late_bound_regions_and_normalize(sig);
-            if !sig.inputs.is_empty() {
-                for &parameter_type in &sig.inputs {
-                    push_unique_type_name(tcx, parameter_type, output);
-                    output.push_str(", ");
+                if abi != ::abi::Abi::Rust {
+                    output.push_str("extern \"");
+                    output.push_str(abi.name());
+                    output.push_str("\" ");
                 }
-                output.pop();
-                output.pop();
-            }
 
-            if sig.variadic {
-                if !sig.inputs.is_empty() {
-                    output.push_str(", ...");
-                } else {
-                    output.push_str("...");
+                output.push_str("fn(");
+
+                let ty::FnSig {
+                    inputs: sig_inputs,
+                    output: sig_output,
+                    variadic: sig_variadic
+                } = self.tcx.erase_late_bound_regions_and_normalize(sig);
+
+                if !sig_inputs.is_empty() {
+                    for &parameter_type in &sig_inputs {
+                        self.push_type_name(parameter_type, output);
+                        output.push_str(", ");
+                    }
+                    output.pop();
+                    output.pop();
+                }
+
+                if sig_variadic {
+                    if !sig_inputs.is_empty() {
+                        output.push_str(", ...");
+                    } else {
+                        output.push_str("...");
+                    }
                 }
-            }
 
-            output.push(')');
+                output.push(')');
 
-            if !sig.output.is_nil() {
-                output.push_str(" -> ");
-                push_unique_type_name(tcx, sig.output, output);
+                if !sig_output.is_nil() {
+                    output.push_str(" -> ");
+                    self.push_type_name(sig_output, output);
+                }
+            },
+            ty::TyClosure(def_id, ref closure_substs) => {
+                self.push_def_path(def_id, output);
+                let generics = self.tcx.item_generics(self.tcx.closure_base_def_id(def_id));
+                let substs = closure_substs.substs.truncate_to(self.tcx, generics);
+                self.push_type_params(substs, &[], output);
+            }
+            ty::TyError |
+            ty::TyInfer(_) |
+            ty::TyProjection(..) |
+            ty::TyParam(_) |
+            ty::TyAnon(..) => {
+                bug!("DefPathBasedNames: Trying to create type name for \
+                                         unexpected type: {:?}", t);
             }
-        },
-        ty::TyClosure(def_id, closure_substs) => {
-            push_item_name(tcx, def_id, output);
-            output.push_str("{");
-            output.push_str(&format!("{}:{}", def_id.krate, def_id.index.as_usize()));
-            output.push_str("}");
-            let generics = tcx.item_generics(tcx.closure_base_def_id(def_id));
-            let substs = closure_substs.substs.truncate_to(tcx, generics);
-            push_type_params(tcx, substs, &[], output);
-        }
-        ty::TyError |
-        ty::TyInfer(_) |
-        ty::TyProjection(..) |
-        ty::TyParam(_) |
-        ty::TyAnon(..) => {
-            bug!("debuginfo: Trying to create type name for \
-                  unexpected type: {:?}", t);
         }
     }
-}
-
-fn push_item_name(tcx: TyCtxt,
-                  def_id: DefId,
-                  output: &mut String) {
-    let def_path = tcx.def_path(def_id);
 
-    // some_crate::
-    output.push_str(&tcx.crate_name(def_path.krate));
-    output.push_str("::");
+    pub fn push_def_path(&self,
+                         def_id: DefId,
+                         output: &mut String) {
+        let def_path = self.tcx.def_path(def_id);
 
-    // foo::bar::ItemName::
-    for part in tcx.def_path(def_id).data {
-        output.push_str(&format!("{}[{}]::",
-                        part.data.as_interned_str(),
-                        part.disambiguator));
-    }
+        // some_crate::
+        if !(self.omit_local_crate_name && def_id.is_local()) {
+            output.push_str(&self.tcx.crate_name(def_path.krate));
+            output.push_str("::");
+        }
 
-    // remove final "::"
-    output.pop();
-    output.pop();
-}
+        // foo::bar::ItemName::
+        for part in self.tcx.def_path(def_id).data {
+            if self.omit_disambiguators {
+                write!(output, "{}::", part.data.as_interned_str()).unwrap();
+            } else {
+                write!(output, "{}[{}]::",
+                       part.data.as_interned_str(),
+                       part.disambiguator).unwrap();
+            }
+        }
 
-fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              substs: &Substs<'tcx>,
-                              projections: &[ty::PolyExistentialProjection<'tcx>],
-                              output: &mut String) {
-    if substs.types().next().is_none() && projections.is_empty() {
-        return;
+        // remove final "::"
+        output.pop();
+        output.pop();
     }
 
-    output.push('<');
-
-    for type_parameter in substs.types() {
-        push_unique_type_name(tcx, type_parameter, output);
-        output.push_str(", ");
-    }
+    pub fn push_type_params(&self,
+                            substs: &Substs<'tcx>,
+                            projections: &[ty::PolyExistentialProjection<'tcx>],
+                            output: &mut String) {
+        if substs.types().next().is_none() && projections.is_empty() {
+            return;
+        }
 
-    for projection in projections {
-        let projection = projection.skip_binder();
-        let name = &projection.item_name.as_str();
-        output.push_str(name);
-        output.push_str("=");
-        push_unique_type_name(tcx, projection.ty, output);
-        output.push_str(", ");
-    }
+        output.push('<');
 
-    output.pop();
-    output.pop();
+        for type_parameter in substs.types() {
+            self.push_type_name(type_parameter, output);
+            output.push_str(", ");
+        }
 
-    output.push('>');
-}
+        for projection in projections {
+            let projection = projection.skip_binder();
+            let name = &projection.item_name.as_str();
+            output.push_str(name);
+            output.push_str("=");
+            self.push_type_name(projection.ty, output);
+            output.push_str(", ");
+        }
 
-fn push_instance_as_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     instance: Instance<'tcx>,
-                                     output: &mut String) {
-    push_item_name(tcx, instance.def, output);
-    push_type_params(tcx, instance.substs, &[], output);
-}
+        output.pop();
+        output.pop();
 
-pub fn def_id_to_string(tcx: TyCtxt, def_id: DefId) -> String {
-    let mut output = String::new();
-    push_item_name(tcx, def_id, &mut output);
-    output
-}
+        output.push('>');
+    }
 
-pub fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                ty: Ty<'tcx>)
-                                -> String {
-    let mut output = String::new();
-    push_unique_type_name(tcx, ty, &mut output);
-    output
+    pub fn push_instance_as_string(&self,
+                                   instance: Instance<'tcx>,
+                                   output: &mut String) {
+        self.push_def_path(instance.def, output);
+        self.push_type_params(instance.substs, &[], output);
+    }
 }
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index dc794d5946a..16d4f97200c 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -10,14 +10,12 @@
 
 #![allow(non_camel_case_types)]
 
-use rustc::hir::def_id::DefId;
 use abi::FnType;
 use adt;
 use common::*;
 use machine;
 use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::ty::subst::Substs;
-
+use trans_item::DefPathBasedNames;
 use type_::Type;
 
 use syntax::ast;
@@ -282,12 +280,12 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           let n = t.simd_size(cx.tcx()) as u64;
           Type::vector(&llet, n)
       }
-      ty::TyAdt(def, substs) => {
+      ty::TyAdt(..) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache. This
           // avoids creating more than one copy of the enum when one
           // of the enum's variants refers to the enum itself.
-          let name = llvm_type_name(cx, def.did, substs);
+          let name = llvm_type_name(cx, t);
           adt::incomplete_type_of(cx, t, &name[..])
       }
 
@@ -319,21 +317,9 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     layout.align(&cx.tcx().data_layout).abi() as machine::llalign
 }
 
-fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                            did: DefId,
-                            substs: &Substs<'tcx>)
-                            -> String {
-    let base = cx.tcx().item_path_str(did);
-    let strings: Vec<String> = substs.types().map(|t| t.to_string()).collect();
-    let tstr = if strings.is_empty() {
-        base
-    } else {
-        format!("{}<{}>", base, strings.join(", "))
-    };
-
-    if did.is_local() {
-        tstr
-    } else {
-        format!("{}.{}", did.krate, tstr)
-    }
+fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> String {
+    let mut name = String::with_capacity(32);
+    let printer = DefPathBasedNames::new(cx.tcx(), true, true);
+    printer.push_type_name(ty, &mut name);
+    name
 }