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