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