diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs
index be00d1c10e0c4..bbd3308809c33 100644
--- a/compiler/rustc_attr_data_structures/src/lib.rs
+++ b/compiler/rustc_attr_data_structures/src/lib.rs
@@ -34,13 +34,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) {
@@ -48,9 +52,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)
@@ -58,9 +63,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("[");
@@ -69,7 +75,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("]");
     }
@@ -77,7 +83,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) { }
         })*
     };
@@ -86,7 +92,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));
             }
@@ -96,7 +102,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));
             }
@@ -105,37 +111,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();
                 }
             }
         }
@@ -146,8 +154,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.
 ///
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 0e3721126fb33..2769b5343a05d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -117,9 +117,9 @@ impl<'a> State<'a> {
                 self.hardbreak()
             }
             hir::Attribute::Parsed(pa) => {
-                self.word("#[attr=\"");
+                self.word("#[attr = ");
                 pa.print_attribute(self);
-                self.word("\")]");
+                self.word("]");
                 self.hardbreak()
             }
         }
diff --git a/compiler/rustc_macros/src/print_attribute.rs b/compiler/rustc_macros/src/print_attribute.rs
index 3c6e30b851bf7..42d94e72ee942 100644
--- a/compiler/rustc_macros/src/print_attribute.rs
+++ b/compiler/rustc_macros/src/print_attribute.rs
@@ -16,12 +16,14 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
                 let name = field.ident.as_ref().unwrap();
                 let string_name = name.to_string();
                 disps.push(quote! {
-                    if __printed_anything && #name.print_something() {
-                        __p.word_space(",");
+                    if #name.should_render() {
+                        if __printed_anything {
+                            __p.word_space(",");
+                        }
+                        __p.word(#string_name);
+                        __p.word_space(":");
                         __printed_anything = true;
                     }
-                    __p.word(#string_name);
-                    __p.word_space(":");
                     #name.print_attribute(__p);
                 });
                 field_names.push(name);
@@ -31,10 +33,11 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
                 quote! { {#(#field_names),*} },
                 quote! {
                     __p.word(#string_name);
-                    if true #(&& !#field_names.print_something())* {
+                    if true #(&& !#field_names.should_render())* {
                         return;
                     }
 
+                    __p.nbsp();
                     __p.word("{");
                     #(#disps)*
                     __p.word("}");
@@ -48,8 +51,10 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
             for idx in 0..fields_unnamed.unnamed.len() {
                 let name = format_ident!("f{idx}");
                 disps.push(quote! {
-                    if __printed_anything && #name.print_something() {
-                        __p.word_space(",");
+                    if #name.should_render() {
+                        if __printed_anything {
+                            __p.word_space(",");
+                        }
                         __printed_anything = true;
                     }
                     #name.print_attribute(__p);
@@ -62,13 +67,13 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
                 quote! {
                     __p.word(#string_name);
 
-                    if true #(&& !#field_names.print_something())* {
+                    if true #(&& !#field_names.should_render())* {
                         return;
                     }
 
-                    __p.word("(");
+                    __p.popen();
                     #(#disps)*
-                    __p.word(")");
+                    __p.pclose();
                 },
                 quote! { true },
             )
@@ -138,7 +143,7 @@ pub(crate) fn print_attribute(input: Structure<'_>) -> TokenStream {
     input.gen_impl(quote! {
         #[allow(unused)]
         gen impl PrintAttribute for @Self {
-            fn print_something(&self) -> bool { #printed }
+            fn should_render(&self) -> bool { #printed }
             fn print_attribute(&self, __p: &mut rustc_ast_pretty::pp::Printer) { #code }
         }
     })
diff --git a/tests/pretty/hir-pretty-attr.pp b/tests/pretty/hir-pretty-attr.pp
index 586810b004662..d8cc8c424ca5f 100644
--- a/tests/pretty/hir-pretty-attr.pp
+++ b/tests/pretty/hir-pretty-attr.pp
@@ -6,6 +6,6 @@
 //@ pretty-mode:hir
 //@ pp-exact:hir-pretty-attr.pp
 
-#[attr="Repr([ReprC, ReprPacked(Align(4 bytes)), ReprTransparent])")]
+#[attr = Repr([ReprC, ReprPacked(Align(4 bytes)), ReprTransparent])]
 struct Example {
 }
diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs
index 82437f5ef03bb..f2bed77902b03 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -1,5 +1,5 @@
 #[repr(i32)]
-//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(SignedInt(I32))])\")]\n"]'
+//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]'
 pub enum Foo {
     //@ is    "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null
     //@ count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0
diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs
index 25bba07e8f796..201c1cdc88e7e 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -1,5 +1,5 @@
 #[repr(u32)]
-//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(UnsignedInt(U32))])\")]\n"]'
+//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(U32))])]\n"]'
 pub enum Foo {
     //@ is    "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null
     //@ count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0
diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs
index 24a32d8a9acf9..dda362a595e24 100644
--- a/tests/ui/unpretty/deprecated-attr.rs
+++ b/tests/ui/unpretty/deprecated-attr.rs
@@ -1,8 +1,6 @@
 //@ compile-flags: -Zunpretty=hir
 //@ check-pass
 
-// FIXME(jdonszelmann): the pretty printing output for deprecated (and possibly more attrs) is
-// slightly broken.
 #[deprecated]
 pub struct PlainDeprecated;
 
diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout
index 675351351a0c6..42de7b4533e51 100644
--- a/tests/ui/unpretty/deprecated-attr.stdout
+++ b/tests/ui/unpretty/deprecated-attr.stdout
@@ -5,24 +5,21 @@ extern crate std;
 //@ compile-flags: -Zunpretty=hir
 //@ check-pass
 
-// FIXME(jdonszelmann): the pretty printing output for deprecated (and possibly more attrs) is
-// slightly broken.
-#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
-suggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
 struct PlainDeprecated;
 
-#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: Unspecified, note:
+"here's why this is deprecated"}}]
 struct DirectNote;
 
-#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: Unspecified, note:
+"here's why this is deprecated"}}]
 struct ExplicitNote;
 
-#[attr="Deprecation{deprecation: Deprecation{since: NonStandard(1.2.3)note:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"),
+note: "here's why this is deprecated"}}]
 struct SinceAndNote;
 
-#[attr="Deprecation{deprecation: Deprecation{since: NonStandard(1.2.3)note:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"),
+note: "here's why this is deprecated"}}]
 struct FlippedOrder;