about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_trans/base.rs3
-rw-r--r--src/librustc_trans/collector.rs365
-rw-r--r--src/librustc_trans/consts.rs3
-rw-r--r--src/librustc_trans/context.rs3
-rw-r--r--src/librustc_trans/glue.rs3
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/partitioning.rs5
-rw-r--r--src/librustc_trans/trans_item.rs367
8 files changed, 383 insertions, 367 deletions
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 7665b730cad..99c059d0b53 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -59,7 +59,7 @@ use callee::{Callee, CallArgs, ArgExprs, ArgVals};
 use cleanup::{self, CleanupMethods, DropHint};
 use closure;
 use common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_uint, C_integral};
-use collector::{self, TransItem, TransItemState, TransItemCollectionMode};
+use collector::{self, TransItemState, TransItemCollectionMode};
 use common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
 use common::{CrateContext, DropFlagHintsMap, Field, FunctionContext};
 use common::{Result, NodeIdAndSpan, VariantInfo};
@@ -82,6 +82,7 @@ use mir;
 use monomorphize::{self, Instance};
 use partitioning::{self, PartitioningStrategy, InstantiationMode, CodegenUnit};
 use symbol_names_test;
+use trans_item::TransItem;
 use tvec;
 use type_::Type;
 use type_of;
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index dfab2bdbf64..a6efc9030bf 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -198,27 +198,25 @@ use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
 use rustc::traits;
 use rustc::ty::subst::{self, Substs, Subst};
-use rustc::ty::{self, Ty, TypeFoldable, TyCtxt};
+use rustc::ty::{self, TypeFoldable, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::repr as mir;
 use rustc::mir::visit as mir_visit;
 use rustc::mir::visit::Visitor as MirVisitor;
 
-use syntax::ast::{self, NodeId};
 use syntax::codemap::DUMMY_SP;
-use syntax::{attr, errors};
-use syntax::parse::token;
+use syntax::errors;
 
-use base::{custom_coerce_unsize_info, llvm_linkage_by_name};
+use base::custom_coerce_unsize_info;
 use context::SharedCrateContext;
 use common::{fulfill_obligation, normalize_and_test_predicates, type_is_sized};
 use glue::{self, DropGlueKind};
-use llvm;
 use meth;
 use monomorphize::{self, Instance};
 use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap};
 
 use std::hash::{Hash, Hasher};
