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