Skip to content

Commit e6e1e09

Browse files
[debuginfo] Emit associated type bindings in trait object type names.
1 parent b919797 commit e6e1e09

File tree

4 files changed

+96
-44
lines changed

4 files changed

+96
-44
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3734,6 +3734,7 @@ dependencies = [
37343734
"rustc_span",
37353735
"rustc_symbol_mangling",
37363736
"rustc_target",
3737+
"smallvec",
37373738
"tempfile",
37383739
"tracing",
37393740
]

compiler/rustc_codegen_ssa/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ libc = "0.2.50"
1616
jobserver = "0.1.22"
1717
tempfile = "3.2"
1818
pathdiff = "0.2.0"
19+
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
1920

2021
rustc_serialize = { path = "../rustc_serialize" }
2122
rustc_ast = { path = "../rustc_ast" }

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+83-37
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD
1919
use rustc_middle::ich::NodeIdHashingMode;
2020
use rustc_middle::ty::layout::IntegerExt;
2121
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
22-
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
22+
use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt};
2323
use rustc_target::abi::{Integer, TagEncoding, Variants};
24+
use smallvec::SmallVec;
2425

2526
use std::fmt::Write;
2627

@@ -188,63 +189,86 @@ pub fn push_debuginfo_type_name<'tcx>(
188189
}
189190
}
190191
ty::Dynamic(ref trait_data, ..) => {
191-
if cpp_like_names {
192+
let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect();
193+
194+
let has_enclosing_parens = if cpp_like_names {
192195
output.push_str("dyn$<");
196+
false
193197
} else {
194-
output.push_str("dyn ");
195-
}
198+
if trait_data.len() > 1 && auto_traits.len() != 0 {
199+
// We need enclosing parens
200+
output.push_str("(dyn ");
201+
true
202+
} else {
203+
output.push_str("dyn ");
204+
false
205+
}
206+
};
196207

197208
if let Some(principal) = trait_data.principal() {
198209
let principal =
199210
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
200211
push_item_name(tcx, principal.def_id, qualified, output);
201212
push_generic_params_internal(tcx, principal.substs, output, visited);
202-
} else {
203-
// The auto traits come ordered by `DefPathHash`, which guarantees stability if the
204-
// environment is stable (e.g., incremental builds) but not otherwise (e.g.,
205-
// updated compiler version, different target).
206-
//
207-
// To avoid that causing instabilities in test output, sort the auto-traits
208-
// alphabetically.
209-
let mut auto_traits: Vec<_> = trait_data
210-
.iter()
211-
.filter_map(|predicate| {
212-
match tcx.normalize_erasing_late_bound_regions(
213-
ty::ParamEnv::reveal_all(),
214-
predicate,
215-
) {
216-
ty::ExistentialPredicate::AutoTrait(def_id) => {
217-
let mut name = String::new();
218-
push_item_name(tcx, def_id, true, &mut name);
219-
Some(name)
220-
}
221-
_ => None,
222-
}
213+
214+
let projection_bounds: SmallVec<[_; 4]> = trait_data
215+
.projection_bounds()
216+
.map(|bound| {
217+
let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder();
218+
(item_def_id, ty)
223219
})
224220
.collect();
225-
auto_traits.sort();
226221

227-
for name in auto_traits {
228-
output.push_str(&name);
222+
if projection_bounds.len() != 0 {
223+
pop_close_angle_bracket(output);
229224

230-
if cpp_like_names {
225+
for (item_def_id, ty) in projection_bounds {
231226
output.push_str(", ");
232-
} else {
233-
output.push_str(" + ");
227+
228+
if cpp_like_names {
229+
output.push_str("assoc$<");
230+
push_item_name(tcx, item_def_id, false, output);
231+
output.push_str(", ");
232+
push_debuginfo_type_name(tcx, ty, true, output, visited);
233+
push_close_angle_bracket(tcx, output);
234+
} else {
235+
push_item_name(tcx, item_def_id, false, output);
236+
output.push('=');
237+
push_debuginfo_type_name(tcx, ty, true, output, visited);
238+
}
234239
}
240+
241+
push_close_angle_bracket(tcx, output);
235242
}
236243

237-
// Remove the trailing joining characters. For cpp_like_names
238-
// this is `, ` otherwise ` + `.
239-
output.pop();
240-
output.pop();
241-
if !cpp_like_names {
242-
output.pop();
244+
if auto_traits.len() != 0 {
245+
push_auto_trait_separator(cpp_like_names, output);
246+
}
247+
}
248+
249+
if auto_traits.len() != 0 {
250+
let mut auto_traits: SmallVec<[String; 4]> = auto_traits
251+
.into_iter()
252+
.map(|def_id| {
253+
let mut name = String::with_capacity(20);
254+
push_item_name(tcx, def_id, true, &mut name);
255+
name
256+
})
257+
.collect();
258+
auto_traits.sort_unstable();
259+
260+
for auto_trait in auto_traits {
261+
output.push_str(&auto_trait);
262+
push_auto_trait_separator(cpp_like_names, output);
243263
}
264+
265+
pop_auto_trait_separator(cpp_like_names, output);
244266
}
245267

246268
if cpp_like_names {
247269
push_close_angle_bracket(tcx, output);
270+
} else if has_enclosing_parens {
271+
output.push(')');
248272
}
249273
}
250274
ty::FnDef(..) | ty::FnPtr(_) => {
@@ -407,6 +431,20 @@ pub fn push_debuginfo_type_name<'tcx>(
407431
}
408432
push_close_angle_bracket(tcx, output);
409433
}
434+
435+
fn auto_trait_separator(cpp_like_names: bool) -> &'static str {
436+
if cpp_like_names { ", " } else { " + " }
437+
}
438+
439+
fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) {
440+
output.push_str(auto_trait_separator(cpp_like_names));
441+
}
442+
443+
fn pop_auto_trait_separator(cpp_like_names: bool, output: &mut String) {
444+
let sep = auto_trait_separator(cpp_like_names);
445+
assert!(output.ends_with(sep));
446+
output.truncate(output.len() - sep.len());
447+
}
410448
}
411449

412450
pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
@@ -555,6 +593,14 @@ fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) {
555593
output.push('>');
556594
}
557595

