1use std::num::NonZero;
2use std::ops::Deref;
3use std::path::PathBuf;
4
5use rustc_abi::Align;
6use rustc_ast::ast::{Path, join_path_idents};
7use rustc_ast::attr::data_structures::CfgEntry;
8use rustc_ast::attr::version::RustcVersion;
9use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
10use rustc_ast::token::{CommentKind, DocFragmentKind};
11use rustc_ast::{AttrId, AttrStyle, IntTy, UintTy};
12use rustc_ast_pretty::pp::Printer;
13use rustc_data_structures::fx::FxIndexMap;
14use rustc_span::def_id::DefId;
15use rustc_span::hygiene::Transparency;
16use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
17use rustc_structures::{CollapseMacroDebuginfo, CrateType, Limit, NativeLibKind, SanitizerSet};
18use thin_vec::ThinVec;
19
20pub trait PrintAttribute {
27 fn should_render(&self) -> bool;
31
32 fn print_attribute(&self, p: &mut Printer);
33}
34
35impl<T: PrintAttribute> PrintAttribute for &T {
36 fn should_render(&self) -> bool {
37 T::should_render(self)
38 }
39
40 fn print_attribute(&self, p: &mut Printer) {
41 T::print_attribute(self, p)
42 }
43}
44impl<T: PrintAttribute> PrintAttribute for Box<T> {
45 fn should_render(&self) -> bool {
46 self.deref().should_render()
47 }
48
49 fn print_attribute(&self, p: &mut Printer) {
50 T::print_attribute(self.deref(), p)
51 }
52}
53impl<T: PrintAttribute> PrintAttribute for Option<T> {
54 fn should_render(&self) -> bool {
55 self.as_ref().is_some_and(|x| x.should_render())
56 }
57
58 fn print_attribute(&self, p: &mut Printer) {
59 if let Some(i) = self {
60 T::print_attribute(i, p)
61 }
62 }
63}
64impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
65 fn should_render(&self) -> bool {
66 self.is_empty() || self[0].should_render()
67 }
68
69 fn print_attribute(&self, p: &mut Printer) {
70 let mut last_printed = false;
71 p.word("[");
72 for i in self {
73 if last_printed {
74 p.word_space(",");
75 }
76 i.print_attribute(p);
77 last_printed = i.should_render();
78 }
79 p.word("]");
80 }
81}
82impl<T: PrintAttribute, T2: PrintAttribute> PrintAttribute for FxIndexMap<T, T2> {
83 fn should_render(&self) -> bool {
84 self.is_empty() || self[0].should_render()
85 }
86
87 fn print_attribute(&self, p: &mut Printer) {
88 let mut last_printed = false;
89 p.word("[");
90 for (i, _) in self {
91 if last_printed {
92 p.word_space(",");
93 }
94 i.print_attribute(p);
95 last_printed = i.should_render();
96 }
97 p.word("]");
98 }
99}
100impl PrintAttribute for PathBuf {
101 fn should_render(&self) -> bool {
102 true
103 }
104
105 fn print_attribute(&self, p: &mut Printer) {
106 p.word(self.display().to_string());
107 }
108}
109impl PrintAttribute for Path {
110 fn should_render(&self) -> bool {
111 true
112 }
113
114 fn print_attribute(&self, p: &mut Printer) {
115 p.word(join_path_idents(self.segments.iter().map(|seg| seg.ident)));
116 }
117}
118
119macro_rules! print_skip {
120 ($($t: ty),* $(,)?) => {$(
121 impl PrintAttribute for $t {
122 fn should_render(&self) -> bool { false }
123 fn print_attribute(&self, _: &mut Printer) { }
124 })*
125 };
126}
127
128macro_rules! print_disp {
129 ($($t: ty),* $(,)?) => {$(
130 impl PrintAttribute for $t {
131 fn should_render(&self) -> bool { true }
132 fn print_attribute(&self, p: &mut Printer) {
133 p.word(format!("{}", self));
134 }
135 }
136 )*};
137}
138macro_rules! print_debug {
139 ($($t: ty),* $(,)?) => {$(
140 impl PrintAttribute for $t {
141 fn should_render(&self) -> bool { true }
142 fn print_attribute(&self, p: &mut Printer) {
143 p.word(format!("{:?}", self));
144 }
145 }
146 )*};
147}
148
149macro_rules! print_tup {
150 (num_should_render $($ts: ident)*) => { 0 $(+ $ts.should_render() as usize)* };
151 () => {};
152 ($t: ident $($ts: ident)*) => {
153 #[allow(non_snake_case, unused)]
154 impl<$t: PrintAttribute, $($ts: PrintAttribute),*> PrintAttribute for ($t, $($ts),*) {
155 fn should_render(&self) -> bool {
156 let ($t, $($ts),*) = self;
157 print_tup!(num_should_render $t $($ts)*) != 0
158 }
159
160 fn print_attribute(&self, p: &mut Printer) {
161 let ($t, $($ts),*) = self;
162 let parens = print_tup!(num_should_render $t $($ts)*) > 1;
163 if parens {
164 p.popen();
165 }
166
167 let mut printed_anything = $t.should_render();
168
169 $t.print_attribute(p);
170
171 $(
172 if $ts.should_render() {
173 if printed_anything {
174 p.word_space(",");
175 }
176 printed_anything = true;
177 }
178 $ts.print_attribute(p);
179 )*
180
181 if parens {
182 p.pclose();
183 }
184 }
185 }
186
187 print_tup!($($ts)*);
188 };
189}
190
191#[allow(non_snake_case, unused)]
impl<H: PrintAttribute> PrintAttribute for (H,) {
fn should_render(&self) -> bool {
let (H,) = self;
0 + H.should_render() as usize != 0
}
fn print_attribute(&self, p: &mut Printer) {
let (H,) = self;
let parens = 0 + H.should_render() as usize > 1;
if parens { p.popen(); }
let mut printed_anything = H.should_render();
H.print_attribute(p);
if parens { p.pclose(); }
}
}print_tup!(A B C D E F G H);
192impl PrintAttribute for Span {
fn should_render(&self) -> bool { false }
fn print_attribute(&self, _: &mut Printer) {}
}
impl PrintAttribute for () {
fn should_render(&self) -> bool { false }
fn print_attribute(&self, _: &mut Printer) {}
}
impl PrintAttribute for ErrorGuaranteed {
fn should_render(&self) -> bool { false }
fn print_attribute(&self, _: &mut Printer) {}
}
impl PrintAttribute for AttrId {
fn should_render(&self) -> bool { false }
fn print_attribute(&self, _: &mut Printer) {}
}print_skip!(Span, (), ErrorGuaranteed, AttrId);
193impl PrintAttribute for u8 {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for u16 {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for u32 {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for u128 {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for usize {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for bool {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for NonZero<u32> {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}
impl PrintAttribute for Limit {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", self))
}));
}
}print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit);
194impl PrintAttribute for Symbol {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for Ident {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for UintTy {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for IntTy {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for Align {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for AttrStyle {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for CommentKind {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for DocFragmentKind {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for Transparency {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for SanitizerSet {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for DefId {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for RustcVersion {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for CfgEntry {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for DiffActivity {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for DiffMode {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for CrateType {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for NativeLibKind {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}
impl PrintAttribute for CollapseMacroDebuginfo {
fn should_render(&self) -> bool { true }
fn print_attribute(&self, p: &mut Printer) {
p.word(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", self))
}));
}
}print_debug!(
195 Symbol,
196 Ident,
197 UintTy,
198 IntTy,
199 Align,
200 AttrStyle,
201 CommentKind,
202 DocFragmentKind,
203 Transparency,
204 SanitizerSet,
205 DefId,
206 RustcVersion,
207 CfgEntry,
208 DiffActivity,
209 DiffMode,
210 CrateType,
211 NativeLibKind,
212 CollapseMacroDebuginfo,
213);