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}
71pub use ReprAttr::*;
72
73pub enum TransparencyError {
74    UnknownTransparency(Symbol, Span),
75    MultipleTransparencyAttrs(Span, Span),
76}
77
78#[derive(Eq, PartialEq, Debug, Copy, Clone)]
79#[derive(Encodable, Decodable, HashStable_Generic, PrintAttribute)]
80pub enum IntType {
81    SignedInt(ast::IntTy),
82    UnsignedInt(ast::UintTy),
83}
84
85#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
86pub struct Deprecation {
87    pub since: DeprecatedSince,
88    /// The note to issue a reason.
89    pub note: Option<Symbol>,
90    /// A text snippet used to completely replace any use of the deprecated item in an expression.
91    ///
92    /// This is currently unstable.
93    pub suggestion: Option<Symbol>,
94}
95
96/// Release in which an API is deprecated.
97#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
98pub enum DeprecatedSince {
99    RustcVersion(RustcVersion),
100    /// Deprecated in the future ("to be determined").
101    Future,
102    /// `feature(staged_api)` is off. Deprecation versions outside the standard
103    /// library are allowed to be arbitrary strings, for better or worse.
104    NonStandard(Symbol),
105    /// Deprecation version is unspecified but optional.
106    Unspecified,
107    /// Failed to parse a deprecation version, or the deprecation version is
108    /// unspecified and required. An error has already been emitted.
109    Err,
110}
111
112impl Deprecation {
113    /// Whether an item marked with #[deprecated(since = "X")] is currently
114    /// deprecated (i.e., whether X is not greater than the current rustc
115    /// version).
116    pub fn is_in_effect(&self) -> bool {
117        match self.since {
118            DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
119            DeprecatedSince::Future => false,
120            // The `since` field doesn't have semantic purpose without `#![staged_api]`.
121            DeprecatedSince::NonStandard(_) => true,
122            // Assume deprecation is in effect if "since" field is absent or invalid.
123            DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
124        }
125    }
126
127    pub fn is_since_rustc_version(&self) -> bool {
128        matches!(self.since, DeprecatedSince::RustcVersion(_))
129    }
130}
131
132/// There are three valid forms of the attribute:
133/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
134/// `#[used(compiler)]`
135/// `#[used(linker)]`
136#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
137#[derive(HashStable_Generic, PrintAttribute)]
138pub enum UsedBy {
139    Compiler,
140    Linker,
141}
142
143/// Represents parsed *built-in* inert attributes.
144///
145/// ## Overview
146/// These attributes are markers that guide the compilation process and are never expanded into other code.
147/// They persist throughout the compilation phases, from AST to HIR and beyond.
148///
149/// ## Attribute Processing
150/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
151/// because different attributes have different internal structures. This enum represents the final,
152/// fully parsed form of these attributes, where each variant contains all the information and
153/// structure relevant for the specific attribute.
154///
155/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
156/// semantic attribute. For example:
157/// ```rust
158/// #[repr(C)]
159/// #[repr(packed)]
160/// struct S { }
161/// ```
162/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing
163/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the
164/// data structures defined in this enum.
165///
166/// ## Usage
167/// These parsed attributes are used throughout the compiler to:
168/// - Control code generation (e.g., `#[repr]`)
169/// - Mark API stability (`#[stable]`, `#[unstable]`)
170/// - Provide documentation (`#[doc]`)
171/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`)
172///
173/// ## Note on Attribute Organization
174/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately
175/// from this enum because they are used in specific compiler phases (like code generation) and don't
176/// need to persist throughout the entire compilation process. They are typically processed and
177/// converted into their final form earlier in the compilation pipeline.
178///
179/// For example:
180/// - `InlineAttr` is used during code generation to control function inlining
181/// - `OptimizeAttr` is used to control optimization levels
182/// - `InstructionSetAttr` is used for target-specific code generation
183///
184/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate
185/// and don't need to be preserved in the same way as the attributes in this enum.
186///
187/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate.
188///
189/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
190/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
191/// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html
192#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
193pub enum AttributeKind {
194    // tidy-alphabetical-start
195    /// Represents `#[align(N)]`.
196    Align { align: Align, span: Span },
197
198    /// Represents `#[rustc_allow_const_fn_unstable]`.
199    AllowConstFnUnstable(ThinVec<Symbol>, Span),
200
201    /// Represents `#[allow_internal_unstable]`.
202    AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
203
204    /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
205    AsPtr(Span),
206
207    /// Represents `#[rustc_default_body_unstable]`.
208    BodyStability {
209        stability: DefaultBodyStability,
210        /// Span of the `#[rustc_default_body_unstable(...)]` attribute
211        span: Span,
212    },
213
214    /// Represents `#[cold]`.
215    Cold(Span),
216
217    /// Represents `#[rustc_confusables]`.
218    Confusables {
219        symbols: ThinVec<Symbol>,
220        // FIXME(jdonszelmann): remove when target validation code is moved
221        first_span: Span,
222    },
223
224    /// Represents `#[const_continue]`.
225    ConstContinue(Span),
226
227    /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
228    ConstStability {
229        stability: PartialConstStability,
230        /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
231        span: Span,
232    },
233
234    /// Represents `#[rustc_const_stable_indirect]`.
235    ConstStabilityIndirect,
236
237    /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
238    Deprecation { deprecation: Deprecation, span: Span },
239
240    /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
241    DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
242
243    /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
244    ExportName {
245        /// The name to export this item with.
246        /// It may not contain \0 bytes as it will be converted to a null-terminated string.
247        name: Symbol,
248        span: Span,
249    },
250
251    /// Represents `#[ignore]`
252    Ignore {
253        span: Span,
254        /// ignore can optionally have a reason: `#[ignore = "reason this is ignored"]`
255        reason: Option<Symbol>,
256    },
257
258    /// Represents `#[inline]` and `#[rustc_force_inline]`.
259    Inline(InlineAttr, Span),
260
261    /// Represents `#[link_name]`.
262    LinkName { name: Symbol, span: Span },
263
264    /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
265    LinkSection { name: Symbol, span: Span },
266
267    /// Represents `#[loop_match]`.
268    LoopMatch(Span),
269
270    /// Represents `#[rustc_macro_transparency]`.
271    MacroTransparency(Transparency),
272
273    /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
274    MayDangle(Span),
275
276    /// Represents `#[must_use]`.
277    MustUse {
278        span: Span,
279        /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
280        reason: Option<Symbol>,
281    },
282
283    /// Represents `#[naked]`
284    Naked(Span),
285
286    /// Represents `#[no_implicit_prelude]`
287    NoImplicitPrelude(Span),
288
289    /// Represents `#[no_mangle]`
290    NoMangle(Span),
291
292    /// Represents `#[non_exhaustive]`
293    NonExhaustive(Span),
294
295    /// Represents `#[optimize(size|speed)]`
296    Optimize(OptimizeAttr, Span),
297
298    /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
299    PassByValue(Span),
300
301    /// Represents `#[path]`
302    Path(Symbol, Span),
303
304    /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
305    PubTransparent(Span),
306
307    /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
308    Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
309
310    /// Represents `#[rustc_layout_scalar_valid_range_end]`.
311    RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
312
313    /// Represents `#[rustc_layout_scalar_valid_range_start]`.
314    RustcLayoutScalarValidRangeStart(Box<u128>, Span),
315
316    /// Represents `#[rustc_object_lifetime_default]`.
317    RustcObjectLifetimeDefault,
318
319    /// Represents `#[rustc_skip_during_method_dispatch]`.
320    SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
321
322    /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
323    Stability {
324        stability: Stability,
325        /// Span of the attribute.
326        span: Span,
327    },
328
329    /// Represents `#[target_feature(enable = "...")]`
330    TargetFeature(ThinVec<(Symbol, Span)>, Span),
331
332    /// Represents `#[track_caller]`
333    TrackCaller(Span),
334
335    /// Represents `#[used]`
336    Used { used_by: UsedBy, span: Span },
337    // tidy-alphabetical-end
338}