]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/debuginfo/type_names.rs
New upstream version 1.13.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 match t.sty {
40 ty::TyBool => output.push_str("bool"),
41 ty::TyChar => output.push_str("char"),
42 ty::TyStr => output.push_str("str"),
43 ty::TyNever => output.push_str("!"),
44 ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
45 ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
46 ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
47 ty::TyAdt(def, substs) => {
48 push_item_name(cx, def.did, qualified, output);
49 push_type_params(cx, substs, output);
50 },
51 ty::TyTuple(component_types) => {
52 output.push('(');
53 for &component_type in component_types {
54 push_debuginfo_type_name(cx, component_type, true, output);
55 output.push_str(", ");
56 }
57 if !component_types.is_empty() {
58 output.pop();
59 output.pop();
60 }
61 output.push(')');
62 },
63 ty::TyBox(inner_type) => {
64 output.push_str("Box<");
65 push_debuginfo_type_name(cx, inner_type, true, output);
66 output.push('>');
67 },
68 ty::TyRawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
69 output.push('*');
70 match mutbl {
71 hir::MutImmutable => output.push_str("const "),
72 hir::MutMutable => output.push_str("mut "),
73 }
74
75 push_debuginfo_type_name(cx, inner_type, true, output);
76 },
77 ty::TyRef(_, ty::TypeAndMut { ty: inner_type, mutbl }) => {
78 output.push('&');
79 if mutbl == hir::MutMutable {
80 output.push_str("mut ");
81 }
82
83 push_debuginfo_type_name(cx, inner_type, true, output);
84 },
85 ty::TyArray(inner_type, len) => {
86 output.push('[');
87 push_debuginfo_type_name(cx, inner_type, true, output);
88 output.push_str(&format!("; {}", len));
89 output.push(']');
90 },
91 ty::TySlice(inner_type) => {
92 output.push('[');
93 push_debuginfo_type_name(cx, inner_type, true, output);
94 output.push(']');
95 },
96 ty::TyTrait(ref trait_data) => {
97 let principal = cx.tcx().erase_late_bound_regions_and_normalize(
98 &trait_data.principal);
99 push_item_name(cx, principal.def_id, false, output);
100 push_type_params(cx, principal.substs, output);
101 },
102 ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) |
103 ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
104 if unsafety == hir::Unsafety::Unsafe {
105 output.push_str("unsafe ");
106 }
107
108 if abi != ::abi::Abi::Rust {
109 output.push_str("extern \"");
110 output.push_str(abi.name());
111 output.push_str("\" ");
112 }
113
114 output.push_str("fn(");
115
116 let sig = cx.tcx().erase_late_bound_regions_and_normalize(sig);
117 if !sig.inputs.is_empty() {
118 for &parameter_type in &sig.inputs {
119 push_debuginfo_type_name(cx, parameter_type, true, output);
120 output.push_str(", ");
121 }
122 output.pop();
123 output.pop();
124 }
125
126 if sig.variadic {
127 if !sig.inputs.is_empty() {
128 output.push_str(", ...");
129 } else {
130 output.push_str("...");
131 }
132 }
133
134 output.push(')');
135
136 if !sig.output.is_nil() {
137 output.push_str(" -> ");
138 push_debuginfo_type_name(cx, sig.output, true, output);
139 }
140 },
141 ty::TyClosure(..) => {
142 output.push_str("closure");
143 }
144 ty::TyError |
145 ty::TyInfer(_) |
146 ty::TyProjection(..) |
147 ty::TyAnon(..) |
148 ty::TyParam(_) => {
149 bug!("debuginfo: Trying to create type name for \
150 unexpected type: {:?}", t);
151 }
152 }
153
154 fn push_item_name(cx: &CrateContext,
155 def_id: DefId,
156 qualified: bool,
157 output: &mut String) {
158 if qualified {
159 output.push_str(&cx.tcx().crate_name(def_id.krate));
160 for path_element in cx.tcx().def_path(def_id).data {
161 output.push_str("::");
162 output.push_str(&path_element.data.as_interned_str());
163 }
164 } else {
165 output.push_str(&cx.tcx().item_name(def_id).as_str());
166 }
167 }
168
169 // Pushes the type parameters in the given `Substs` to the output string.
170 // This ignores region parameters, since they can't reliably be
171 // reconstructed for items from non-local crates. For local crates, this
172 // would be possible but with inlining and LTO we have to use the least
173 // common denominator - otherwise we would run into conflicts.
174 fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
175 substs: &Substs<'tcx>,
176 output: &mut String) {
177 if substs.types().next().is_none() {
178 return;
179 }
180
181 output.push('<');
182
183 for type_parameter in substs.types() {
184 push_debuginfo_type_name(cx, type_parameter, true, output);
185 output.push_str(", ");
186 }
187
188 output.pop();
189 output.pop();
190
191 output.push('>');
192 }
193 }