[debuginfo] Emit associated type bindings in trait object type names.
This commit is contained in:
parent
b9197978a9
commit
e6e1e095ff
4 changed files with 96 additions and 44 deletions
|
@ -3734,6 +3734,7 @@ dependencies = [
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_symbol_mangling",
|
"rustc_symbol_mangling",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
|
"smallvec",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
|
@ -16,6 +16,7 @@ libc = "0.2.50"
|
||||||
jobserver = "0.1.22"
|
jobserver = "0.1.22"
|
||||||
tempfile = "3.2"
|
tempfile = "3.2"
|
||||||
pathdiff = "0.2.0"
|
pathdiff = "0.2.0"
|
||||||
|
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
|
||||||
|
|
||||||
rustc_serialize = { path = "../rustc_serialize" }
|
rustc_serialize = { path = "../rustc_serialize" }
|
||||||
rustc_ast = { path = "../rustc_ast" }
|
rustc_ast = { path = "../rustc_ast" }
|
||||||
|
|
|
@ -19,8 +19,9 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD
|
||||||
use rustc_middle::ich::NodeIdHashingMode;
|
use rustc_middle::ich::NodeIdHashingMode;
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
|
use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt};
|
||||||
use rustc_target::abi::{Integer, TagEncoding, Variants};
|
use rustc_target::abi::{Integer, TagEncoding, Variants};
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
@ -188,63 +189,86 @@ pub fn push_debuginfo_type_name<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Dynamic(ref trait_data, ..) => {
|
ty::Dynamic(ref trait_data, ..) => {
|
||||||
if cpp_like_names {
|
let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect();
|
||||||
|
|
||||||
|
let has_enclosing_parens = if cpp_like_names {
|
||||||
output.push_str("dyn$<");
|
output.push_str("dyn$<");
|
||||||
|
false
|
||||||
} else {
|
} else {
|
||||||
output.push_str("dyn ");
|
if trait_data.len() > 1 && auto_traits.len() != 0 {
|
||||||
}
|
// We need enclosing parens
|
||||||
|
output.push_str("(dyn ");
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
output.push_str("dyn ");
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(principal) = trait_data.principal() {
|
if let Some(principal) = trait_data.principal() {
|
||||||
let principal =
|
let principal =
|
||||||
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
|
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
|
||||||
push_item_name(tcx, principal.def_id, qualified, output);
|
push_item_name(tcx, principal.def_id, qualified, output);
|
||||||
push_generic_params_internal(tcx, principal.substs, output, visited);
|
push_generic_params_internal(tcx, principal.substs, output, visited);
|
||||||
} else {
|
|
||||||
// The auto traits come ordered by `DefPathHash`, which guarantees stability if the
|
let projection_bounds: SmallVec<[_; 4]> = trait_data
|
||||||
// environment is stable (e.g., incremental builds) but not otherwise (e.g.,
|
.projection_bounds()
|
||||||
// updated compiler version, different target).
|
.map(|bound| {
|
||||||
//
|
let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder();
|
||||||
// To avoid that causing instabilities in test output, sort the auto-traits
|
(item_def_id, ty)
|
||||||
// alphabetically.
|
|
||||||
let mut auto_traits: Vec<_> = trait_data
|
|
||||||
.iter()
|
|
||||||
.filter_map(|predicate| {
|
|
||||||
match tcx.normalize_erasing_late_bound_regions(
|
|
||||||
ty::ParamEnv::reveal_all(),
|
|
||||||
predicate,
|
|
||||||
) {
|
|
||||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
|
||||||
let mut name = String::new();
|
|
||||||
push_item_name(tcx, def_id, true, &mut name);
|
|
||||||
Some(name)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
auto_traits.sort();
|
|
||||||
|
|
||||||
for name in auto_traits {
|
if projection_bounds.len() != 0 {
|
||||||
output.push_str(&name);
|
pop_close_angle_bracket(output);
|
||||||
|
|
||||||
if cpp_like_names {
|
for (item_def_id, ty) in projection_bounds {
|
||||||
output.push_str(", ");
|
output.push_str(", ");
|
||||||
} else {
|
|
||||||
output.push_str(" + ");
|
if cpp_like_names {
|
||||||
|
output.push_str("assoc$<");
|
||||||
|
push_item_name(tcx, item_def_id, false, output);
|
||||||
|
output.push_str(", ");
|
||||||
|
push_debuginfo_type_name(tcx, ty, true, output, visited);
|
||||||
|
push_close_angle_bracket(tcx, output);
|
||||||
|
} else {
|
||||||
|
push_item_name(tcx, item_def_id, false, output);
|
||||||
|
output.push('=');
|
||||||
|
push_debuginfo_type_name(tcx, ty, true, output, visited);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
push_close_angle_bracket(tcx, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the trailing joining characters. For cpp_like_names
|
if auto_traits.len() != 0 {
|
||||||
// this is `, ` otherwise ` + `.
|
push_auto_trait_separator(cpp_like_names, output);
|
||||||
output.pop();
|
|
||||||
output.pop();
|
|
||||||
if !cpp_like_names {
|
|
||||||
output.pop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if auto_traits.len() != 0 {
|
||||||
|
let mut auto_traits: SmallVec<[String; 4]> = auto_traits
|
||||||
|
.into_iter()
|
||||||
|
.map(|def_id| {
|
||||||
|
let mut name = String::with_capacity(20);
|
||||||
|
push_item_name(tcx, def_id, true, &mut name);
|
||||||
|
name
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
auto_traits.sort_unstable();
|
||||||
|
|
||||||
|
for auto_trait in auto_traits {
|
||||||
|
output.push_str(&auto_trait);
|
||||||
|
push_auto_trait_separator(cpp_like_names, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
pop_auto_trait_separator(cpp_like_names, output);
|
||||||
|
}
|
||||||
|
|
||||||
if cpp_like_names {
|
if cpp_like_names {
|
||||||
push_close_angle_bracket(tcx, output);
|
push_close_angle_bracket(tcx, output);
|
||||||
|
} else if has_enclosing_parens {
|
||||||
|
output.push(')');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||||
|
@ -407,6 +431,20 @@ pub fn push_debuginfo_type_name<'tcx>(
|
||||||
}
|
}
|
||||||
push_close_angle_bracket(tcx, output);
|
push_close_angle_bracket(tcx, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn auto_trait_separator(cpp_like_names: bool) -> &'static str {
|
||||||
|
if cpp_like_names { ", " } else { " + " }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) {
|
||||||
|
output.push_str(auto_trait_separator(cpp_like_names));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_auto_trait_separator(cpp_like_names: bool, output: &mut String) {
|
||||||
|
let sep = auto_trait_separator(cpp_like_names);
|
||||||
|
assert!(output.ends_with(sep));
|
||||||
|
output.truncate(output.len() - sep.len());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
|
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) {
|
||||||
output.push('>');
|
output.push('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pop_close_angle_bracket(output: &mut String) {
|
||||||
|
assert!(output.ends_with('>'));
|
||||||
|
output.pop();
|
||||||
|
if output.ends_with(' ') {
|
||||||
|
output.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn cpp_like_names(tcx: TyCtxt<'_>) -> bool {
|
fn cpp_like_names(tcx: TyCtxt<'_>) -> bool {
|
||||||
tcx.sess.target.is_like_msvc
|
tcx.sess.target.is_like_msvc
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,11 @@
|
||||||
// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
|
// gdb-check:type = &mut dyn type_names::Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
|
||||||
|
|
||||||
// gdb-command:whatis no_principal_trait
|
// gdb-command:whatis no_principal_trait
|
||||||
// gdb-check:type = alloc::boxed::Box<dyn core::marker::Send + core::marker::Sync, alloc::alloc::Global>
|
// gdb-check:type = alloc::boxed::Box<(dyn core::marker::Send + core::marker::Sync), alloc::alloc::Global>
|
||||||
|
|
||||||
|
// gdb-command:whatis has_associated_type_trait
|
||||||
|
// gdb-check:type = &(dyn type_names::Trait3<u32, AssocType=isize> + core::marker::Send)
|
||||||
|
|
||||||
|
|
||||||
// BARE FUNCTIONS
|
// BARE FUNCTIONS
|
||||||
// gdb-command:whatis rust_fn
|
// gdb-command:whatis rust_fn
|
||||||
|
@ -224,7 +228,7 @@
|
||||||
// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...]
|
// cdb-check:struct ref$<dyn$<type_names::Trait1> > ref_trait = [...]
|
||||||
// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...]
|
// cdb-check:struct ref_mut$<dyn$<type_names::Trait1> > mut_ref_trait = [...]
|
||||||
// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send, core::marker::Sync>, alloc::alloc::Global> no_principal_trait = [...]
|
// cdb-check:struct alloc::boxed::Box<dyn$<core::marker::Send, core::marker::Sync>, alloc::alloc::Global> no_principal_trait = [...]
|
||||||
// cdb-check:struct ref$<dyn$<type_names::Trait3> > has_associated_type_trait = struct ref$<dyn$<type_names::Trait3> >
|
// 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> >
|
||||||
|
|
||||||
// BARE FUNCTIONS
|
// BARE FUNCTIONS
|
||||||
// cdb-command:dv /t *_fn*
|
// cdb-command:dv /t *_fn*
|
||||||
|
@ -306,14 +310,14 @@ trait Trait1 {
|
||||||
trait Trait2<T1, T2> {
|
trait Trait2<T1, T2> {
|
||||||
fn dummy(&self, _: T1, _: T2) {}
|
fn dummy(&self, _: T1, _: T2) {}
|
||||||
}
|
}
|
||||||
trait Trait3 {
|
trait Trait3<T> {
|
||||||
type AssocType;
|
type AssocType;
|
||||||
fn dummy(&self) {}
|
fn dummy(&self) -> T { panic!() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait1 for isize {}
|
impl Trait1 for isize {}
|
||||||
impl<T1, T2> Trait2<T1, T2> for isize {}
|
impl<T1, T2> Trait2<T1, T2> for isize {}
|
||||||
impl Trait3 for isize {
|
impl<T> Trait3<T> for isize {
|
||||||
type AssocType = isize;
|
type AssocType = isize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,8 +408,8 @@ fn main() {
|
||||||
let ref_trait = &0_isize as &dyn Trait1;
|
let ref_trait = &0_isize as &dyn Trait1;
|
||||||
let mut mut_int1 = 0_isize;
|
let mut mut_int1 = 0_isize;
|
||||||
let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
|
let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
|
||||||
let no_principal_trait = (box 0_isize) as Box<dyn Send + Sync>;
|
let no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>;
|
||||||
let has_associated_type_trait = &0_isize as &dyn Trait3<AssocType = isize>;
|
let has_associated_type_trait = &0_isize as &(dyn Trait3<u32, AssocType = isize> + Send);
|
||||||
|
|
||||||
let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
|
let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
|
||||||
let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
|
let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue