Skip to content

Commit 6779af2

Browse files
committed
Print regions in type_name.
Currently they are skipped, which is a bit weird, and it sometimes causes malformed output like `Foo<>` and `dyn Bar<, A = u32>`. Most regions are erased by the time `type_name` does its work. Erased regions are now printed as `'_` in non-optional places. Bound regions can also occur, and they are now printed as `'0`, `'1`, etc. The commit also renames `should_print_region` as `should_print_optional_region`, which makes it clearer that it only applies to some regions. Fixes #145168.
1 parent 2fd855f commit 6779af2

File tree

5 files changed

+44
-31
lines changed

5 files changed

+44
-31
lines changed

compiler/rustc_const_eval/src/util/type_name.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_hir::def_id::CrateNum;
55
use rustc_hir::definitions::DisambiguatedDefPathData;
66
use rustc_middle::bug;
77
use rustc_middle::ty::print::{PrettyPrinter, PrintError, Printer};
8-
use rustc_middle::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt};
8+
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt};
99

1010
struct AbsolutePathPrinter<'tcx> {
1111
tcx: TyCtxt<'tcx>,
@@ -17,10 +17,17 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
1717
self.tcx
1818
}
1919

20-
fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
21-
// This is reachable (via `pretty_print_dyn_existential`) even though
22-
// `<Self As PrettyPrinter>::should_print_region` returns false. See #144994.
23-
Ok(())
20+
fn print_region(&mut self, region: ty::Region<'_>) -> Result<(), PrintError> {
21+
match region.kind() {
22+
ty::ReErased => write!(self, "'_"),
23+
24+
// Because of this, `type_name::<dyn for<'a> Fn(&'a u32)>` will
25+
// produce "dyn core::ops::function::Fn(&'0 u32)", which isn't
26+
// great but probably better than omitting the lifetime.
27+
ty::ReBound(_, b) => write!(self, "'{}", b.var.as_u32()),
28+
29+
_ => unreachable!(),
30+
}
2431
}
2532