596+
fn pop_close_angle_bracket(output: &mut String) {
597+
assert!(output.ends_with('>'));
598+
output.pop();
599+
if output.ends_with(' ') {
600+
output.pop();
601+
}
602+
}
603+
558604
fn cpp_like_names(tcx: TyCtxt<'_>) -> bool {
559605
tcx.sess.target.is_like_msvc
560606
}

src/test/debuginfo/type-names.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@
117117
// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
118118

119119
// gdb-command:whatis no_principal_trait
120-
// gdb-check:type = alloc::boxed::Box<dyn core::marker::Send + core::marker::Sync, alloc::alloc::Global>
120+
// gdb-check:type = alloc::boxed::Box<(dyn core::marker::Send + core::marker::Sync), alloc::alloc::Global>
121+
122+
// gdb-command:whatis has_associated_type_trait
123+
// gdb-check:type = &(dyn type_names::Trait3<u32, AssocType=isize> + core::marker::Send)
124+
121125

122126
// BARE FUNCTIONS
123127
// gdb-command:whatis rust_fn
@@ -224,7 +228,7 @@
224228
// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...]
225229
// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...]
226230
// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send, core::marker::Sync>, alloc::alloc::Global> no_principal_trait = [...]
227-
// cdb-check:struct ref$<dyn$<type_names::Trait3> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3> >
231+
// cdb-check:struct ref$<dyn$<type_names::Trait3<u32, assoc$<AssocType, isize> >, core::marker::Send> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3<u32, assoc$<AssocType, isize> >, core::marker::Send> >
228232

229233
// BARE FUNCTIONS
230234
// cdb-command:dv /t *_fn*
@@ -306,14 +310,14 @@ trait Trait1 {
306310
trait Trait2<T1, T2> {
307311
fn dummy(&self, _: T1, _: T2) {}
308312
}
309-
trait Trait3 {
313+
trait Trait3<T> {
310314
type AssocType;
311-
fn dummy(&self) {}
315+
fn dummy(&self) -> T { panic!() }
312316
}
313317

314318
impl Trait1 for isize {}
315319
impl<T1, T2> Trait2<T1, T2> for isize {}
316-
impl Trait3 for isize {
320+
impl<T> Trait3<T> for isize {
317321
type AssocType = isize;
318322
}
319323

@@ -404,8 +408,8 @@ fn main() {
404408
let ref_trait = &0_isize as &dyn Trait1;
405409
let mut mut_int1 = 0_isize;
406410
let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
407-
let no_principal_trait = (box 0_isize) as Box<dyn Send + Sync>;
408-
let has_associated_type_trait = &0_isize as &dyn Trait3<AssocType = isize>;
411+
let no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>;
412+
let has_associated_type_trait = &0_isize as &(dyn Trait3<u32, AssocType = isize> + Send);
409413

410414
let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
411415
let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;

0 commit comments

Comments
 (0)