+use trans_item::{TransItem, type_to_string, def_id_to_string};
 
 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
 pub enum TransItemCollectionMode {
@@ -226,33 +224,6 @@ pub enum TransItemCollectionMode {
     Lazy
 }
 
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub enum TransItem<'tcx> {
-    DropGlue(DropGlueKind<'tcx>),
-    Fn(Instance<'tcx>),
-    Static(NodeId)
-}
-
-impl<'tcx> Hash for TransItem<'tcx> {
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        match *self {
-            TransItem::DropGlue(t) => {
-                0u8.hash(s);
-                t.hash(s);
-            },
-            TransItem::Fn(instance) => {
-                1u8.hash(s);
-                instance.def.hash(s);
-                (instance.substs as *const _ as usize).hash(s);
-            }
-            TransItem::Static(node_id) => {
-                2u8.hash(s);
-                node_id.hash(s);
-            }
-        };
-    }
-}
-
 /// Maps every translation item to all translation items it references in its
 /// body.
 pub struct ReferenceMap<'tcx> {
@@ -1210,334 +1181,6 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-//=-----------------------------------------------------------------------------
-// TransItem String Keys
-//=-----------------------------------------------------------------------------
-
-// The code below allows for producing a unique string key for a trans item.
-// These keys are used by the handwritten auto-tests, so they need to be
-// predictable and human-readable.
-//
-// Note: A lot of this could looks very similar to what's already in the
-//       ppaux module. It would be good to refactor things so we only have one
-//       parameterizable implementation for printing types.
-
-/// 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::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::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::TyStruct(adt_def, substs) |
-        ty::TyEnum(adt_def, substs) => {
-            push_item_name(tcx, adt_def.did, output);
-            push_type_params(tcx, &substs.types, &[], 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 "),
-            }
-
-            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 ");
-            }
-
-            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.skip_binder().def_id, output);
-            push_type_params(tcx,
-                             &trait_data.principal.skip_binder().substs.types,
-                             &trait_data.bounds.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 ");
-            }
-
-            if abi != ::abi::Abi::Rust {
-                output.push_str("extern \"");
-                output.push_str(abi.name());
-                output.push_str("\" ");
-            }
-
-            output.push_str("fn(");
-
-            let sig = tcx.erase_late_bound_regions(sig);
-            if !sig.inputs.is_empty() {
-                for &parameter_type in &sig.inputs {
-                    push_unique_type_name(tcx, 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(')');
-
-            match sig.output {
-                ty::FnConverging(result_type) if result_type.is_nil() => {}
-                ty::FnConverging(result_type) => {
-                    output.push_str(" -> ");
-                    push_unique_type_name(tcx, result_type, output);
-                }
-                ty::FnDiverging => {
-                    output.push_str(" -> !");
-                }
-            }
-        },
-        ty::TyClosure(def_id, ref 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("}");
-            push_type_params(tcx, &closure_substs.func_substs.types, &[], output);
-        }
-        ty::TyError |
-        ty::TyInfer(_) |
-        ty::TyProjection(..) |
-        ty::TyParam(_) => {
-            bug!("debuginfo: Trying to create type name for \
-                  unexpected type: {:?}", t);
-        }
-    }
-}
-
-fn push_item_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            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("::");
-
-    // foo::bar::ItemName::
-    for part in tcx.def_path(def_id).data {
-        output.push_str(&format!("{}[{}]::",
-                        part.data.as_interned_str(),
-                        part.disambiguator));
-    }
-
-    // remove final "::"
-    output.pop();
-    output.pop();
-}
-
-fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                              types: &'tcx subst::VecPerParamSpace<Ty<'tcx>>,
-                              projections: &[ty::PolyProjectionPredicate<'tcx>],
-                              output: &mut String) {
-    if types.is_empty() && projections.is_empty() {
-        return;
-    }
-
-    output.push('<');
-
-    for &type_parameter in types {
-        push_unique_type_name(tcx, type_parameter, output);
-        output.push_str(", ");
-    }
-
-    for projection in projections {
-        let projection = projection.skip_binder();
-        let name = token::get_ident_interner().get(projection.projection_ty.item_name);
-        output.push_str(&name[..]);
-        output.push_str("=");
-        push_unique_type_name(tcx, projection.ty, output);
-        output.push_str(", ");
-    }
-
-    output.pop();
-    output.pop();
-
-    output.push('>');
-}
-
-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.types, &[], output);
-}
-
-pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  def_id: DefId) -> String {
-    let mut output = String::new();
-    push_item_name(tcx, 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();
-    push_unique_type_name(tcx, ty, &mut output);
-    output
-}
-
-impl<'a, 'tcx> TransItem<'tcx> {
-    pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
-        match *self {
-            TransItem::Fn(ref instance) => {
-                let attributes = tcx.get_attrs(instance.def);
-                attr::requests_inline(&attributes[..])
-            }
-            TransItem::DropGlue(..) => true,
-            TransItem::Static(..)   => false,
-        }
-    }
-
-    pub fn is_from_extern_crate(&self) -> bool {
-        match *self {
-            TransItem::Fn(ref instance) => !instance.def.is_local(),
-            TransItem::DropGlue(..) |
-            TransItem::Static(..)   => false,
-        }
-    }
-
-    pub fn is_lazily_instantiated(&self) -> bool {
-        match *self {
-            TransItem::Fn(ref instance) => !instance.substs.types.is_empty(),
-            TransItem::DropGlue(..) => true,
-            TransItem::Static(..)   => false,
-        }
-    }
-
-    pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
-        let def_id = match *self {
-            TransItem::Fn(ref instance) => instance.def,
-            TransItem::Static(node_id) => tcx.map.local_def_id(node_id),
-            TransItem::DropGlue(..) => return None,
-        };
-
-        let attributes = tcx.get_attrs(def_id);
-        if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
-            if let Some(linkage) = llvm_linkage_by_name(&name) {
-                Some(linkage)
-            } else {
-                let span = tcx.map.span_if_local(def_id);
-                if let Some(span) = span {
-                    tcx.sess.span_fatal(span, "invalid linkage specified")
-                } else {
-                    tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
-                }
-            }
-        } else {
-            None
-        }
-    }
-
-    pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
-        let hir_map = &tcx.map;
-
-        return match *self {
-            TransItem::DropGlue(dg) => {
-                let mut s = String::with_capacity(32);
-                match dg {
-                    DropGlueKind::Ty(_) => s.push_str("drop-glue "),
-                    DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "),
-                };
-                push_unique_type_name(tcx, dg.ty(), &mut s);
-                s
-            }
-            TransItem::Fn(instance) => {
-                to_string_internal(tcx, "fn ", instance)
-            },
-            TransItem::Static(node_id) => {
-                let def_id = hir_map.local_def_id(node_id);
-                let instance = Instance::mono(tcx, def_id);
-                to_string_internal(tcx, "static ", instance)
-            },
-        };
-
-        fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        prefix: &str,
-                                        instance: Instance<'tcx>)
-                                        -> String {
-            let mut result = String::with_capacity(32);
-            result.push_str(prefix);
-            push_instance_as_string(tcx, instance, &mut result);
-            result
-        }
-    }
-
-    fn to_raw_string(&self) -> String {
-        match *self {
-            TransItem::DropGlue(dg) => {
-                format!("DropGlue({})", dg.ty() as *const _ as usize)
-            }
-            TransItem::Fn(instance) => {
-                format!("Fn({:?}, {})",
-                         instance.def,
-                         instance.substs as *const _ as usize)
-            }
-            TransItem::Static(id) => {
-                format!("Static({:?})", id)
-            }
-        }
-    }
-}
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum TransItemState {
     PredictedAndGenerated,
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 7775ed3fc68..b175f638b9e 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -21,7 +21,8 @@ use rustc::hir::map as hir_map;
 use {abi, adt, closure, debuginfo, expr, machine};
 use base::{self, exported_name, imported_name, push_ctxt};
 use callee::Callee;
-use collector::{self, TransItem};
+use collector;
+use trans_item::TransItem;
 use common::{type_is_sized, C_nil, const_get_elt};
 use common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty};
 use common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint};
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 61137d7f377..f5d943db25d 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -27,8 +27,9 @@ use glue::DropGlueKind;
 use mir::CachedMir;
 use monomorphize::Instance;
 
