rustc_attr_data_structures/
attributes.rs

1use rustc_abi::Align;
2use rustc_ast::token::CommentKind;
3use rustc_ast::{self as ast, AttrStyle};
4use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
5use rustc_span::hygiene::Transparency;
6use rustc_span::{Span, Symbol};
7use thin_vec::ThinVec;
8
9use crate::{DefaultBodyStability, PartialConstStability, PrintAttribute, RustcVersion, Stability};
10
11#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)]
12pub enum InlineAttr {
13    None,
14    Hint,
15    Always,
16    Never,
17    /// `#[rustc_force_inline]` forces inlining to happen in the MIR inliner - it reports an error
18    /// if the inlining cannot happen. It is limited to only free functions so that the calls
19    /// can always be resolved.
20    Force {
21        attr_span: Span,
22        reason: Option<Symbol>,
23    },
24}
25
26impl InlineAttr {
27    pub fn always(&self) -> bool {
28        match self {
29            InlineAttr::Always | InlineAttr::Force { .. } => true,
30            InlineAttr::None | InlineAttr::Hint | InlineAttr::Never => false,
31        }
32    }
33}
34
35#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)]
36pub enum InstructionSetAttr {
37    ArmA32,
38    ArmT32,
39}
40
41#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
42#[derive(Encodable, Decodable, HashStable_Generic)]
43pub enum OptimizeAttr {
44    /// No `#[optimize(..)]` attribute
45    #[default]
46    Default,
47    /// `#[optimize(none)]`
48    DoNotOptimize,
49    /// `#[optimize(speed)]`
50    Speed,
51    /// `#[optimize(size)]`
52    Size,
53}
54
55impl OptimizeAttr {
56    pub fn do_not_optimize(&self) -> bool {
57        matches!(self, Self::DoNotOptimize)
58    }
59}
60
61#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, HashStable_Generic, PrintAttribute)]
62pub enum ReprAttr {
63    ReprInt(IntType),
64    ReprRust,
65    ReprC,
66    ReprPacked(Align),
67    ReprSimd,
68    ReprTransparent,
69    ReprAlign(Align),
70    // this one is just so we can emit a lint for it
71    ReprEmpty,
72}
73pub use ReprAttr::*;
74
75pub enum TransparencyError {
76    UnknownTransparency(Symbol, Span),
77    MultipleTransparencyAttrs(Span, Span),
78}
79
80#[derive(Eq, PartialEq, Debug, Copy, Clone)]
81#[derive(Encodable, Decodable, HashStable_Generic, PrintAttribute)]
82pub enum IntType {
83    SignedInt(ast::IntTy),
84    UnsignedInt(ast::UintTy),
85}
86
87#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
88pub struct Deprecation {
89    pub since: DeprecatedSince,
90    /// The note to issue a reason.
91    pub note: Option<Symbol>,
92    /// A text snippet used to completely replace any use of the deprecated item in an expression.
93    ///
94    /// This is currently unstable.
95    pub suggestion: Option<Symbol>,
96}
97
98/// Release in which an API is deprecated.
99#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
100pub enum DeprecatedSince {
101    RustcVersion(RustcVersion),
102    /// Deprecated in the future ("to be determined").
103    Future,
104    /// `feature(staged_api)` is off. Deprecation versions outside the standard
105    /// library are allowed to be arbitrary strings, for better or worse.
106    NonStandard(Symbol),
107    /// Deprecation version is unspecified but optional.
108    Unspecified,
109    /// Failed to parse a deprecation version, or the deprecation version is
110    /// unspecified and required. An error has already been emitted.
111    Err,
112}
113
114impl Deprecation {
115    /// Whether an item marked with #[deprecated(since = "X")] is currently
116    /// deprecated (i.e., whether X is not greater than the current rustc
117    /// version).
118    pub fn is_in_effect(&self) -> bool {
119        match self.since {
120            DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
121            DeprecatedSince::Future => false,
122            // The `since` field doesn't have semantic purpose without `#![staged_api]`.
123            DeprecatedSince::NonStandard(_) => true,
124            // Assume deprecation is in effect if "since" field is absent or invalid.
125            DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
126        }
127    }
128
129    pub fn is_since_rustc_version(&self) -> bool {
130        matches!(self.since, DeprecatedSince::RustcVersion(_))
131    }
132}
133
134/// Represents parsed *built-in* inert attributes.
135///
136/// ## Overview
137/// These attributes are markers that guide the compilation process and are never expanded into other code.
138/// They persist throughout the compilation phases, from AST to HIR and beyond.
139///
140/// ## Attribute Processing
141/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
142/// because different attributes have different internal structures. This enum represents the final,
143/// fully parsed form of these attributes, where each variant contains contains all the information and
144/// structure relevant for the specific attribute.
145///
146/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
147/// semantic attribute. For example:
148/// ```rust
149/// #[repr(C)]
150/// #[repr(packed)]
151/// struct S { }
152/// ```
153/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing
154/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the
155/// data structures defined in this enum.
156///
157/// ## Usage
158/// These parsed attributes are used throughout the compiler to:
159/// - Control code generation (e.g., `#[repr]`)
160/// - Mark API stability (`#[stable]`, `#[unstable]`)
161/// - Provide documentation (`#[doc]`)
162/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`)
163///
164/// ## Note on Attribute Organization
165/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately
166/// from this enum because they are used in specific compiler phases (like code generation) and don't
167/// need to persist throughout the entire compilation process. They are typically processed and
168/// converted into their final form earlier in the compilation pipeline.
169///
170/// For example:
171/// - `InlineAttr` is used during code generation to control function inlining
172/// - `OptimizeAttr` is used to control optimization levels
173/// - `InstructionSetAttr` is used for target-specific code generation
174///
175/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate
176/// and don't need to be preserved in the same way as the attributes in this enum.
177///
178/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate.
179///
180/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
181/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
182/// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html
183#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
184pub enum AttributeKind {
185    // tidy-alphabetical-start
186    /// Represents `#[align(N)]`.
187    // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
188    Align { align: Align, span: Span },
189
190    /// Represents `#[rustc_allow_const_fn_unstable]`.
191    AllowConstFnUnstable(ThinVec<Symbol>),
192
193    /// Represents `#[allow_internal_unstable]`.
194    AllowInternalUnstable(ThinVec<(Symbol, Span)>),
195
196    /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
197    AsPtr(Span),
198
199    /// Represents `#[rustc_default_body_unstable]`.
200    BodyStability {
201        stability: DefaultBodyStability,
202        /// Span of the `#[rustc_default_body_unstable(...)]` attribute
203        span: Span,
204    },
205
206    /// Represents `#[cold]`.
207    Cold(Span),
208
209    /// Represents `#[rustc_confusables]`.
210    Confusables {
211        symbols: ThinVec<Symbol>,
212        // FIXME(jdonszelmann): remove when target validation code is moved
213        first_span: Span,
214    },
215
216    /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
217    ConstStability {
218        stability: PartialConstStability,
219        /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
220        span: Span,
221    },
222
223    /// Represents `#[rustc_const_stable_indirect]`.
224    ConstStabilityIndirect,
225
226    /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
227    Deprecation { deprecation: Deprecation, span: Span },
228
229    /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
230    DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
231
232    /// Represents `#[inline]` and `#[rustc_force_inline]`.
233    Inline(InlineAttr, Span),
234
235    /// Represents `#[rustc_macro_transparency]`.
236    MacroTransparency(Transparency),
237
238    /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
239    MayDangle(Span),
240
241    /// Represents `#[must_use]`.
242    MustUse {
243        span: Span,
244        /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
245        reason: Option<Symbol>,
246    },
247
248    /// Represents `#[no_mangle]`
249    NoMangle(Span),
250
251    /// Represents `#[optimize(size|speed)]`
252    Optimize(OptimizeAttr, Span),
253
254    /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
255    PubTransparent(Span),
256
257    /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
258    Repr(ThinVec<(ReprAttr, Span)>),
259
260    /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
261    Stability {
262        stability: Stability,
263        /// Span of the attribute.
264        span: Span,
265    },
266    // tidy-alphabetical-end
267}