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](../rustc_attr_parsing/index.html).
5
6// tidy-alphabetical-start
7#![expect(internal_features, reason = "rustdoc_internals, for documenting attributes")]
8#![feature(const_default)]
9#![feature(const_trait_impl)]
10#![feature(default_field_values)]
11#![feature(derive_const)]
12#![feature(exhaustive_patterns)]
13#![feature(rustdoc_internals)]
14#![feature(variant_count)]
15#![recursion_limit = "256"]
16// tidy-alphabetical-end
17
18pub use attr::*;
19pub use data_structures::*;
20pub use encode_cross_crate::EncodeCrossCrate;
21pub use lang_items::*;
22pub use pretty_printing::PrintAttribute;
23pub use stability::*;
24
25mod attr;
26mod canonical_symbols;
27mod data_structures;
28pub mod diagnostic;
29pub mod diagnostic_items;
30mod encode_cross_crate;
31pub mod lang_items;
32pub mod lint;
33mod pretty_printing;
34mod stability;
35pub mod target;
36pub mod weak_lang_items;
37
38/// A trait for types that can provide a list of attributes given a `TyCtxt`.
39///
40/// It is an implementation detail of the [`find_attr!`] macro to be able to accept either a
41/// [`DefId`], [`LocalDefId`], [`OwnerId`], or [`HirId`]. It is defined here with a generic `Tcx`
42/// because this crate can't depend on `rustc_middle`. The concrete implementations are in
43/// `rustc_middle`.
44///
45/// Not to be confused with [`rustc_ast::ast_traits::HasAttrs`].
46///
47/// [`DefId`]: rustc_span::def_id::DefId
48/// [`LocalDefId`]: rustc_span::def_id::LocalDefId
49/// [`OwnerId`]: ../rustc_hir/struct.OwnerId.html
50/// [`HirId`]: ../rustc_hir/struct.HirId.html
51pub trait HasAttrs<'tcx, Tcx> {
52    fn get_attrs(self, tcx: &Tcx) -> &'tcx [crate::Attribute];
53}
54
55/// Finds attributes by pattern matching.
56///
57/// A little like `matches` but for attributes.
58///
59/// Note that this macro accepts several "id" types: [`DefId`], [`LocalDefId`], [`OwnerId`] and
60/// [`HirId`].
61///
62/// # Examples
63///
64/// It is most commonly used to check whether something has an attribute or to get its contents
65/// if it is present:
66/// ```rust,ignore (illustrative)
67/// let is_naked: bool = find_attr!(tcx, def_id, Naked(..));
68///
69/// let is_visible: bool = find_attr!(tcx, def_id, Doc(doc) if doc.hidden.is_none());
70///
71/// let link_name: Option<Symbol> = find_attr!(tcx, def_id, LinkName { name, .. } => *name);
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///
81/// If you already have a list of attributes in scope, you can also use that:
82///
83/// ```rust,ignore (illustrative)
84/// let attrs = <list of attributes>;
85///
86/// // finds the repr attribute
87/// if let Some(r) = find_attr!(attrs, Repr(r) => r) {
88///
89/// }
90///
91/// // checks if one has matched
92/// if find_attr!(attrs, Repr(_)) {
93///
94/// }
95/// ```
96///
97/// [`DefId`]: rustc_span::def_id::DefId
98/// [`LocalDefId`]: rustc_span::def_id::LocalDefId
99/// [`OwnerId`]: ../rustc_hir/struct.OwnerId.html
100/// [`HirId`]: ../rustc_hir/struct.HirId.html
101#[macro_export]
102macro_rules! find_attr {
103    ($tcx: expr, crate, $pattern: pat $(if $guard: expr)?) => {
104        $crate::find_attr!($tcx, crate, $pattern $(if $guard)? => ()).is_some()
105    };
106    ($tcx: expr, crate, $pattern: pat $(if $guard: expr)? => $e: expr) => {
107        $crate::find_attr!($tcx.hir_krate_attrs(), $pattern $(if $guard)? => $e)
108    };
109
110    ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)?) => {
111        $crate::find_attr!($tcx, $id, $pattern $(if $guard)? => ()).is_some()
112    };
113
114    ($tcx: expr, $id: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
115        $crate::find_attr!(
116            $crate::HasAttrs::get_attrs($id, &$tcx),
117            $pattern $(if $guard)? => $e
118        )
119    }};
120
121    ($attributes_list: expr, $pattern: pat $(if $guard: expr)?) => {{
122        $crate::find_attr!($attributes_list, $pattern $(if $guard)? => ()).is_some()
123    }};
124
125    ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{
126        'done: {
127            for i in $attributes_list {
128                #[allow(unused_imports)]
129                use $crate::AttributeKind::*;
130                let i: &$crate::Attribute = i;
131                match i {
132                    $crate::Attribute::Parsed($pattern) $(if $guard)? => {
133                        break 'done Some($e);
134                    }
135                    $crate::Attribute::Unparsed(..) => {}
136                    // In lint emitting, there's a specific exception for this warning.
137                    // It's not usually emitted from inside macros from other crates
138                    // (see https://github.com/rust-lang/rust/issues/110613)
139                    // But this one is!
140                    #[deny(unreachable_patterns)]
141                    _ => {}
142                }
143            }
144
145            None
146        }
147    }};
148}
149
150include!("attribute_docs.rs");