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