rustc_hir/attrs/
pretty_printing.rs1use std::num::NonZero;
2
3use rustc_abi::Align;
4use rustc_ast::token::CommentKind;
5use rustc_ast::{AttrStyle, IntTy, UintTy};
6use rustc_ast_pretty::pp::Printer;
7use rustc_span::hygiene::Transparency;
8use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
9use rustc_target::spec::SanitizerSet;
10use thin_vec::ThinVec;
11
12pub trait PrintAttribute {
19 fn should_render(&self) -> bool;
23
24 fn print_attribute(&self, p: &mut Printer);
25}
26
27impl PrintAttribute for u128 {
28 fn should_render(&self) -> bool {
29 true
30 }
31
32 fn print_attribute(&self, p: &mut Printer) {
33 p.word(self.to_string())
34 }
35}
36
37impl<T: PrintAttribute> PrintAttribute for &T {
38 fn should_render(&self) -> bool {
39 T::should_render(self)
40 }
41
42 fn print_attribute(&self, p: &mut Printer) {
43 T::print_attribute(self, p)
44 }
45}
46impl<T: PrintAttribute> PrintAttribute for Option<T> {
47 fn should_render(&self) -> bool {
48 self.as_ref().is_some_and(|x| x.should_render())
49 }
50
51 fn print_attribute(&self, p: &mut Printer) {
52 if let Some(i) = self {
53 T::print_attribute(i, p)
54 }
55 }
56}
57impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
58 fn should_render(&self) -> bool {
59 self.is_empty() || self[0].should_render()
60 }
61
62 fn print_attribute(&self, p: &mut Printer) {
63 let mut last_printed = false;
64 p.word("[");
65 for i in self {
66 if last_printed {
67 p.word_space(",");
68 }
69 i.print_attribute(p);
70 last_printed = i.should_render();
71 }
72 p.word("]");
73 }
74}
75macro_rules! print_skip {
76 ($($t: ty),* $(,)?) => {$(
77 impl PrintAttribute for $t {
78 fn should_render(&self) -> bool { false }
79 fn print_attribute(&self, _: &mut Printer) { }
80 })*
81 };
82}
83
84macro_rules! print_disp {
85 ($($t: ty),* $(,)?) => {$(
86 impl PrintAttribute for $t {
87 fn should_render(&self) -> bool { true }
88 fn print_attribute(&self, p: &mut Printer) {
89 p.word(format!("{}", self));
90 }
91 }
92 )*};
93}
94macro_rules! print_debug {
95 ($($t: ty),* $(,)?) => {$(
96 impl PrintAttribute for $t {
97 fn should_render(&self) -> bool { true }
98 fn print_attribute(&self, p: &mut Printer) {
99 p.word(format!("{:?}", self));
100 }
101 }
102 )*};
103}
104
105macro_rules! print_tup {
106 (num_should_render $($ts: ident)*) => { 0 $(+ $ts.should_render() as usize)* };
107 () => {};
108 ($t: ident $($ts: ident)*) => {
109 #[allow(non_snake_case, unused)]
110 impl<$t: PrintAttribute, $($ts: PrintAttribute),*> PrintAttribute for ($t, $($ts),*) {
111 fn should_render(&self) -> bool {
112 let ($t, $($ts),*) = self;
113 print_tup!(num_should_render $t $($ts)*) != 0
114 }
115
116 fn print_attribute(&self, p: &mut Printer) {
117 let ($t, $($ts),*) = self;
118 let parens = print_tup!(num_should_render $t $($ts)*) > 1;
119 if parens {
120 p.popen();
121 }
122
123 let mut printed_anything = $t.should_render();
124
125 $t.print_attribute(p);
126
127 $(
128 if $ts.should_render() {
129 if printed_anything {
130 p.word_space(",");
131 }
132 printed_anything = true;
133 }
134 $ts.print_attribute(p);
135 )*
136
137 if parens {
138 p.pclose();
139 }
140 }
141 }
142
143 print_tup!($($ts)*);
144 };
145}
146
147print_tup!(A B C D E F G H);
148print_skip!(Span, (), ErrorGuaranteed);
149print_disp!(u16, bool, NonZero<u32>);
150print_debug!(
151 Symbol,
152 Ident,
153 UintTy,
154 IntTy,
155 Align,
156 AttrStyle,
157 CommentKind,
158 Transparency,
159 SanitizerSet,
160);