rustc_attr_data_structures/
lib.rs1#![allow(internal_features)]
3#![doc(rust_logo)]
4#![feature(rustdoc_internals)]
5mod attributes;
8mod stability;
9mod version;
10
11use std::num::NonZero;
12
13pub use attributes::*;
14use rustc_abi::Align;
15use rustc_ast::token::CommentKind;
16use rustc_ast::{AttrStyle, IntTy, UintTy};
17use rustc_ast_pretty::pp::Printer;
18use rustc_span::hygiene::Transparency;
19use rustc_span::{Span, Symbol};
20pub use stability::*;
21use thin_vec::ThinVec;
22pub use version::*;
23
24pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext {}
28
29pub trait PrintAttribute {
36 fn should_render(&self) -> bool;
40
41 fn print_attribute(&self, p: &mut Printer);
42}
43
44impl<T: PrintAttribute> PrintAttribute for &T {
45 fn should_render(&self) -> bool {
46 T::should_render(self)
47 }
48
49 fn print_attribute(&self, p: &mut Printer) {
50 T::print_attribute(self, 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}
82macro_rules! print_skip {
83 ($($t: ty),* $(,)?) => {$(
84 impl PrintAttribute for $t {
85 fn should_render(&self) -> bool { false }
86 fn print_attribute(&self, _: &mut Printer) { }
87 })*
88 };
89}
90
91macro_rules! print_disp {
92 ($($t: ty),* $(,)?) => {$(
93 impl PrintAttribute for $t {
94 fn should_render(&self) -> bool { true }
95 fn print_attribute(&self, p: &mut Printer) {
96 p.word(format!("{}", self));
97 }
98 }
99 )*};
100}
101macro_rules! print_debug {
102 ($($t: ty),* $(,)?) => {$(
103 impl PrintAttribute for $t {
104 fn should_render(&self) -> bool { true }
105 fn print_attribute(&self, p: &mut Printer) {
106 p.word(format!("{:?}", self));
107 }
108 }
109 )*};
110}
111
112macro_rules! print_tup {
113 (num_should_render $($ts: ident)*) => { 0 $(+ $ts.should_render() as usize)* };
114 () => {};
115 ($t: ident $($ts: ident)*) => {
116 #[allow(non_snake_case, unused)]
117 impl<$t: PrintAttribute, $($ts: PrintAttribute),*> PrintAttribute for ($t, $($ts),*) {
118 fn should_render(&self) -> bool {
119 let ($t, $($ts),*) = self;
120 print_tup!(num_should_render $t $($ts)*) != 0
121 }
122
123 fn print_attribute(&self, p: &mut Printer) {
124 let ($t, $($ts),*) = self;
125 let parens = print_tup!(num_should_render $t $($ts)*) > 1;
126 if parens {
127 p.popen();
128 }
129
130 let mut printed_anything = $t.should_render();
131
132 $t.print_attribute(p);
133
134 $(
135 if $ts.should_render() {
136 if printed_anything {
137 p.word_space(",");
138 }
139 printed_anything = true;
140 }
141 $ts.print_attribute(p);
142 )*
143
144 if parens {
145 p.pclose();
146 }
147 }
148 }
149
150 print_tup!($($ts)*);
151 };
152}
153
154print_tup!(A B C D E F G H);
155print_skip!(Span, ());
156print_disp!(u16, bool, NonZero<u32>);
157print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
158
159#[macro_export]
178macro_rules! find_attr {
179 ($attributes_list: expr, $pattern: pat $(if $guard: expr)?) => {{
180 $crate::find_attr!($attributes_list, $pattern $(if $guard)? => ()).is_some()
181 }};
182
183 ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
184 'done: {
185 for i in $attributes_list {
186 let i: &rustc_hir::Attribute = i;
187 match i {
188 rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => {
189 break 'done Some($e);
190 }
191 _ => {}
192 }
193 }
194
195 None
196 }
197 }};
198}