]> git.proxmox.com Git - rustc.git/blame - src/librustc_codegen_ssa/debuginfo/type_names.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_codegen_ssa / debuginfo / type_names.rs
CommitLineData
d9579d0f
AL
1// Type Names for Debug Info.
2
48663c56
XL
3use rustc::hir::{self, def_id::DefId};
4use rustc::ty::{self, Ty, TyCtxt, subst::SubstsRef};
532ac7d7 5use rustc_data_structures::fx::FxHashSet;
d9579d0f 6
d9579d0f 7// Compute the name of the type as it should be stored in debuginfo. Does not do
0731742a 8// any caching, i.e., calling the function twice with the same type will also do
d9579d0f 9// the work twice. The `qualified` parameter only affects the first level of the
0731742a 10// type name, further levels (i.e., type parameters) are always fully qualified.
dc9dc135
XL
11pub fn compute_debuginfo_type_name<'tcx>(
12 tcx: TyCtxt<'tcx>,
13 t: Ty<'tcx>,
14 qualified: bool,
15) -> String {
d9579d0f 16 let mut result = String::with_capacity(64);
532ac7d7 17 let mut visited = FxHashSet::default();
48663c56 18 push_debuginfo_type_name(tcx, t, qualified, &mut result, &mut visited);
d9579d0f
AL
19 result
20}
21
22// Pushes the name of the type as it should be stored in debuginfo on the
23// `output` String. See also compute_debuginfo_type_name().
dc9dc135
XL
24pub fn push_debuginfo_type_name<'tcx>(
25 tcx: TyCtxt<'tcx>,
26 t: Ty<'tcx>,
27 qualified: bool,
28 output: &mut String,
29 visited: &mut FxHashSet<Ty<'tcx>>,
30) {
3b2f2976
XL
31 // When targeting MSVC, emit C++ style type names for compatibility with
32 // .natvis visualizers (and perhaps other existing native debuggers?)
48663c56 33 let cpp_like_names = tcx.sess.target.target.options.is_like_msvc;
3b2f2976 34
e74abb32 35 match t.kind {
b7449926
XL
36 ty::Bool => output.push_str("bool"),
37 ty::Char => output.push_str("char"),
38 ty::Str => output.push_str("str"),
39 ty::Never => output.push_str("!"),
60c5eb7d
XL
40 ty::Int(int_ty) => output.push_str(int_ty.name_str()),
41 ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
42 ty::Float(float_ty) => output.push_str(float_ty.name_str()),
48663c56 43 ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
b7449926 44 ty::Adt(def, substs) => {
48663c56
XL
45 push_item_name(tcx, def.did, qualified, output);
46 push_type_params(tcx, substs, output, visited);
d9579d0f 47 },
b7449926 48 ty::Tuple(component_types) => {
d9579d0f
AL
49 output.push('(');
50 for &component_type in component_types {
48663c56 51 push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited);
d9579d0f
AL
52 output.push_str(", ");
53 }
54 if !component_types.is_empty() {
55 output.pop();
56 output.pop();
57 }
58 output.push(')');
59 },
b7449926 60 ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
3b2f2976
XL
61 if !cpp_like_names {
62 output.push('*');
63 }
d9579d0f 64 match mutbl {
60c5eb7d
XL
65 hir::Mutability::Immutable => output.push_str("const "),
66 hir::Mutability::Mutable => output.push_str("mut "),
d9579d0f
AL
67 }
68
48663c56 69 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
3b2f2976
XL
70
71 if cpp_like_names {
72 output.push('*');
73 }
d9579d0f 74 },
b7449926 75 ty::Ref(_, inner_type, mutbl) => {
3b2f2976
XL
76 if !cpp_like_names {
77 output.push('&');
78 }
60c5eb7d 79 output.push_str(mutbl.prefix_str());
d9579d0f 80
48663c56 81 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
3b2f2976
XL
82
83 if cpp_like_names {
84 output.push('*');
85 }
d9579d0f 86 },
b7449926 87 ty::Array(inner_type, len) => {
62682a34 88 output.push('[');
48663c56 89 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
416331ca 90 output.push_str(&format!("; {}", len.eval_usize(tcx, ty::ParamEnv::reveal_all())));
62682a34
SL
91 output.push(']');
92 },
b7449926 93 ty::Slice(inner_type) => {
3b2f2976
XL
94 if cpp_like_names {
95 output.push_str("slice<");
96 } else {
97 output.push('[');
98 }
99
48663c56 100 push_debuginfo_type_name(tcx, inner_type, true, output, visited);
3b2f2976
XL
101
102 if cpp_like_names {
103 output.push('>');
104 } else {
105 output.push(']');
106 }
d9579d0f 107 },
b7449926 108 ty::Dynamic(ref trait_data, ..) => {
0731742a 109 if let Some(principal) = trait_data.principal() {
48663c56 110 let principal = tcx.normalize_erasing_late_bound_regions(
0731742a
XL
111 ty::ParamEnv::reveal_all(),
112 &principal,
113 );
48663c56
XL
114 push_item_name(tcx, principal.def_id, false, output);
115 push_type_params(tcx, principal.substs, output, visited);
0731742a
XL
116 } else {
117 output.push_str("dyn '_");
118 }
d9579d0f 119 },
b7449926 120 ty::FnDef(..) | ty::FnPtr(_) => {
532ac7d7
XL
121 // We've encountered a weird 'recursive type'
122 // Currently, the only way to generate such a type
123 // is by using 'impl trait':
124 //
125 // fn foo() -> impl Copy { foo }
126 //
127 // There's not really a sensible name we can generate,
128 // since we don't include 'impl trait' types (e.g. ty::Opaque)
129 // in the output
130 //
131 // Since we need to generate *something*, we just
132 // use a dummy string that should make it clear
133 // that something unusual is going on
134 if !visited.insert(t) {
135 output.push_str("<recursive_type>");
136 return;
137 }
138
139
48663c56 140 let sig = t.fn_sig(tcx);
60c5eb7d 141 output.push_str(sig.unsafety().prefix_str());
d9579d0f 142
8bb4bdeb 143 let abi = sig.abi();
48663c56 144 if abi != rustc_target::spec::abi::Abi::Rust {
d9579d0f
AL
145 output.push_str("extern \"");
146 output.push_str(abi.name());
147 output.push_str("\" ");
148 }
149
150 output.push_str("fn(");
151
48663c56 152 let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
476ff2be
SL
153 if !sig.inputs().is_empty() {
154 for &parameter_type in sig.inputs() {
48663c56 155 push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
d9579d0f
AL
156 output.push_str(", ");
157 }
158 output.pop();
159 output.pop();
160 }
161
532ac7d7 162 if sig.c_variadic {
476ff2be 163 if !sig.inputs().is_empty() {
d9579d0f
AL
164 output.push_str(", ...");
165 } else {
166 output.push_str("...");
167 }
168 }
169
170 output.push(')');
171
b7449926 172 if !sig.output().is_unit() {
5bcae85e 173 output.push_str(" -> ");
48663c56 174 push_debuginfo_type_name(tcx, sig.output(), true, output, visited);
d9579d0f 175 }
532ac7d7
XL
176
177
178 // We only keep the type in 'visited'
179 // for the duration of the body of this method.
180 // It's fine for a particular function type
181 // to show up multiple times in one overall type
182 // (e.g. MyType<fn() -> u8, fn() -> u8>
183 //
184 // We only care about avoiding recursing
185 // directly back to the type we're currently
186 // processing
187 visited.remove(t);
d9579d0f 188 },
416331ca
XL
189 ty::Closure(def_id, ..) => {
190 output.push_str(&format!(
191 "closure-{}",
192 tcx.def_key(def_id).disambiguated_data.disambiguator
193 ));
d9579d0f 194 }
416331ca
XL
195 ty::Generator(def_id, ..) => {
196 output.push_str(&format!(
197 "generator-{}",
198 tcx.def_key(def_id).disambiguated_data.disambiguator
199 ));
ea8adc8c 200 }
b7449926
XL
201 ty::Error |
202 ty::Infer(_) |
a1dfa0c6 203 ty::Placeholder(..) |
0bf4aa26 204 ty::UnnormalizedProjection(..) |
b7449926 205 ty::Projection(..) |
a1dfa0c6 206 ty::Bound(..) |
b7449926
XL
207 ty::Opaque(..) |
208 ty::GeneratorWitness(..) |
209 ty::Param(_) => {
54a0048b 210 bug!("debuginfo: Trying to create type name for \
0bf4aa26 211 unexpected type: {:?}", t);
d9579d0f
AL
212 }
213 }
214
dc9dc135 215 fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
54a0048b 216 if qualified {
48663c56
XL
217 output.push_str(&tcx.crate_name(def_id.krate).as_str());
218 for path_element in tcx.def_path(def_id).data {
54a0048b 219 output.push_str("::");
e74abb32 220 output.push_str(&path_element.data.as_symbol().as_str());
d9579d0f 221 }
54a0048b 222 } else {
48663c56 223 output.push_str(&tcx.item_name(def_id).as_str());
54a0048b 224 }
d9579d0f
AL
225 }
226
532ac7d7 227 // Pushes the type parameters in the given `InternalSubsts` to the output string.
d9579d0f
AL
228 // This ignores region parameters, since they can't reliably be
229 // reconstructed for items from non-local crates. For local crates, this
230 // would be possible but with inlining and LTO we have to use the least
231 // common denominator - otherwise we would run into conflicts.
dc9dc135
XL
232 fn push_type_params<'tcx>(
233 tcx: TyCtxt<'tcx>,
234 substs: SubstsRef<'tcx>,
235 output: &mut String,
236 visited: &mut FxHashSet<Ty<'tcx>>,
237 ) {
9e0c209e 238 if substs.types().next().is_none() {
d9579d0f
AL
239 return;
240 }
241
242 output.push('<');
243
9e0c209e 244 for type_parameter in substs.types() {
48663c56 245 push_debuginfo_type_name(tcx, type_parameter, true, output, visited);
d9579d0f
AL
246 output.push_str(", ");
247 }
248
249 output.pop();
250 output.pop();
251
252 output.push('>');
253 }
254}