]>
Commit | Line | Data |
---|---|---|
d9579d0f AL |
1 | // Type Names for Debug Info. |
2 | ||
48663c56 XL |
3 | use rustc::hir::{self, def_id::DefId}; |
4 | use rustc::ty::{self, Ty, TyCtxt, subst::SubstsRef}; | |
532ac7d7 | 5 | use 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 |
11 | pub 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 |
24 | pub 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 ¶meter_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 | } |