2633
fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError> {
@@ -125,8 +132,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
125132
args: &[GenericArg<'tcx>],
126133
) -> Result<(), PrintError> {
127134
print_prefix(self)?;
128-
let args =
129-
args.iter().cloned().filter(|arg| !matches!(arg.kind(), GenericArgKind::Lifetime(_)));
135+
let args = args.iter().cloned();
130136
if args.clone().next().is_some() {
131137
self.generic_delimiters(|cx| cx.comma_sep(args))
132138
} else {
@@ -136,8 +142,12 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
136142
}
137143

138144
impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
139-
fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
140-
false
145+
fn should_print_optional_region(&self, _region: ty::Region<'_>) -> bool {
146+
match _region.kind() {
147+
ty::ReErased => false,
148+
ty::ReBound(..) => true,
149+
_ => unreachable!(),
150+
}
141151
}
142152

143153
fn generic_delimiters(

compiler/rustc_middle/src/ty/print/pretty.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
333333
f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
334334
) -> Result<(), PrintError>;
335335

336-
/// Returns `true` if the region should be printed in
337-
/// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
338-
/// This is typically the case for all non-`'_` regions.
339-
fn should_print_region(&self, region: ty::Region<'tcx>) -> bool;
336+
/// Returns `true` if the region should be printed in optional positions,
337+
/// e.g., `&'a T` or `dyn Tr + 'b`. (Regions like the one in `Cow<'static, T>`
338+
/// will always be printed.)
339+
fn should_print_optional_region(&self, region: ty::Region<'tcx>) -> bool;
340340

341341
fn reset_type_limit(&mut self) {}
342342

@@ -710,7 +710,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
710710
}
711711
ty::Ref(r, ty, mutbl) => {
712712
write!(self, "&")?;
713-
if self.should_print_region(r) {
713+
if self.should_print_optional_region(r) {
714714
r.print(self)?;
715715
write!(self, " ")?;
716716
}
@@ -778,7 +778,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
778778
},
779779
ty::Adt(def, args) => self.print_def_path(def.did(), args)?,
780780
ty::Dynamic(data, r, repr) => {
781-
let print_r = self.should_print_region(r);
781+
let print_r = self.should_print_optional_region(r);
782782
if print_r {
783783
write!(self, "(")?;
784784
}
@@ -2487,7 +2487,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
24872487
Ok(())
24882488
}
24892489

2490-
fn should_print_region(&self, region: ty::Region<'tcx>) -> bool {
2490+
fn should_print_optional_region(&self, region: ty::Region<'tcx>) -> bool {
24912491
let highlight = self.region_highlight_mode;
24922492
if highlight.region_highlighted(region).is_some() {
24932493
return true;

compiler/rustc_symbol_mangling/src/legacy.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
235235

236236
fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> {
237237
// This might be reachable (via `pretty_print_dyn_existential`) even though
238-
// `<Self As PrettyPrinter>::should_print_region` returns false. See #144994.
238+
// `<Self As PrettyPrinter>::should_print_optional_region` returns false and
239+
// `path_generic_args` filters out lifetimes. See #144994.
239240
Ok(())
240241
}
241242

@@ -386,7 +387,6 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
386387

387388
let args =
388389
args.iter().cloned().filter(|arg| !matches!(arg.kind(), GenericArgKind::Lifetime(_)));
389-
390390
if args.clone().next().is_some() {
391391
self.generic_delimiters(|cx| cx.comma_sep(args))
392392
} else {
@@ -456,7 +456,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
456456
}
457457

458458
impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> {
459-
fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
459+
fn should_print_optional_region(&self, _region: ty::Region<'_>) -> bool {
460460
false
461461
}
462462

library/core/src/any.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,9 @@ impl fmt::Debug for TypeId {
835835
///
836836
/// The returned string must not be considered to be a unique identifier of a
837837
/// type as multiple types may map to the same type name. Similarly, there is no
838-
/// guarantee that all parts of a type will appear in the returned string: for
839-
/// example, lifetime specifiers are currently not included. In addition, the
840-
/// output may change between versions of the compiler.
838+
/// guarantee that all parts of a type will appear in the returned string. In
839+
/// addition, the output may change between versions of the compiler. For
840+
/// example, lifetime specifiers were omitted in some earlier versions.
841841
///
842842
/// The current implementation uses the same infrastructure as compiler
843843
/// diagnostics and debuginfo, but this is not guaranteed.

tests/ui/type/type-name-basic.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,28 +62,31 @@ pub fn main() {
6262

6363
t!(Vec<Vec<u32>>, "alloc::vec::Vec<alloc::vec::Vec<u32>>");
6464
t!(Foo<usize>, "type_name_basic::Foo<usize>");
65-
t!(Bar<'static>, "type_name_basic::Bar");
66-
t!(Baz<'static, u32>, "type_name_basic::Baz<u32>");
65+
t!(Bar<'static>, "type_name_basic::Bar<'_>");
66+
t!(Baz<'static, u32>, "type_name_basic::Baz<'_, u32>");
6767

68-
// FIXME: lifetime omission means these all print badly.
69-
t!(dyn TrL<'static>, "dyn type_name_basic::TrL<>");
70-
t!(dyn TrLA<'static, A = u32>, "dyn type_name_basic::TrLA<, A = u32>");
68+
t!(dyn TrL<'static>, "dyn type_name_basic::TrL<'_>");
69+
t!(dyn TrLA<'static, A = u32>, "dyn type_name_basic::TrLA<'_, A = u32>");
7170
t!(
7271
dyn TrLT<'static, Cow<'static, ()>>,
73-
"dyn type_name_basic::TrLT<, alloc::borrow::Cow<()>>"
72+
"dyn type_name_basic::TrLT<'_, alloc::borrow::Cow<'_, ()>>"
7473
);
7574
t!(
7675
dyn TrLTA<'static, u32, A = Cow<'static, ()>>,
77-
"dyn type_name_basic::TrLTA<, u32, A = alloc::borrow::Cow<()>>"
76+
"dyn type_name_basic::TrLTA<'_, u32, A = alloc::borrow::Cow<'_, ()>>"
7877
);
7978

8079
t!(fn(i32) -> i32, "fn(i32) -> i32");
81-
t!(dyn for<'a> Fn(&'a u32), "dyn core::ops::function::Fn(&u32)");
80+
81+
// FIXME: these are sub-optimal, ideally the `for<...>` would be printed.
82+
t!(dyn Fn(&'static u32), "dyn core::ops::function::Fn(&u32)");
83+
t!(dyn for<'a> Fn(&'a u32), "dyn core::ops::function::Fn(&'0 u32)");
84+
t!(dyn for<'a, 'b> Fn(&'a u32, &'b u32), "dyn core::ops::function::Fn(&'0 u32, &'1 u32)");
8285

8386
struct S<'a, T>(&'a T);
8487
impl<'a, T: Clone> S<'a, T> {
8588
fn test() {
86-
t!(Cow<'a, T>, "alloc::borrow::Cow<u32>");
89+
t!(Cow<'a, T>, "alloc::borrow::Cow<'_, u32>");
8790
}
8891
}
8992
S::<u32>::test();

0 commit comments

Comments
 (0)