Skip to main content

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