-use collector::{TransItem, TransItemState};
 use partitioning::CodegenUnit;
+use collector::TransItemState;
+use trans_item::TransItem;
 use type_::{Type, TypeNames};
 use rustc::ty::subst::{Substs, VecPerParamSpace};
 use rustc::ty::{self, Ty, TyCtxt};
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index a29ff95851d..10e33195305 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -29,13 +29,14 @@ use build::*;
 use callee::{Callee, ArgVals};
 use cleanup;
 use cleanup::CleanupMethods;
-use collector::{self, TransItem};
+use collector;
 use common::*;
 use debuginfo::DebugLoc;
 use declare;
 use expr;
 use machine::*;
 use monomorphize;
+use trans_item::TransItem;
 use type_of::{type_of, sizing_type_of, align_of};
 use type_::Type;
 use value::Value;
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index f48409ec755..bccb5aa050b 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -123,6 +123,7 @@ mod mir;
 mod monomorphize;
 mod partitioning;
 mod symbol_names_test;
+mod trans_item;
 mod tvec;
 mod type_;
 mod type_of;
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index 18a860f9357..eeff280a7d6 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -116,14 +116,15 @@
 //! source-level module, functions from the same module will be available for
 //! inlining, even when they are not marked #[inline].
 
-use collector::{TransItem, ReferenceMap};
+use collector::ReferenceMap;
+use llvm;
 use monomorphize;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::ty::TyCtxt;
 use rustc::ty::item_path::characteristic_def_id_of_type;
