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, ClosureTyper}
;
19 use syntax
::parse
::token
;
23 // Compute the name of the type as it should be stored in debuginfo. Does not do
24 // any caching, i.e. calling the function twice with the same type will also do
25 // the work twice. The `qualified` parameter only affects the first level of the
26 // type name, further levels (i.e. type parameters) are always fully qualified.
27 pub fn compute_debuginfo_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
31 let mut result
= String
::with_capacity(64);
32 push_debuginfo_type_name(cx
, t
, qualified
, &mut result
);
36 // Pushes the name of the type as it should be stored in debuginfo on the
37 // `output` String. See also compute_debuginfo_type_name().
38 pub fn push_debuginfo_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
41 output
: &mut String
) {
43 ty
::ty_bool
=> output
.push_str("bool"),
44 ty
::ty_char
=> output
.push_str("char"),
45 ty
::ty_str
=> output
.push_str("str"),
46 ty
::ty_int(ast
::TyIs
) => output
.push_str("isize"),
47 ty
::ty_int(ast
::TyI8
) => output
.push_str("i8"),
48 ty
::ty_int(ast
::TyI16
) => output
.push_str("i16"),
49 ty
::ty_int(ast
::TyI32
) => output
.push_str("i32"),
50 ty
::ty_int(ast
::TyI64
) => output
.push_str("i64"),
51 ty
::ty_uint(ast
::TyUs
) => output
.push_str("usize"),
52 ty
::ty_uint(ast
::TyU8
) => output
.push_str("u8"),
53 ty
::ty_uint(ast
::TyU16
) => output
.push_str("u16"),
54 ty
::ty_uint(ast
::TyU32
) => output
.push_str("u32"),
55 ty
::ty_uint(ast
::TyU64
) => output
.push_str("u64"),
56 ty
::ty_float(ast
::TyF32
) => output
.push_str("f32"),
57 ty
::ty_float(ast
::TyF64
) => output
.push_str("f64"),
58 ty
::ty_struct(def_id
, substs
) |
59 ty
::ty_enum(def_id
, substs
) => {
60 push_item_name(cx
, def_id
, qualified
, output
);
61 push_type_params(cx
, substs
, output
);
63 ty
::ty_tup(ref component_types
) => {
65 for &component_type
in component_types
{
66 push_debuginfo_type_name(cx
, component_type
, true, output
);
67 output
.push_str(", ");
69 if !component_types
.is_empty() {
75 ty
::ty_uniq(inner_type
) => {
76 output
.push_str("Box<");
77 push_debuginfo_type_name(cx
, inner_type
, true, output
);
80 ty
::ty_ptr(ty
::mt { ty: inner_type, mutbl }
) => {
83 ast
::MutImmutable
=> output
.push_str("const "),
84 ast
::MutMutable
=> output
.push_str("mut "),
87 push_debuginfo_type_name(cx
, inner_type
, true, output
);
89 ty
::ty_rptr(_
, ty
::mt { ty: inner_type, mutbl }
) => {
91 if mutbl
== ast
::MutMutable
{
92 output
.push_str("mut ");
95 push_debuginfo_type_name(cx
, inner_type
, true, output
);
97 ty
::ty_vec(inner_type
, optional_length
) => {
99 push_debuginfo_type_name(cx
, inner_type
, true, output
);
101 match optional_length
{
103 output
.push_str(&format
!("; {}", len
));
105 None
=> { /* nothing to do */ }
110 ty
::ty_trait(ref trait_data
) => {
111 let principal
= ty
::erase_late_bound_regions(cx
.tcx(), &trait_data
.principal
);
112 push_item_name(cx
, principal
.def_id
, false, output
);
113 push_type_params(cx
, principal
.substs
, output
);
115 ty
::ty_bare_fn(_
, &ty
::BareFnTy{ unsafety, abi, ref sig }
) => {
116 if unsafety
== ast
::Unsafety
::Unsafe
{
117 output
.push_str("unsafe ");
120 if abi
!= ::syntax
::abi
::Rust
{
121 output
.push_str("extern \"");
122 output
.push_str(abi
.name());
123 output
.push_str("\" ");
126 output
.push_str("fn(");
128 let sig
= ty
::erase_late_bound_regions(cx
.tcx(), sig
);
129 if !sig
.inputs
.is_empty() {
130 for ¶meter_type
in &sig
.inputs
{
131 push_debuginfo_type_name(cx
, parameter_type
, true, output
);
132 output
.push_str(", ");
139 if !sig
.inputs
.is_empty() {
140 output
.push_str(", ...");
142 output
.push_str("...");
149 ty
::FnConverging(result_type
) if ty
::type_is_nil(result_type
) => {}
150 ty
::FnConverging(result_type
) => {
151 output
.push_str(" -> ");
152 push_debuginfo_type_name(cx
, result_type
, true, output
);
155 output
.push_str(" -> !");
159 ty
::ty_closure(..) => {
160 output
.push_str("closure");
164 ty
::ty_projection(..) |
166 cx
.sess().bug(&format
!("debuginfo: Trying to create type name for \
167 unexpected type: {}", ppaux
::ty_to_string(cx
.tcx(), t
)));
171 fn push_item_name(cx
: &CrateContext
,
174 output
: &mut String
) {
175 ty
::with_path(cx
.tcx(), def_id
, |path
| {
177 if def_id
.krate
== ast
::LOCAL_CRATE
{
178 output
.push_str(crate_root_namespace(cx
));
179 output
.push_str("::");
182 let mut path_element_count
= 0;
183 for path_element
in path
{
184 let name
= token
::get_name(path_element
.name());
185 output
.push_str(&name
);
186 output
.push_str("::");
187 path_element_count
+= 1;
190 if path_element_count
== 0 {
191 cx
.sess().bug("debuginfo: Encountered empty item path!");
197 let name
= token
::get_name(path
.last()
198 .expect("debuginfo: Empty item path?")
200 output
.push_str(&name
);
205 // Pushes the type parameters in the given `Substs` to the output string.
206 // This ignores region parameters, since they can't reliably be
207 // reconstructed for items from non-local crates. For local crates, this
208 // would be possible but with inlining and LTO we have to use the least
209 // common denominator - otherwise we would run into conflicts.
210 fn push_type_params
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
211 substs
: &subst
::Substs
<'tcx
>,
212 output
: &mut String
) {
213 if substs
.types
.is_empty() {
219 for &type_parameter
in substs
.types
.iter() {
220 push_debuginfo_type_name(cx
, type_parameter
, true, output
);
221 output
.push_str(", ");