]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/debuginfo/type_names.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / librustc_trans / debuginfo / type_names.rs
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.
4 //
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.
10
11 // Type Names for Debug Info.
12
13 use common::CrateContext;
14 use rustc::hir::def_id::DefId;
15 use rustc::ty::subst::Substs;
16 use rustc::ty::{self, Ty};
17
18 use rustc::hir;
19
20 // Compute the name of the type as it should be stored in debuginfo. Does not do
21 // any caching, i.e. calling the function twice with the same type will also do
22 // the work twice. The `qualified` parameter only affects the first level of the
23 // type name, further levels (i.e. type parameters) are always fully qualified.
24 pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
25 t: Ty<'tcx>,
26 qualified: bool)
27 -> String {
28 let mut result = String::with_capacity(64);
29 push_debuginfo_type_name(cx, t, qualified, &mut result);
30 result
31 }
32
33 // Pushes the name of the type as it should be stored in debuginfo on the
34 // `output` String. See also compute_debuginfo_type_name().
35 pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
36 t: Ty<'tcx>,
37 qualified: bool,
38 output: &mut String) {
39 // When targeting MSVC, emit C++ style type names for compatibility with
40 // .natvis visualizers (and perhaps other existing native debuggers?)
41 let cpp_like_names = cx.sess().target.target.options.is_like_msvc;
42
43 match t.sty {
44 ty::TyBool => output.push_str("bool"),
45 ty::TyChar => output.push_str("char"),
46 ty::TyStr => output.push_str("str"),
47 ty::TyNever => output.push_str("!"),
48 ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
49 ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
50 ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
51 ty::TyAdt(def, substs) => {
52 push_item_name(cx, def.did, qualified, output);
53 push_type_params(cx, substs, output);
54 },
55 ty::TyTuple(component_types, _) => {
56 output.push('(');
57 for &component_type in component_types {
58 push_debuginfo_type_name(cx, component_type, true, output);
59 output.push_str(", ");
60 }
61 if !component_types.is_empty() {
62 output.pop();
63 output.pop();
64 }
65 output.push(')');
66 },
67 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
68 if !cpp_like_names {
69 output.push('*');
70 }
71 match mutbl {
72 hir::MutImmutable => output.push_str("const "),
73 hir::MutMutable => output.push_str("mut "),
74 }
75
76 push_debuginfo_type_name(cx, inner_type, true, output);
77
78 if cpp_like_names {
79 output.push('*');
80 }
81 },
82 ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
83 if !cpp_like_names {
84 output.push('&');
85 }
86 if mutbl == hir::MutMutable {
87 output.push_str("mut ");
88 }
89
90 push_debuginfo_type_name(cx, inner_type, true, output);
91
92 if cpp_like_names {
93 output.push('*');
94 }
95 },
96 ty::TyArray(inner_type, len) => {
97 output.push('[');
98 push_debuginfo_type_name(cx, inner_type, true, output);
99 output.push_str(&format!("; {}", len));
100 output.push(']');
101 },
102 ty::TySlice(inner_type) => {
103 if cpp_like_names {
104 output.push_str("slice<");
105 } else {
106 output.push('[');
107 }
108
109 push_debuginfo_type_name(cx, inner_type, true, output);
110
111 if cpp_like_names {
112 output.push('>');
113 } else {
114 output.push(']');
115 }
116 },
117 ty::TyDynamic(ref trait_data, ..) => {
118 if let Some(principal) = trait_data.principal() {
119 let principal = cx.tcx().erase_late_bound_regions_and_normalize(
120 &principal);
121 push_item_name(cx, principal.def_id, false, output);
122 push_type_params(cx, principal.substs, output);
123 }
124 },
125 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
126 let sig = t.fn_sig(cx.tcx());
127 if sig.unsafety() == hir::Unsafety::Unsafe {
128 output.push_str("unsafe ");
129 }
130
131 let abi = sig.abi();
132 if abi != ::abi::Abi::Rust {
133 output.push_str("extern \"");
134 output.push_str(abi.name());
135 output.push_str("\" ");
136 }
137
138 output.push_str("fn(");
139
140 let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig);
141 if !sig.inputs().is_empty() {
142 for &parameter_type in sig.inputs() {
143 push_debuginfo_type_name(cx, parameter_type, true, output);
144 output.push_str(", ");
145 }
146 output.pop();
147 output.pop();
148 }
149
150 if sig.variadic {
151 if !sig.inputs().is_empty() {
152 output.push_str(", ...");
153 } else {
154 output.push_str("...");
155 }
156 }
157
158 output.push(')');
159
160 if !sig.output().is_nil() {
161 output.push_str(" -> ");
162 push_debuginfo_type_name(cx, sig.output(), true, output);
163 }
164 },
165 ty::TyClosure(..) => {
166 output.push_str("closure");
167 }
168 ty::TyError |
169 ty::TyInfer(_) |
170 ty::TyProjection(..) |
171 ty::TyAnon(..) |
172 ty::TyParam(_) => {
173 bug!("debuginfo: Trying to create type name for \
174 unexpected type: {:?}", t);
175 }
176 }
177
178 fn push_item_name(cx: &CrateContext,
179 def_id: DefId,
180 qualified: bool,
181 output: &mut String) {
182 if qualified {
183 output.push_str(&cx.tcx().crate_name(def_id.krate).as_str());
184 for path_element in cx.tcx().def_path(def_id).data {
185 output.push_str("::");
186 output.push_str(&path_element.data.as_interned_str());
187 }
188 } else {
189 output.push_str(&cx.tcx().item_name(def_id).as_str());
190 }
191 }
192
193 // Pushes the type parameters in the given `Substs` to the output string.
194 // This ignores region parameters, since they can't reliably be
195 // reconstructed for items from non-local crates. For local crates, this
196 // would be possible but with inlining and LTO we have to use the least
197 // common denominator - otherwise we would run into conflicts.
198 fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
199 substs: &Substs<'tcx>,
200 output: &mut String) {
201 if substs.types().next().is_none() {
202 return;
203 }
204
205 output.push('<');
206
207 for type_parameter in substs.types() {
208 push_debuginfo_type_name(cx, type_parameter, true, output);
209 output.push_str(", ");
210 }
211
212 output.pop();
213 output.pop();
214
215 output.push('>');
216 }
217 }