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 super::namespace::crate_root_namespace;
15 use trans::common::CrateContext;
16 use middle::subst::{self, Substs};
17 use middle::ty::{self, Ty};
22 // Compute the name of the type as it should be stored in debuginfo. Does not do
23 // any caching, i.e. calling the function twice with the same type will also do
24 // the work twice. The `qualified` parameter only affects the first level of the
25 // type name, further levels (i.e. type parameters) are always fully qualified.
26 pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
30 let mut result = String::with_capacity(64);
31 push_debuginfo_type_name(cx, t, qualified, &mut result);
35 // Pushes the name of the type as it should be stored in debuginfo on the
36 // `output` String. See also compute_debuginfo_type_name().
37 pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
40 output: &mut String) {
42 ty::TyBool => output.push_str("bool"),
43 ty::TyChar => output.push_str("char"),
44 ty::TyStr => output.push_str("str"),
45 ty::TyInt(ast::TyIs) => output.push_str("isize"),
46 ty::TyInt(ast::TyI8) => output.push_str("i8"),
47 ty::TyInt(ast::TyI16) => output.push_str("i16"),
48 ty::TyInt(ast::TyI32) => output.push_str("i32"),
49 ty::TyInt(ast::TyI64) => output.push_str("i64"),
50 ty::TyUint(ast::TyUs) => output.push_str("usize"),
51 ty::TyUint(ast::TyU8) => output.push_str("u8"),
52 ty::TyUint(ast::TyU16) => output.push_str("u16"),
53 ty::TyUint(ast::TyU32) => output.push_str("u32"),
54 ty::TyUint(ast::TyU64) => output.push_str("u64"),
55 ty::TyFloat(ast::TyF32) => output.push_str("f32"),
56 ty::TyFloat(ast::TyF64) => output.push_str("f64"),
57 ty::TyStruct(def_id, substs) |
58 ty::TyEnum(def_id, substs) => {
59 push_item_name(cx, def_id, qualified, output);
60 push_type_params(cx, substs, output);
62 ty::TyTuple(ref component_types) => {
64 for &component_type in component_types {
65 push_debuginfo_type_name(cx, component_type, true, output);
66 output.push_str(", ");
68 if !component_types.is_empty() {
74 ty::TyBox(inner_type) => {
75 output.push_str("Box<");
76 push_debuginfo_type_name(cx, inner_type, true, output);
79 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
82 ast::MutImmutable => output.push_str("const "),
83 ast::MutMutable => output.push_str("mut "),
86 push_debuginfo_type_name(cx, inner_type, true, output);
88 ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
90 if mutbl == ast::MutMutable {
91 output.push_str("mut ");
94 push_debuginfo_type_name(cx, inner_type, true, output);
96 ty::TyArray(inner_type, len) => {
98 push_debuginfo_type_name(cx, inner_type, true, output);
99 output.push_str(&format!("; {}", len));
102 ty::TySlice(inner_type) => {
104 push_debuginfo_type_name(cx, inner_type, true, output);
107 ty::TyTrait(ref trait_data) => {
108 let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
109 push_item_name(cx, principal.def_id, false, output);
110 push_type_params(cx, principal.substs, output);
112 ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
113 if unsafety == ast::Unsafety::Unsafe {
114 output.push_str("unsafe ");
117 if abi != ::syntax::abi::Rust {
118 output.push_str("extern \"");
119 output.push_str(abi.name());
120 output.push_str("\" ");
123 output.push_str("fn(");
125 let sig = cx.tcx().erase_late_bound_regions(sig);
126 if !sig.inputs.is_empty() {
127 for ¶meter_type in &sig.inputs {
128 push_debuginfo_type_name(cx, parameter_type, true, output);
129 output.push_str(", ");
136 if !sig.inputs.is_empty() {
137 output.push_str(", ...");
139 output.push_str("...");
146 ty::FnConverging(result_type) if result_type.is_nil() => {}
147 ty::FnConverging(result_type) => {
148 output.push_str(" -> ");
149 push_debuginfo_type_name(cx, result_type, true, output);
152 output.push_str(" -> !");
156 ty::TyClosure(..) => {
157 output.push_str("closure");
161 ty::TyProjection(..) |
163 cx.sess().bug(&format!("debuginfo: Trying to create type name for \
164 unexpected type: {:?}", t));
168 fn push_item_name(cx: &CrateContext,
171 output: &mut String) {
172 cx.tcx().with_path(def_id, |path| {
174 if def_id.krate == ast::LOCAL_CRATE {
175 output.push_str(crate_root_namespace(cx));
176 output.push_str("::");
179 let mut path_element_count = 0;
180 for path_element in path {
181 output.push_str(&path_element.name().as_str());
182 output.push_str("::");
183 path_element_count += 1;
186 if path_element_count == 0 {
187 cx.sess().bug("debuginfo: Encountered empty item path!");
193 let name = path.last().expect("debuginfo: Empty item path?").name();
194 output.push_str(&name.as_str());
199 // Pushes the type parameters in the given `Substs` to the output string.
200 // This ignores region parameters, since they can't reliably be
201 // reconstructed for items from non-local crates. For local crates, this
202 // would be possible but with inlining and LTO we have to use the least
203 // common denominator - otherwise we would run into conflicts.
204 fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
205 substs: &subst::Substs<'tcx>,
206 output: &mut String) {
207 if substs.types.is_empty() {
213 for &type_parameter in &substs.types {
214 push_debuginfo_type_name(cx, type_parameter, true, output);
215 output.push_str(", ");