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");