-use llvm;
 use syntax::parse::token::{self, InternedString};
+use trans_item::TransItem;
 use util::nodemap::{FnvHashMap, FnvHashSet};
 
 #[derive(Clone, Copy, Eq, PartialEq, Debug)]
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
new file mode 100644
index 00000000000..b0acd535182
--- /dev/null
+++ b/src/librustc_trans/trans_item.rs
@@ -0,0 +1,367 @@
+use base::llvm_linkage_by_name;
+use glue::DropGlueKind;
+use llvm;
+use monomorphize::Instance;
+use rustc::hir;
+use rustc::hir::def_id::DefId;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::subst;
+use std::hash::{Hash, Hasher};
+use syntax::ast::{self, NodeId};
+use syntax::attr;
+use syntax::parse::token;
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub enum TransItem<'tcx> {
+    DropGlue(DropGlueKind<'tcx>),
+    Fn(Instance<'tcx>),
+    Static(NodeId)
+}
+
+impl<'tcx> Hash for TransItem<'tcx> {
+    fn hash<H: Hasher>(&self, s: &mut H) {
+        match *self {
+            TransItem::DropGlue(t) => {
+                0u8.hash(s);
+                t.hash(s);
+            },
+            TransItem::Fn(instance) => {
+                1u8.hash(s);
+                instance.def.hash(s);
+                (instance.substs as *const _ as usize).hash(s);
+            }
+            TransItem::Static(node_id) => {
+                2u8.hash(s);
+                node_id.hash(s);
+            }
+        };
+    }
+}
+
+//=-----------------------------------------------------------------------------
+// TransItem String Keys
+//=-----------------------------------------------------------------------------
+
+// The code below allows for producing a unique string key for a trans item.
+// These keys are used by the handwritten auto-tests, so they need to be
+// predictable and human-readable.
+//
+// Note: A lot of this could looks very similar to what's already in the
+//       ppaux module. It would be good to refactor things so we only have one
+//       parameterizable implementation for printing types.
+
+/// 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::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::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::TyStruct(adt_def, substs) |
+        ty::TyEnum(adt_def, substs) => {
+            push_item_name(tcx, adt_def.did, output);
+            push_type_params(tcx, &substs.types, &[], 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 "),
+            }
+
+            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 ");
+            }
+
+            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.skip_binder().def_id, output);
+            push_type_params(tcx,
+                             &trait_data.principal.skip_binder().substs.types,
+                             &trait_data.bounds.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 ");
+            }
+
+            if abi != ::abi::Abi::Rust {
+                output.push_str("extern \"");
+                output.push_str(abi.name());
+                output.push_str("\" ");
+            }
+
+            output.push_str("fn(");
+
+            let sig = tcx.erase_late_bound_regions(sig);
+            if !sig.inputs.is_empty() {
+                for &parameter_type in &sig.inputs {
+                    push_unique_type_name(tcx, 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(')');
+
+            match sig.output {
+                ty::FnConverging(result_type) if result_type.is_nil() => {}
+                ty::FnConverging(result_type) => {
+                    output.push_str(" -> ");
+                    push_unique_type_name(tcx, result_type, output);
+                }
+                ty::FnDiverging => {
+                    output.push_str(" -> !");
+                }
+            }
+        },
+        ty::TyClosure(def_id, ref 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("}");
+            push_type_params(tcx, &closure_substs.func_substs.types, &[], output);
+        }
+        ty::TyError |
+        ty::TyInfer(_) |
+        ty::TyProjection(..) |
+        ty::TyParam(_) => {
+            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("::");
+
+    // foo::bar::ItemName::
+    for part in tcx.def_path(def_id).data {
+        output.push_str(&format!("{}[{}]::",
+                        part.data.as_interned_str(),
+                        part.disambiguator));
+    }
+
+    // remove final "::"
+    output.pop();
+    output.pop();
+}
+
+fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                              types: &'tcx subst::VecPerParamSpace<Ty<'tcx>>,
+                              projections: &[ty::PolyProjectionPredicate<'tcx>],
+                              output: &mut String) {
+    if types.is_empty() && projections.is_empty() {
+        return;
+    }
+
+    output.push('<');
+
+    for &type_parameter in types {
+        push_unique_type_name(tcx, type_parameter, output);
+        output.push_str(", ");
+    }
+
+    for projection in projections {
+        let projection = projection.skip_binder();
+        let name = token::get_ident_interner().get(projection.projection_ty.item_name);
+        output.push_str(&name[..]);
+        output.push_str("=");
+        push_unique_type_name(tcx, projection.ty, output);
+        output.push_str(", ");
+    }
+
+    output.pop();
+    output.pop();
+
+    output.push('>');
+}
+
+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.types, &[], output);
+}
+
+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
+}
+
+pub fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                ty: ty::Ty<'tcx>)
+                                -> String {
+    let mut output = String::new();
+    push_unique_type_name(tcx, ty, &mut output);
+    output
+}
+
+impl<'tcx> TransItem<'tcx> {
+
+    pub fn requests_inline<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+        match *self {
+            TransItem::Fn(ref instance) => {
+                let attributes = tcx.get_attrs(instance.def);
+                attr::requests_inline(&attributes[..])
+            }
+            TransItem::DropGlue(..) => true,
+            TransItem::Static(..)   => false,
+        }
+    }
+
+    pub fn is_from_extern_crate(&self) -> bool {
+        match *self {
+            TransItem::Fn(ref instance) => !instance.def.is_local(),
+            TransItem::DropGlue(..) |
+            TransItem::Static(..)   => false,
+        }
+    }
+
+    pub fn is_lazily_instantiated(&self) -> bool {
+        match *self {
+            TransItem::Fn(ref instance) => !instance.substs.types.is_empty(),
+            TransItem::DropGlue(..) => true,
+            TransItem::Static(..)   => false,
+        }
+    }
+
+    pub fn explicit_linkage<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
+        let def_id = match *self {
+            TransItem::Fn(ref instance) => instance.def,
+            TransItem::Static(node_id) => tcx.map.local_def_id(node_id),
+            TransItem::DropGlue(..) => return None,
+        };
+
+        let attributes = tcx.get_attrs(def_id);
+        if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
+            if let Some(linkage) = llvm_linkage_by_name(&name) {
+                Some(linkage)
+            } else {
+                let span = tcx.map.span_if_local(def_id);
+                if let Some(span) = span {
+                    tcx.sess.span_fatal(span, "invalid linkage specified")
+                } else {
+                    tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
+                }
+            }
+        } else {
+            None
+        }
+    }
+
+    pub fn to_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
+        let hir_map = &tcx.map;
+
+        return match *self {
+            TransItem::DropGlue(dg) => {
+                let mut s = String::with_capacity(32);
+                match dg {
+                    DropGlueKind::Ty(_) => s.push_str("drop-glue "),
+                    DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "),
+                };
+                push_unique_type_name(tcx, dg.ty(), &mut s);
+                s
+            }
+            TransItem::Fn(instance) => {
+                to_string_internal(tcx, "fn ", instance)
+            },
+            TransItem::Static(node_id) => {
+                let def_id = hir_map.local_def_id(node_id);
+                let instance = Instance::mono(tcx, def_id);
+                to_string_internal(tcx, "static ", instance)
+            },
+        };
+
+        fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                        prefix: &str,
+                                        instance: Instance<'tcx>)
+                                        -> String {
+            let mut result = String::with_capacity(32);
+            result.push_str(prefix);
+            push_instance_as_string(tcx, instance, &mut result);
+            result
+        }
+    }
+
+    pub fn to_raw_string(&self) -> String {
+        match *self {
+            TransItem::DropGlue(dg) => {
+                format!("DropGlue({})", dg.ty() as *const _ as usize)
+            }
+            TransItem::Fn(instance) => {
+                format!("Fn({:?}, {})",
+                         instance.def,
+                         instance.substs as *const _ as usize)
+            }
+            TransItem::Static(id) => {
+                format!("Static({:?})", id)
+            }
+        }
+    }
+}