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::{Ident, 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::*;
72use rustc_span::def_id::DefId;
73
74pub enum TransparencyError {
75    UnknownTransparency(Symbol, Span),
76    MultipleTransparencyAttrs(Span, Span),
77}
78
79#[derive(Eq, PartialEq, Debug, Copy, Clone)]
80#[derive(Encodable, Decodable, HashStable_Generic, PrintAttribute)]
81pub enum IntType {
82    SignedInt(ast::IntTy),
83    UnsignedInt(ast::UintTy),
84}
85
86#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
87pub struct Deprecation {
88    pub since: DeprecatedSince,
89    /// The note to issue a reason.
90    pub note: Option<Symbol>,
91    /// A text snippet used to completely replace any use of the deprecated item in an expression.
92    ///
93    /// This is currently unstable.
94    pub suggestion: Option<Symbol>,
95}
96
97/// Release in which an API is deprecated.
98#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
99pub enum DeprecatedSince {
100    RustcVersion(RustcVersion),
101    /// Deprecated in the future ("to be determined").
102    Future,
103    /// `feature(staged_api)` is off. Deprecation versions outside the standard
104    /// library are allowed to be arbitrary strings, for better or worse.
105    NonStandard(Symbol),
106    /// Deprecation version is unspecified but optional.
107    Unspecified,
108    /// Failed to parse a deprecation version, or the deprecation version is
109    /// unspecified and required. An error has already been emitted.
110    Err,
111}
112
113#[derive(
114    Copy,
115    Debug,
116    Eq,
117    PartialEq,
118    Encodable,
119    Decodable,
120    Clone,
121    HashStable_Generic,
122    PrintAttribute
123)]
124pub enum CoverageStatus {
125    On,
126    Off,
127}
128
129impl Deprecation {
130    /// Whether an item marked with #[deprecated(since = "X")] is currently
131    /// deprecated (i.e., whether X is not greater than the current rustc
132    /// version).
133    pub fn is_in_effect(&self) -> bool {
134        match self.since {
135            DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
136            DeprecatedSince::Future => false,
137            // The `since` field doesn't have semantic purpose without `#![staged_api]`.
138            DeprecatedSince::NonStandard(_) => true,
139            // Assume deprecation is in effect if "since" field is absent or invalid.
140            DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
141        }
142    }
143
144    pub fn is_since_rustc_version(&self) -> bool {
145        matches!(self.since, DeprecatedSince::RustcVersion(_))
146    }
147}
148
149/// There are three valid forms of the attribute:
150/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
151/// `#[used(compiler)]`
152/// `#[used(linker)]`
153#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
154#[derive(HashStable_Generic, PrintAttribute)]
155pub enum UsedBy {
156    Compiler,
157    Linker,
158}
159
160#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
161pub struct StrippedCfgItem<ModId = DefId> {
162    pub parent_module: ModId,
163    pub ident: Ident,
164    pub cfg: (CfgEntry, Span),
165}
166
167impl<ModId> StrippedCfgItem<ModId> {
168    pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
169        StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg }
170    }
171}
172
173#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
174#[derive(HashStable_Generic, PrintAttribute)]
175pub enum CfgEntry {
176    All(ThinVec<CfgEntry>, Span),
177    Any(ThinVec<CfgEntry>, Span),
178    Not(Box<CfgEntry>, Span),
179    Bool(bool, Span),
180    NameValue { name: Symbol, name_span: Span, value: Option<(Symbol, Span)>, span: Span },
181    Version(Option<RustcVersion>, Span),
182}
183
184/// Represents parsed *built-in* inert attributes.
185///
186/// ## Overview
187/// These attributes are markers that guide the compilation process and are never expanded into other code.
188/// They persist throughout the compilation phases, from AST to HIR and beyond.
189///
190/// ## Attribute Processing
191/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
192/// because different attributes have different internal structures. This enum represents the final,
193/// fully parsed form of these attributes, where each variant contains all the information and
194/// structure relevant for the specific attribute.
195///
196/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
197/// semantic attribute. For example:
198/// ```rust
199/// #[repr(C)]
200/// #[repr(packed)]
201/// struct S { }
202/// ```
203/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing
204/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the
205/// data structures defined in this enum.
206///
207/// ## Usage
208/// These parsed attributes are used throughout the compiler to:
209/// - Control code generation (e.g., `#[repr]`)
210/// - Mark API stability (`#[stable]`, `#[unstable]`)
211/// - Provide documentation (`#[doc]`)
212/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`)
213///
214/// ## Note on Attribute Organization
215/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately
216/// from this enum because they are used in specific compiler phases (like code generation) and don't
217/// need to persist throughout the entire compilation process. They are typically processed and
218/// converted into their final form earlier in the compilation pipeline.
219///
220/// For example:
221/// - `InlineAttr` is used during code generation to control function inlining
222/// - `OptimizeAttr` is used to control optimization levels
223/// - `InstructionSetAttr` is used for target-specific code generation
224///
225/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate
226/// and don't need to be preserved in the same way as the attributes in this enum.
227///
228/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate.
229///
230/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
231/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
232/// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html
233#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
234pub enum AttributeKind {
235    // tidy-alphabetical-start
236    /// Represents `#[align(N)]`.
237    Align { align: Align, span: Span },
238
239    /// Represents `#[rustc_allow_const_fn_unstable]`.
240    AllowConstFnUnstable(ThinVec<Symbol>, Span),
241
242    /// Represents `#[rustc_allow_incoherent_impl]`.
243    AllowIncoherentImpl(Span),
244
245    /// Represents `#[allow_internal_unstable]`.
246    AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
247
248    /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
249    AsPtr(Span),
250
251    /// Represents `#[automatically_derived]`
252    AutomaticallyDerived(Span),
253
254    /// Represents `#[rustc_default_body_unstable]`.
255    BodyStability {
256        stability: DefaultBodyStability,
257        /// Span of the `#[rustc_default_body_unstable(...)]` attribute
258        span: Span,
259    },
260
261    /// Represents `#[rustc_coherence_is_core]`.
262    CoherenceIsCore,
263
264    /// Represents `#[rustc_coinductive]`.
265    Coinductive(Span),
266
267    /// Represents `#[cold]`.
268    Cold(Span),
269
270    /// Represents `#[rustc_confusables]`.
271    Confusables {
272        symbols: ThinVec<Symbol>,
273        // FIXME(jdonszelmann): remove when target validation code is moved
274        first_span: Span,
275    },
276
277    /// Represents `#[const_continue]`.
278    ConstContinue(Span),
279
280    /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
281    ConstStability {
282        stability: PartialConstStability,
283        /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
284        span: Span,
285    },
286
287    /// Represents `#[rustc_const_stable_indirect]`.
288    ConstStabilityIndirect,
289
290    /// Represents `#[const_trait]`.
291    ConstTrait(Span),
292
293    /// Represents `#[coverage]`.
294    Coverage(Span, CoverageStatus),
295
296    ///Represents `#[rustc_deny_explicit_impl]`.
297    DenyExplicitImpl(Span),
298
299    /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
300    Deprecation { deprecation: Deprecation, span: Span },
301
302    /// Represents `#[rustc_do_not_implement_via_object]`.
303    DoNotImplementViaObject(Span),
304
305    /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
306    DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
307
308    /// Represents `#[rustc_dummy]`.
309    Dummy,
310
311    /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
312    ExportName {
313        /// The name to export this item with.
314        /// It may not contain \0 bytes as it will be converted to a null-terminated string.
315        name: Symbol,
316        span: Span,
317    },
318
319    /// Represents `#[export_stable]`.
320    ExportStable,
321
322    /// Represents `#[ffi_const]`.
323    FfiConst(Span),
324
325    /// Represents `#[ffi_pure]`.
326    FfiPure(Span),
327
328    /// Represents `#[fundamental]`.
329    Fundamental,
330
331    /// Represents `#[ignore]`
332    Ignore {
333        span: Span,
334        /// ignore can optionally have a reason: `#[ignore = "reason this is ignored"]`
335        reason: Option<Symbol>,
336    },
337
338    /// Represents `#[inline]` and `#[rustc_force_inline]`.
339    Inline(InlineAttr, Span),
340
341    /// Represents `#[link_name]`.
342    LinkName { name: Symbol, span: Span },
343
344    /// Represents `#[link_ordinal]`.
345    LinkOrdinal { ordinal: u16, span: Span },
346
347    /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
348    LinkSection { name: Symbol, span: Span },
349
350    /// Represents `#[loop_match]`.
351    LoopMatch(Span),
352
353    /// Represents `#[rustc_macro_transparency]`.
354    MacroTransparency(Transparency),
355
356    /// Represents `#[marker]`.
357    Marker(Span),
358
359    /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
360    MayDangle(Span),
361
362    /// Represents `#[must_use]`.
363    MustUse {
364        span: Span,
365        /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
366        reason: Option<Symbol>,
367    },
368
369    /// Represents `#[naked]`
370    Naked(Span),
371
372    /// Represents `#[no_implicit_prelude]`
373    NoImplicitPrelude(Span),
374
375    /// Represents `#[no_mangle]`
376    NoMangle(Span),
377
378    /// Represents `#[non_exhaustive]`
379    NonExhaustive(Span),
380
381    /// Represents `#[omit_gdb_pretty_printer_section]`
382    OmitGdbPrettyPrinterSection,
383
384    /// Represents `#[optimize(size|speed)]`
385    Optimize(OptimizeAttr, Span),
386
387    /// Represents `#[rustc_paren_sugar]`.
388    ParenSugar(Span),
389
390    /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
391    PassByValue(Span),
392
393    /// Represents `#[path]`
394    Path(Symbol, Span),
395
396    /// Represents `#[pointee]`
397    Pointee(Span),
398
399    /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
400    PubTransparent(Span),
401
402    /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
403    Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
404
405    /// Represents `#[rustc_layout_scalar_valid_range_end]`.
406    RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
407
408    /// Represents `#[rustc_layout_scalar_valid_range_start]`.
409    RustcLayoutScalarValidRangeStart(Box<u128>, Span),
410
411    /// Represents `#[rustc_object_lifetime_default]`.
412    RustcObjectLifetimeDefault,
413
414    /// Represents `#[rustc_skip_during_method_dispatch]`.
415    SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
416
417    /// Represents `#[rustc_specialization_trait]`.
418    SpecializationTrait(Span),
419
420    /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
421    Stability {
422        stability: Stability,
423        /// Span of the attribute.
424        span: Span,
425    },
426
427    /// Represents `#[rustc_std_internal_symbol]`.
428    StdInternalSymbol(Span),
429
430    /// Represents `#[target_feature(enable = "...")]`
431    TargetFeature(ThinVec<(Symbol, Span)>, Span),
432
433    /// Represents `#[track_caller]`
434    TrackCaller(Span),
435
436    /// Represents `#[type_const]`.
437    TypeConst(Span),
438
439    /// Represents `#[rustc_unsafe_specialization_marker]`.
440    UnsafeSpecializationMarker(Span),
441
442    /// Represents `#[unstable_feature_bound]`.
443    UnstableFeatureBound(ThinVec<(Symbol, Span)>),
444
445    /// Represents `#[used]`
446    Used { used_by: UsedBy, span: Span },
447    // tidy-alphabetical-end
448}