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