rustc_hir/attrs/mod.rs
1//! Data structures for representing parsed attributes in the Rust compiler.
2//! Formerly `rustc_attr_data_structures`.
3//!
4//! For detailed documentation about attribute processing,
5//! see [rustc_attr_parsing](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html).
6
7pub use data_structures::*;
8pub use encode_cross_crate::EncodeCrossCrate;
9pub use pretty_printing::PrintAttribute;
10
11mod canonical_symbols;
12mod data_structures;
13pub mod diagnostic;
14mod encode_cross_crate;
15mod pretty_printing;
16
17/// A trait for types that can provide a list of attributes given a `TyCtxt`.
18///
19/// It allows `find_attr!` to accept either a `DefId`, `LocalDefId`, `OwnerId`, or `HirId`.
20/// It is defined here with a generic `Tcx` because `rustc_hir` can't depend on `rustc_middle`.
21/// The concrete implementations are in `rustc_middle`.
22pub trait HasAttrs<'tcx, Tcx> {
23 fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::Attribute];
24}
25
26/// Finds attributes in sequences of attributes by pattern matching.
27///
28/// A little like `matches` but for attributes.
29///
30/// ```rust,ignore (illustrative)
31/// // finds the repr attribute
32/// if let Some(r) = find_attr!(attrs, AttributeKind::Repr(r) => r) {
33///
34/// }
35///
36/// // checks if one has matched
37/// if find_attr!(attrs, AttributeKind::Repr(_)) {
38///
39/// }
40/// ```
41///
42/// Often this requires you to first end up with a list of attributes.
43/// Often these are available through the `tcx`.
44///
45/// As a convenience, this macro can do that for you!
46///
47/// Instead of providing an attribute list, provide the `tcx` and an id
48/// (a `DefId`, `LocalDefId`, `OwnerId` or `HirId`).
49///
50/// ```rust,ignore (illustrative)
51/// find_attr!(tcx, def_id, <pattern>)
52/// find_attr!(tcx, hir_id, <pattern>)
53/// ```
54///
55/// Another common case is finding attributes applied to the root of the current crate.
56/// For that, use the shortcut:
57///
58/// ```rust, ignore (illustrative)
59/// find_attr!(tcx, crate, <pattern>)
60/// ```
61#[macro_export]
62macro_rules! find_attr {
63 ($tcx: expr, crate, $pattern: pat $(if $guard: expr)?) => {
64 $crate::find_attr!($tcx, crate, $pattern $(if $guard)? => ()).is_some()
65 };
66 ($tcx: expr, crate, $pattern: pat $(if $guard: expr)? => $e: expr) => {
67 $crate::find_attr!($tcx.hir_krate_attrs(), $pattern $(if $guard)? => $e)
68 };
69
70 ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)?) => {
71 $crate::find_attr!($tcx, $id, $pattern $(if $guard)? => ()).is_some()
72 };
73 ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
74 $crate::find_attr!(
75 $crate::attrs::HasAttrs::get_attrs($id, &$tcx),
76 $pattern $(if $guard)? => $e
77 )
78 }};
79
80
81 ($attributes_list: expr, $pattern: pat $(if $guard: expr)?) => {{
82 $crate::find_attr!($attributes_list, $pattern $(if $guard)? => ()).is_some()
83 }};
84
85 ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
86 'done: {
87 for i in $attributes_list {
88 #[allow(unused_imports)]
89 use $crate::attrs::AttributeKind::*;
90 let i: &$crate::Attribute = i;
91 match i {
92 $crate::Attribute::Parsed($pattern) $(if $guard)? => {
93 break 'done Some($e);
94 }
95 $crate::Attribute::Unparsed(..) => {}
96 // In lint emitting, there's a specific exception for this warning.
97 // It's not usually emitted from inside macros from other crates
98 // (see https://github.com/rust-lang/rust/issues/110613)
99 // But this one is!
100 #[deny(unreachable_patterns)]
101 _ => {}
102 }
103 }
104
105 None
106 }
107 }};
108}