mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
[debuginfo] Emit associated type bindings in trait object type names.
This commit is contained in:
parent
b9197978a9
commit
e6e1e095ff
@ -3734,6 +3734,7 @@ dependencies = [
|
||||
"rustc_span",
|
||||
"rustc_symbol_mangling",
|
||||
"rustc_target",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
]
|
||||
|
@ -16,6 +16,7 @@ libc = "0.2.50"
|
||||
jobserver = "0.1.22"
|
||||
tempfile = "3.2"
|
||||
pathdiff = "0.2.0"
|
||||
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
|
||||
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
|
@ -19,8 +19,9 @@ use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathD
|
||||
use rustc_middle::ich::NodeIdHashingMode;
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
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 smallvec::SmallVec;
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
@ -188,63 +189,86 @@ pub fn push_debuginfo_type_name<'tcx>(
|
||||
}
|
||||
}
|
||||
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$<");
|
||||
false
|
||||
} 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() {
|
||||
let principal =
|
||||
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
|
||||
push_item_name(tcx, principal.def_id, qualified, output);
|
||||
push_generic_params_internal(tcx, principal.substs, output, visited);
|
||||
} else {
|
||||
// The auto traits come ordered by `DefPathHash`, which guarantees stability if the
|
||||
// environment is stable (e.g., incremental builds) but not otherwise (e.g.,
|
||||
// updated compiler version, different target).
|
||||
//
|
||||
// To avoid that causing instabilities in test output, sort the auto-traits
|
||||
// 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,
|
||||
}
|
||||
|
||||
let projection_bounds: SmallVec<[_; 4]> = trait_data
|
||||
.projection_bounds()
|
||||
.map(|bound| {
|
||||
let ExistentialProjection { item_def_id, ty, .. } = bound.skip_binder();
|
||||
(item_def_id, ty)
|
||||
})
|
||||
.collect();
|
||||
auto_traits.sort();
|
||||
|
||||
for name in auto_traits {
|
||||
output.push_str(&name);
|
||||
if projection_bounds.len() != 0 {
|
||||
pop_close_angle_bracket(output);
|
||||
|
||||
if cpp_like_names {
|
||||
for (item_def_id, ty) in projection_bounds {
|
||||
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
|
||||
// this is `, ` otherwise ` + `.
|
||||
output.pop();
|
||||
output.pop();
|
||||
if !cpp_like_names {
|
||||
output.pop();
|
||||
if auto_traits.len() != 0 {
|
||||
push_auto_trait_separator(cpp_like_names, output);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
push_close_angle_bracket(tcx, output);
|
||||
} else if has_enclosing_parens {
|
||||
output.push(')');
|
||||
}
|
||||
}
|
||||
ty::FnDef(..) | ty::FnPtr(_) => {
|
||||
@ -407,6 +431,20 @@ pub fn push_debuginfo_type_name<'tcx>(
|
||||
}
|
||||
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) {
|
||||
@ -555,6 +593,14 @@ fn push_close_angle_bracket<'tcx>(tcx: TyCtxt<'tcx>, output: &mut String) {
|
||||
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 {
|
||||
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-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
|
||||
// gdb-command:whatis rust_fn
|
||||
@ -224,7 +228,7 @@
|
||||
// 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 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
|
||||
// cdb-command:dv /t *_fn*
|
||||
@ -306,14 +310,14 @@ trait Trait1 {
|
||||
trait Trait2<T1, T2> {
|
||||
fn dummy(&self, _: T1, _: T2) {}
|
||||
}
|
||||
trait Trait3 {
|
||||
trait Trait3<T> {
|
||||
type AssocType;
|
||||
fn dummy(&self) {}
|
||||
fn dummy(&self) -> T { panic!() }
|
||||
}
|
||||
|
||||
impl Trait1 for isize {}
|
||||
impl<T1, T2> Trait2<T1, T2> for isize {}
|
||||
impl Trait3 for isize {
|
||||
impl<T> Trait3<T> for isize {
|
||||
type AssocType = isize;
|
||||
}
|
||||
|
||||
@ -404,8 +408,8 @@ fn main() {
|
||||
let ref_trait = &0_isize as &dyn Trait1;
|
||||
let mut mut_int1 = 0_isize;
|
||||
let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
|
||||
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 no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>;
|
||||
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_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
|
||||
|
Loading…
Reference in New Issue
Block a user