1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // Type Names for Debug Info.
13 use common::CodegenCx;
14 use rustc::hir::def_id::DefId;
15 use rustc::ty::subst::Substs;
16 use rustc::ty::{self, Ty};
17 use rustc_codegen_ssa::traits::*;
21 // Compute the name of the type as it should be stored in debuginfo. Does not do
22 // any caching, i.e. calling the function twice with the same type will also do
23 // the work twice. The `qualified` parameter only affects the first level of the
24 // type name, further levels (i.e. type parameters) are always fully qualified.
25 pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
29 let mut result = String::with_capacity(64);
30 push_debuginfo_type_name(cx, t, qualified, &mut result);
34 // Pushes the name of the type as it should be stored in debuginfo on the
35 // `output` String. See also compute_debuginfo_type_name().
36 pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
39 output: &mut String) {
40 // When targeting MSVC, emit C++ style type names for compatibility with
41 // .natvis visualizers (and perhaps other existing native debuggers?)
42 let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
45 ty::Bool => output.push_str("bool"),
46 ty::Char => output.push_str("char"),
47 ty::Str => output.push_str("str"),
48 ty::Never => output.push_str("!"),
49 ty::Int(int_ty) => output.push_str(int_ty.ty_to_string()),
50 ty::Uint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
51 ty::Float(float_ty) => output.push_str(float_ty.ty_to_string()),
52 ty::Foreign(def_id) => push_item_name(cx, def_id, qualified, output),
53 ty::Adt(def, substs) => {
54 push_item_name(cx, def.did, qualified, output);
55 push_type_params(cx, substs, output);
57 ty::Tuple(component_types) => {
59 for &component_type in component_types {
60 push_debuginfo_type_name(cx, component_type, true, output);
61 output.push_str(", ");
63 if !component_types.is_empty() {
69 ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
74 hir::MutImmutable => output.push_str("const "),
75 hir::MutMutable => output.push_str("mut "),
78 push_debuginfo_type_name(cx, inner_type, true, output);
84 ty::Ref(_, inner_type, mutbl) => {
88 if mutbl == hir::MutMutable {
89 output.push_str("mut ");
92 push_debuginfo_type_name(cx, inner_type, true, output);
98 ty::Array(inner_type, len) => {
100 push_debuginfo_type_name(cx, inner_type, true, output);
101 output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
104 ty::Slice(inner_type) => {
106 output.push_str("slice<");
111 push_debuginfo_type_name(cx, inner_type, true, output);
119 ty::Dynamic(ref trait_data, ..) => {
120 let principal = cx.tcx.normalize_erasing_late_bound_regions(
121 ty::ParamEnv::reveal_all(),
122 &trait_data.principal(),
124 push_item_name(cx, principal.def_id, false, output);
125 push_type_params(cx, principal.substs, output);
127 ty::FnDef(..) | ty::FnPtr(_) => {
128 let sig = t.fn_sig(cx.tcx);
129 if sig.unsafety() == hir::Unsafety::Unsafe {
130 output.push_str("unsafe ");
134 if abi != ::abi::Abi::Rust {
135 output.push_str("extern \"");
136 output.push_str(abi.name());
137 output.push_str("\" ");
140 output.push_str("fn(");
142 let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
143 if !sig.inputs().is_empty() {
144 for ¶meter_type in sig.inputs() {
145 push_debuginfo_type_name(cx, parameter_type, true, output);
146 output.push_str(", ");
153 if !sig.inputs().is_empty() {
154 output.push_str(", ...");
156 output.push_str("...");
162 if !sig.output().is_unit() {
163 output.push_str(" -> ");
164 push_debuginfo_type_name(cx, sig.output(), true, output);
168 output.push_str("closure");
170 ty::Generator(..) => {
171 output.push_str("generator");
175 ty::UnnormalizedProjection(..) |
179 ty::GeneratorWitness(..) |
181 bug!("debuginfo: Trying to create type name for \
182 unexpected type: {:?}", t);
186 fn push_item_name(cx: &CodegenCx,
189 output: &mut String) {
191 output.push_str(&cx.tcx.crate_name(def_id.krate).as_str());
192 for path_element in cx.tcx.def_path(def_id).data {
193 output.push_str("::");
194 output.push_str(&path_element.data.as_interned_str().as_str());
197 output.push_str(&cx.tcx.item_name(def_id).as_str());
201 // Pushes the type parameters in the given `Substs` to the output string.
202 // This ignores region parameters, since they can't reliably be
203 // reconstructed for items from non-local crates. For local crates, this
204 // would be possible but with inlining and LTO we have to use the least
205 // common denominator - otherwise we would run into conflicts.
206 fn push_type_params<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
207 substs: &Substs<'tcx>,
208 output: &mut String) {
209 if substs.types().next().is_none() {
215 for type_parameter in substs.types() {
216 push_debuginfo_type_name(cx, type_parameter, true, output);
217 output.push_str(", ");