]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/trans/debuginfo/type_names.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc_trans / 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 super::namespace::crate_root_namespace;
14
15 use trans::common::CrateContext;
16 use middle::def_id::DefId;
17 use middle::infer;
18 use middle::subst;
19 use middle::ty::{self, Ty};
20
21 use rustc_front::hir;
22
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>,
28 t: Ty<'tcx>,
29 qualified: bool)
30 -> String {
31 let mut result = String::with_capacity(64);
32 push_debuginfo_type_name(cx, t, qualified, &mut result);
33 result
34 }
35
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>,
39 t: Ty<'tcx>,
40 qualified: bool,
41 output: &mut String) {
42 match t.sty {
43 ty::TyBool => output.push_str("bool"),
44 ty::TyChar => output.push_str("char"),
45 ty::TyStr => output.push_str("str"),
46 ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
47 ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
48 ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
49 ty::TyStruct(def, substs) |
50 ty::TyEnum(def, substs) => {
51 push_item_name(cx, def.did, qualified, output);
52 push_type_params(cx, substs, output);
53 },
54 ty::TyTuple(ref component_types) => {
55 output.push('(');
56 for &component_type in component_types {
57 push_debuginfo_type_name(cx, component_type, true, output);
58 output.push_str(", ");
59 }
60 if !component_types.is_empty() {
61 output.pop();
62 output.pop();
63 }
64 output.push(')');
65 },
66 ty::TyBox(inner_type) => {
67 output.push_str("Box<");
68 push_debuginfo_type_name(cx, inner_type, true, output);
69 output.push('>');
70 },
71 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
72 output.push('*');
73 match mutbl {
74 hir::MutImmutable => output.push_str("const "),
75 hir::MutMutable => output.push_str("mut "),
76 }
77
78 push_debuginfo_type_name(cx, inner_type, true, output);
79 },
80 ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
81 output.push('&');
82 if mutbl == hir::MutMutable {
83 output.push_str("mut ");
84 }
85
86 push_debuginfo_type_name(cx, inner_type, true, output);
87 },
88 ty::TyArray(inner_type, len) => {
89 output.push('[');
90 push_debuginfo_type_name(cx, inner_type, true, output);
91 output.push_str(&format!("; {}", len));
92 output.push(']');
93 },
94 ty::TySlice(inner_type) => {
95 output.push('[');
96 push_debuginfo_type_name(cx, inner_type, true, output);
97 output.push(']');
98 },
99 ty::TyTrait(ref trait_data) => {
100 let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
101 push_item_name(cx, principal.def_id, false, output);
102 push_type_params(cx, principal.substs, output);
103 },
104 ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
105 if unsafety == hir::Unsafety::Unsafe {
106 output.push_str("unsafe ");
107 }
108
109 if abi != ::syntax::abi::Abi::Rust {
110 output.push_str("extern \"");
111 output.push_str(abi.name());
112 output.push_str("\" ");
113 }
114
115 output.push_str("fn(");
116
117 let sig = cx.tcx().erase_late_bound_regions(sig);
118 let sig = infer::normalize_associated_type(cx.tcx(), &sig);
119 if !sig.inputs.is_empty() {
120 for &parameter_type in &sig.inputs {
121 push_debuginfo_type_name(cx, parameter_type, true, output);
122 output.push_str(", ");
123 }
124 output.pop();
125 output.pop();
126 }
127
128 if sig.variadic {
129 if !sig.inputs.is_empty() {
130 output.push_str(", ...");
131 } else {
132 output.push_str("...");
133 }
134 }
135
136 output.push(')');
137
138 match sig.output {
139 ty::FnConverging(result_type) if result_type.is_nil() => {}
140 ty::FnConverging(result_type) => {
141 output.push_str(" -> ");
142 push_debuginfo_type_name(cx, result_type, true, output);
143 }
144 ty::FnDiverging => {
145 output.push_str(" -> !");
146 }
147 }
148 },
149 ty::TyClosure(..) => {
150 output.push_str("closure");
151 }
152 ty::TyError |
153 ty::TyInfer(_) |
154 ty::TyProjection(..) |
155 ty::TyParam(_) => {
156 cx.sess().bug(&format!("debuginfo: Trying to create type name for \
157 unexpected type: {:?}", t));
158 }
159 }
160
161 fn push_item_name(cx: &CrateContext,
162 def_id: DefId,
163 qualified: bool,
164 output: &mut String) {
165 cx.tcx().with_path(def_id, |path| {
166 if qualified {
167 if def_id.is_local() {
168 output.push_str(crate_root_namespace(cx));
169 output.push_str("::");
170 }
171
172 let mut path_element_count = 0;
173 for path_element in path {
174 output.push_str(&path_element.name().as_str());
175 output.push_str("::");
176 path_element_count += 1;
177 }
178
179 if path_element_count == 0 {
180 cx.sess().bug("debuginfo: Encountered empty item path!");
181 }
182
183 output.pop();
184 output.pop();
185 } else {
186 let name = path.last().expect("debuginfo: Empty item path?").name();
187 output.push_str(&name.as_str());
188 }
189 });
190 }
191
192 // Pushes the type parameters in the given `Substs` to the output string.
193 // This ignores region parameters, since they can't reliably be
194 // reconstructed for items from non-local crates. For local crates, this
195 // would be possible but with inlining and LTO we have to use the least
196 // common denominator - otherwise we would run into conflicts.
197 fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
198 substs: &subst::Substs<'tcx>,
199 output: &mut String) {
200 if substs.types.is_empty() {
201 return;
202 }
203
204 output.push('<');
205
206 for &type_parameter in &substs.types {
207 push_debuginfo_type_name(cx, type_parameter, true, output);
208 output.push_str(", ");
209 }
210
211 output.pop();
212 output.pop();
213
214 output.push('>');
215 }
216 }