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