]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/trans/debuginfo/type_names.rs
Imported Upstream version 1.6.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::{self, Substs};
19 use middle::ty::{self, Ty};
20
21 use rustc_front::hir;
22 use syntax::ast_util;
23
24 // Compute the name of the type as it should be stored in debuginfo. Does not do
25 // any caching, i.e. calling the function twice with the same type will also do
26 // the work twice. The `qualified` parameter only affects the first level of the
27 // type name, further levels (i.e. type parameters) are always fully qualified.
28 pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
29 t: Ty<'tcx>,
30 qualified: bool)
31 -> String {
32 let mut result = String::with_capacity(64);
33 push_debuginfo_type_name(cx, t, qualified, &mut result);
34 result
35 }
36
37 // Pushes the name of the type as it should be stored in debuginfo on the
38 // `output` String. See also compute_debuginfo_type_name().
39 pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
40 t: Ty<'tcx>,
41 qualified: bool,
42 output: &mut String) {
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::TyInt(int_ty) => output.push_str(ast_util::int_ty_to_string(int_ty)),
48 ty::TyUint(uint_ty) => output.push_str(ast_util::uint_ty_to_string(uint_ty)),
49 ty::TyFloat(float_ty) => output.push_str(ast_util::float_ty_to_string(float_ty)),
50 ty::TyStruct(def, substs) |
51 ty::TyEnum(def, substs) => {
52 push_item_name(cx, def.did, qualified, output);
53 push_type_params(cx, substs, output);
54 },
55 ty::TyTuple(ref 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::TyBox(inner_type) => {
68 output.push_str("Box<");
69 push_debuginfo_type_name(cx, inner_type, true, output);
70 output.push('>');
71 },
72 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
73 output.push('*');
74 match mutbl {
75 hir::MutImmutable => output.push_str("const "),
76 hir::MutMutable => output.push_str("mut "),
77 }
78
79 push_debuginfo_type_name(cx, inner_type, true, output);
80 },
81 ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
82 output.push('&');
83 if mutbl == hir::MutMutable {
84 output.push_str("mut ");
85 }
86
87 push_debuginfo_type_name(cx, inner_type, true, output);
88 },
89 ty::TyArray(inner_type, len) => {
90 output.push('[');
91 push_debuginfo_type_name(cx, inner_type, true, output);
92 output.push_str(&format!("; {}", len));
93 output.push(']');
94 },
95 ty::TySlice(inner_type) => {
96 output.push('[');
97 push_debuginfo_type_name(cx, inner_type, true, output);
98 output.push(']');
99 },
100 ty::TyTrait(ref trait_data) => {
101 let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
102 push_item_name(cx, principal.def_id, false, output);
103 push_type_params(cx, principal.substs, output);
104 },
105 ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
106 if unsafety == hir::Unsafety::Unsafe {
107 output.push_str("unsafe ");
108 }
109
110 if abi != ::syntax::abi::Rust {
111 output.push_str("extern \"");
112 output.push_str(abi.name());
113 output.push_str("\" ");
114 }
115
116 output.push_str("fn(");
117
118 let sig = cx.tcx().erase_late_bound_regions(sig);
119 let sig = infer::normalize_associated_type(cx.tcx(), &sig);
120 if !sig.inputs.is_empty() {
121 for &parameter_type in &sig.inputs {
122 push_debuginfo_type_name(cx, parameter_type, true, output);
123 output.push_str(", ");
124 }
125 output.pop();
126 output.pop();
127 }
128
129 if sig.variadic {
130 if !sig.inputs.is_empty() {
131 output.push_str(", ...");
132 } else {
133 output.push_str("...");
134 }
135 }
136
137 output.push(')');
138
139 match sig.output {
140 ty::FnConverging(result_type) if result_type.is_nil() => {}
141 ty::FnConverging(result_type) => {
142 output.push_str(" -> ");
143 push_debuginfo_type_name(cx, result_type, true, output);
144 }
145 ty::FnDiverging => {
146 output.push_str(" -> !");
147 }
148 }
149 },
150 ty::TyClosure(..) => {
151 output.push_str("closure");
152 }
153 ty::TyError |
154 ty::TyInfer(_) |
155 ty::TyProjection(..) |
156 ty::TyParam(_) => {
157 cx.sess().bug(&format!("debuginfo: Trying to create type name for \
158 unexpected type: {:?}", t));
159 }
160 }
161
162 fn push_item_name(cx: &CrateContext,
163 def_id: DefId,
164 qualified: bool,
165 output: &mut String) {
166 cx.tcx().with_path(def_id, |path| {
167 if qualified {
168 if def_id.is_local() {
169 output.push_str(crate_root_namespace(cx));
170 output.push_str("::");
171 }
172
173 let mut path_element_count = 0;
174 for path_element in path {
175 output.push_str(&path_element.name().as_str());
176 output.push_str("::");
177 path_element_count += 1;
178 }
179
180 if path_element_count == 0 {
181 cx.sess().bug("debuginfo: Encountered empty item path!");
182 }
183
184 output.pop();
185 output.pop();
186 } else {
187 let name = path.last().expect("debuginfo: Empty item path?").name();
188 output.push_str(&name.as_str());
189 }
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: &subst::Substs<'tcx>,
200 output: &mut String) {
201 if substs.types.is_empty() {
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 }