Rollup merge of #138063 - compiler-errors:improve-attr-unpretty, r=jdonszelmann

Improve `-Zunpretty=hir` for parsed attrs

0. Rename `print_something` to `should_render` to make it distinct from `print_attribute` in that it doesn't print anything, it's just a way to probe if a type renders anything.
1. Fixes a few bugs in the `PrintAttribute` derive. Namely, the `__printed_anything` variable was entangled with the `should_render` call, leading us to always render field names but never render commas.
2. Remove the outermost `""` from the attr.
3. Debug print `Symbol`s. I know that this is redundant for some parsed attributes, but there's no good way to distinguish symbols that are ident-like and symbols which are cooked string literals. We could perhaps *conditionally* to fall back to a debug printing if the symbol doesn't match an ident? But seems like overkill.

Based on #138060, only review the commits not in that one.
This commit is contained in:
Jakub Beránek 2025-03-11 13:30:51 +01:00 committed by GitHub
commit c054bac89a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 60 additions and 52 deletions

View file

@ -35,13 +35,17 @@ pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStabl
/// like [`Span`]s and empty tuples, are gracefully skipped so they don't clutter the
/// representation much.
pub trait PrintAttribute {
fn print_something(&self) -> bool;
/// Whether or not this will render as something meaningful, or if it's skipped
/// (which will force the containing struct to also skip printing a comma
/// and the field name).
fn should_render(&self) -> bool;
fn print_attribute(&self, p: &mut Printer);
}
impl<T: PrintAttribute> PrintAttribute for &T {
fn print_something(&self) -> bool {
T::print_something(self)
fn should_render(&self) -> bool {
T::should_render(self)
}
fn print_attribute(&self, p: &mut Printer) {
@ -49,9 +53,10 @@ impl<T: PrintAttribute> PrintAttribute for &T {
}
}
impl<T: PrintAttribute> PrintAttribute for Option<T> {
fn print_something(&self) -> bool {
self.as_ref().is_some_and(|x| x.print_something())
fn should_render(&self) -> bool {
self.as_ref().is_some_and(|x| x.should_render())
}
fn print_attribute(&self, p: &mut Printer) {
if let Some(i) = self {
T::print_attribute(i, p)
@ -59,9 +64,10 @@ impl<T: PrintAttribute> PrintAttribute for Option<T> {
}
}
impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
fn print_something(&self) -> bool {
self.is_empty() || self[0].print_something()
fn should_render(&self) -> bool {
self.is_empty() || self[0].should_render()
}
fn print_attribute(&self, p: &mut Printer) {
let mut last_printed = false;
p.word("[");
@ -70,7 +76,7 @@ impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
p.word_space(",");
}
i.print_attribute(p);
last_printed = i.print_something();
last_printed = i.should_render();
}
p.word("]");
}
@ -78,7 +84,7 @@ impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
macro_rules! print_skip {
($($t: ty),* $(,)?) => {$(
impl PrintAttribute for $t {
fn print_something(&self) -> bool { false }
fn should_render(&self) -> bool { false }
fn print_attribute(&self, _: &mut Printer) { }
})*
};
@ -87,7 +93,7 @@ macro_rules! print_skip {
macro_rules! print_disp {
($($t: ty),* $(,)?) => {$(
impl PrintAttribute for $t {
fn print_something(&self) -> bool { true }
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(format!("{}", self));
}
@ -97,7 +103,7 @@ macro_rules! print_disp {
macro_rules! print_debug {
($($t: ty),* $(,)?) => {$(
impl PrintAttribute for $t {
fn print_something(&self) -> bool { true }
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(format!("{:?}", self));
}
@ -106,37 +112,39 @@ macro_rules! print_debug {
}
macro_rules! print_tup {
(num_print_something $($ts: ident)*) => { 0 $(+ $ts.print_something() as usize)* };
(num_should_render $($ts: ident)*) => { 0 $(+ $ts.should_render() as usize)* };
() => {};
($t: ident $($ts: ident)*) => {
#[allow(non_snake_case, unused)]
impl<$t: PrintAttribute, $($ts: PrintAttribute),*> PrintAttribute for ($t, $($ts),*) {
fn print_something(&self) -> bool {
fn should_render(&self) -> bool {
let ($t, $($ts),*) = self;
print_tup!(num_print_something $t $($ts)*) != 0
print_tup!(num_should_render $t $($ts)*) != 0
}
fn print_attribute(&self, p: &mut Printer) {
let ($t, $($ts),*) = self;
let parens = print_tup!(num_print_something $t $($ts)*) > 1;
let parens = print_tup!(num_should_render $t $($ts)*) > 1;
if parens {
p.word("(");
p.popen();
}
let mut printed_anything = $t.print_something();
let mut printed_anything = $t.should_render();
$t.print_attribute(p);
$(
if printed_anything && $ts.print_something() {
p.word_space(",");
if $ts.should_render() {
if printed_anything {
p.word_space(",");
}
printed_anything = true;
}
$ts.print_attribute(p);
)*
if parens {
p.word(")");
p.pclose();
}
}
}
@ -147,8 +155,8 @@ macro_rules! print_tup {
print_tup!(A B C D E F G H);
print_skip!(Span, ());
print_disp!(Symbol, u16, bool, NonZero<u32>);
print_debug!(UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
print_disp!(u16, bool, NonZero<u32>);
print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
/// Finds attributes in sequences of attributes by pattern matching.
///