]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/trans/debuginfo/type_names.rs
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / librustc_trans / trans / debuginfo / type_names.rs
CommitLineData
d9579d0f
AL
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
13use super::namespace::crate_root_namespace;
14
15use trans::common::CrateContext;
16use middle::subst::{self, Substs};
c1a9b12d 17use middle::ty::{self, Ty};
62682a34 18
d9579d0f 19use syntax::ast;
d9579d0f
AL
20
21
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.
26pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
27 t: Ty<'tcx>,
28 qualified: bool)
29 -> String {
30 let mut result = String::with_capacity(64);
31 push_debuginfo_type_name(cx, t, qualified, &mut result);
32 result
33}
34
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().
37pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
38 t: Ty<'tcx>,
39 qualified: bool,
40 output: &mut String) {
41 match t.sty {
62682a34
SL
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) => {
d9579d0f
AL
59 push_item_name(cx, def_id, qualified, output);
60 push_type_params(cx, substs, output);
61 },
62682a34 62 ty::TyTuple(ref component_types) => {
d9579d0f
AL
63 output.push('(');
64 for &component_type in component_types {
65 push_debuginfo_type_name(cx, component_type, true, output);
66 output.push_str(", ");
67 }
68 if !component_types.is_empty() {
69 output.pop();
70 output.pop();
71 }
72 output.push(')');
73 },
62682a34 74 ty::TyBox(inner_type) => {
d9579d0f
AL
75 output.push_str("Box<");
76 push_debuginfo_type_name(cx, inner_type, true, output);
77 output.push('>');
78 },
c1a9b12d 79 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
d9579d0f
AL
80 output.push('*');
81 match mutbl {
82 ast::MutImmutable => output.push_str("const "),
83 ast::MutMutable => output.push_str("mut "),
84 }
85
86 push_debuginfo_type_name(cx, inner_type, true, output);
87 },
c1a9b12d 88 ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
d9579d0f
AL
89 output.push('&');
90 if mutbl == ast::MutMutable {
91 output.push_str("mut ");
92 }
93
94 push_debuginfo_type_name(cx, inner_type, true, output);
95 },
62682a34
SL
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) => {
d9579d0f
AL
103 output.push('[');
104 push_debuginfo_type_name(cx, inner_type, true, output);
d9579d0f
AL
105 output.push(']');
106 },
62682a34 107 ty::TyTrait(ref trait_data) => {
c1a9b12d 108 let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
d9579d0f
AL
109 push_item_name(cx, principal.def_id, false, output);
110 push_type_params(cx, principal.substs, output);
111 },
62682a34 112 ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
d9579d0f
AL
113 if unsafety == ast::Unsafety::Unsafe {
114 output.push_str("unsafe ");
115 }
116
117 if abi != ::syntax::abi::Rust {
118 output.push_str("extern \"");
119 output.push_str(abi.name());
120 output.push_str("\" ");
121 }
122
123 output.push_str("fn(");
124
c1a9b12d 125 let sig = cx.tcx().erase_late_bound_regions(sig);
d9579d0f
AL
126 if !sig.inputs.is_empty() {
127 for &parameter_type in &sig.inputs {
128 push_debuginfo_type_name(cx, parameter_type, true, output);
129 output.push_str(", ");
130 }
131 output.pop();
132 output.pop();
133 }
134
135 if sig.variadic {
136 if !sig.inputs.is_empty() {
137 output.push_str(", ...");
138 } else {
139 output.push_str("...");
140 }
141 }
142
143 output.push(')');
144
145 match sig.output {
c1a9b12d 146 ty::FnConverging(result_type) if result_type.is_nil() => {}
d9579d0f
AL
147 ty::FnConverging(result_type) => {
148 output.push_str(" -> ");
149 push_debuginfo_type_name(cx, result_type, true, output);
150 }
151 ty::FnDiverging => {
152 output.push_str(" -> !");
153 }
154 }
155 },
62682a34 156 ty::TyClosure(..) => {
d9579d0f
AL
157 output.push_str("closure");
158 }
62682a34
SL
159 ty::TyError |
160 ty::TyInfer(_) |
161 ty::TyProjection(..) |
162 ty::TyParam(_) => {
d9579d0f 163 cx.sess().bug(&format!("debuginfo: Trying to create type name for \
62682a34 164 unexpected type: {:?}", t));
d9579d0f
AL
165 }
166 }
167
168 fn push_item_name(cx: &CrateContext,
169 def_id: ast::DefId,
170 qualified: bool,
171 output: &mut String) {
c1a9b12d 172 cx.tcx().with_path(def_id, |path| {
d9579d0f
AL
173 if qualified {
174 if def_id.krate == ast::LOCAL_CRATE {
175 output.push_str(crate_root_namespace(cx));
176 output.push_str("::");
177 }
178
179 let mut path_element_count = 0;
180 for path_element in path {
c1a9b12d 181 output.push_str(&path_element.name().as_str());
d9579d0f
AL
182 output.push_str("::");
183 path_element_count += 1;
184 }
185
186 if path_element_count == 0 {
187 cx.sess().bug("debuginfo: Encountered empty item path!");
188 }
189
190 output.pop();
191 output.pop();
192 } else {
c1a9b12d
SL
193 let name = path.last().expect("debuginfo: Empty item path?").name();
194 output.push_str(&name.as_str());
d9579d0f
AL
195 }
196 });
197 }
198
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() {
208 return;
209 }
210
211 output.push('<');
212
62682a34 213 for &type_parameter in &substs.types {
d9579d0f
AL
214 push_debuginfo_type_name(cx, type_parameter, true, output);
215 output.push_str(", ");
216 }
217
218 output.pop();
219 output.pop();
220
221 output.push('>');
222 }
223}