Skip to main content

rustc_attr_ir/
lib.rs

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