rustc_hir/attrs/
data_structures.rs

1pub use ReprAttr::*;
2use rustc_abi::Align;
3use rustc_ast::token::CommentKind;
4use rustc_ast::{AttrStyle, ast};
5use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
6use rustc_span::def_id::DefId;
7use rustc_span::hygiene::Transparency;
8use rustc_span::{Ident, Span, Symbol};
9use thin_vec::ThinVec;
10
11use crate::attrs::pretty_printing::PrintAttribute;
12use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability};
13
14#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)]
15pub enum InlineAttr {
16    None,
17    Hint,
18    Always,
19    Never,
20    /// `#[rustc_force_inline]` forces inlining to happen in the MIR inliner - it reports an error
21    /// if the inlining cannot happen. It is limited to only free functions so that the calls
22    /// can always be resolved.
23    Force {
24        attr_span: Span,
25        reason: Option<Symbol>,
26    },
27}
28
29impl InlineAttr {
30    pub fn always(&self) -> bool {
31        match self {
32            InlineAttr::Always | InlineAttr::Force { .. } => true,
33            InlineAttr::None | InlineAttr::Hint | InlineAttr::Never => false,
34        }
35    }
36}
37
38#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)]
39pub enum InstructionSetAttr {
40    ArmA32,
41    ArmT32,
42}
43
44#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
45#[derive(Encodable, Decodable, HashStable_Generic)]
46pub enum OptimizeAttr {
47    /// No `#[optimize(..)]` attribute
48    #[default]
49    Default,
50    /// `#[optimize(none)]`
51    DoNotOptimize,
52    /// `#[optimize(speed)]`
53    Speed,
54    /// `#[optimize(size)]`
55    Size,
56}
57
58impl OptimizeAttr {
59    pub fn do_not_optimize(&self) -> bool {
60        matches!(self, Self::DoNotOptimize)
61    }
62}
63
64#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, HashStable_Generic, PrintAttribute)]
65pub enum ReprAttr {
66    ReprInt(IntType),
67    ReprRust,
68    ReprC,
69    ReprPacked(Align),
70    ReprSimd,
71    ReprTransparent,
72    ReprAlign(Align),
73}
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
114/// Successfully-parsed value of a `#[coverage(..)]` attribute.
115#[derive(Copy, Debug, Eq, PartialEq, Encodable, Decodable, Clone)]
116#[derive(HashStable_Generic, PrintAttribute)]
117pub enum CoverageAttrKind {
118    On,
119    Off,
120}
121
122impl Deprecation {
123    /// Whether an item marked with #[deprecated(since = "X")] is currently
124    /// deprecated (i.e., whether X is not greater than the current rustc
125    /// version).
126    pub fn is_in_effect(&self) -> bool {
127        match self.since {
128            DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
129            DeprecatedSince::Future => false,
130            // The `since` field doesn't have semantic purpose without `#![staged_api]`.
131            DeprecatedSince::NonStandard(_) => true,
132            // Assume deprecation is in effect if "since" field is absent or invalid.
133            DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
134        }
135    }
136
137    pub fn is_since_rustc_version(&self) -> bool {
138        matches!(self.since, DeprecatedSince::RustcVersion(_))
139    }
140}
141
142/// There are three valid forms of the attribute:
143/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
144/// `#[used(compiler)]`
145/// `#[used(linker)]`
146#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
147#[derive(HashStable_Generic, PrintAttribute)]
148pub enum UsedBy {
149    Compiler,
150    Linker,
151}
152
153#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
154#[derive(HashStable_Generic, PrintAttribute)]
155pub enum MacroUseArgs {
156    UseAll,
157    UseSpecific(ThinVec<Ident>),
158}
159
160impl Default for MacroUseArgs {
161    fn default() -> Self {
162        Self::UseSpecific(ThinVec::new())
163    }
164}
165
166#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
167pub struct StrippedCfgItem<ModId = DefId> {
168    pub parent_module: ModId,
169    pub ident: Ident,
170    pub cfg: (CfgEntry, Span),
171}
172
173impl<ModId> StrippedCfgItem<ModId> {
174    pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
175        StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg }
176    }
177}
178
179#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
180#[derive(HashStable_Generic, PrintAttribute)]
181pub enum CfgEntry {
182    All(ThinVec<CfgEntry>, Span),
183    Any(ThinVec<CfgEntry>, Span),
184    Not(Box<CfgEntry>, Span),
185    Bool(bool, Span),
186    NameValue { name: Symbol, name_span: Span, value: Option<(Symbol, Span)>, span: Span },
187    Version(Option<RustcVersion>, Span),
188}
189
190/// Possible values for the `#[linkage]` attribute, allowing to specify the
191/// linkage type for a `MonoItem`.
192///
193/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
194#[derive(Encodable, Decodable, Clone, Copy, Debug, PartialEq, Eq, Hash)]
195#[derive(HashStable_Generic, PrintAttribute)]
196pub enum Linkage {
197    AvailableExternally,
198    Common,
199    ExternalWeak,
200    External,
201    Internal,
202    LinkOnceAny,
203    LinkOnceODR,
204    WeakAny,
205    WeakODR,
206}
207
208/// Represents parsed *built-in* inert attributes.
209///
210/// ## Overview
211/// These attributes are markers that guide the compilation process and are never expanded into other code.
212/// They persist throughout the compilation phases, from AST to HIR and beyond.
213///
214/// ## Attribute Processing
215/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
216/// because different attributes have different internal structures. This enum represents the final,
217/// fully parsed form of these attributes, where each variant contains all the information and
218/// structure relevant for the specific attribute.
219///
220/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
221/// semantic attribute. For example:
222/// ```rust
223/// #[repr(C)]
224/// #[repr(packed)]
225/// struct S { }
226/// ```
227/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing
228/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the
229/// data structures defined in this enum.
230///
231/// ## Usage
232/// These parsed attributes are used throughout the compiler to:
233/// - Control code generation (e.g., `#[repr]`)
234/// - Mark API stability (`#[stable]`, `#[unstable]`)
235/// - Provide documentation (`#[doc]`)
236/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`)
237///
238/// ## Note on Attribute Organization
239/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately
240/// from this enum because they are used in specific compiler phases (like code generation) and don't
241/// need to persist throughout the entire compilation process. They are typically processed and
242/// converted into their final form earlier in the compilation pipeline.
243///
244/// For example:
245/// - `InlineAttr` is used during code generation to control function inlining
246/// - `OptimizeAttr` is used to control optimization levels
247/// - `InstructionSetAttr` is used for target-specific code generation
248///
249/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate
250/// and don't need to be preserved in the same way as the attributes in this enum.
251///
252/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate.
253///
254/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
255/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
256/// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html
257#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
258pub enum AttributeKind {
259    // tidy-alphabetical-start
260    /// Represents `#[align(N)]`.
261    // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
262    Align { align: Align, span: Span },
263
264    /// Represents `#[rustc_allow_const_fn_unstable]`.
265    AllowConstFnUnstable(ThinVec<Symbol>, Span),
266
267    /// Represents `#[rustc_allow_incoherent_impl]`.
268    AllowIncoherentImpl(Span),
269
270    /// Represents `#[allow_internal_unsafe]`.
271    AllowInternalUnsafe(Span),
272
273    /// Represents `#[allow_internal_unstable]`.
274    AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
275
276    /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
277    AsPtr(Span),
278
279    /// Represents `#[automatically_derived]`
280    AutomaticallyDerived(Span),
281
282    /// Represents `#[rustc_default_body_unstable]`.
283    BodyStability {
284        stability: DefaultBodyStability,
285        /// Span of the `#[rustc_default_body_unstable(...)]` attribute
286        span: Span,
287    },
288
289    /// Represents `#[rustc_coherence_is_core]`.
290    CoherenceIsCore,
291
292    /// Represents `#[rustc_coinductive]`.
293    Coinductive(Span),
294
295    /// Represents `#[cold]`.
296    Cold(Span),
297
298    /// Represents `#[rustc_confusables]`.
299    Confusables {
300        symbols: ThinVec<Symbol>,
301        // FIXME(jdonszelmann): remove when target validation code is moved
302        first_span: Span,
303    },
304
305    /// Represents `#[const_continue]`.
306    ConstContinue(Span),
307
308    /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
309    ConstStability {
310        stability: PartialConstStability,
311        /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
312        span: Span,
313    },
314
315    /// Represents `#[rustc_const_stable_indirect]`.
316    ConstStabilityIndirect,
317
318    /// Represents `#[const_trait]`.
319    ConstTrait(Span),
320
321    /// Represents `#[coroutine]`.
322    Coroutine(Span),
323
324    /// Represents `#[coverage(..)]`.
325    Coverage(Span, CoverageAttrKind),
326
327    ///Represents `#[rustc_deny_explicit_impl]`.
328    DenyExplicitImpl(Span),
329
330    /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
331    Deprecation { deprecation: Deprecation, span: Span },
332
333    /// Represents `#[rustc_do_not_implement_via_object]`.
334    DoNotImplementViaObject(Span),
335
336    /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
337    DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
338
339    /// Represents `#[rustc_dummy]`.
340    Dummy,
341
342    /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
343    ExportName {
344        /// The name to export this item with.
345        /// It may not contain \0 bytes as it will be converted to a null-terminated string.
346        name: Symbol,
347        span: Span,
348    },
349
350    /// Represents `#[export_stable]`.
351    ExportStable,
352
353    /// Represents `#[ffi_const]`.
354    FfiConst(Span),
355
356    /// Represents `#[ffi_pure]`.
357    FfiPure(Span),
358
359    /// Represents `#[fundamental]`.
360    Fundamental,
361
362    /// Represents `#[ignore]`
363    Ignore {
364        span: Span,
365        /// ignore can optionally have a reason: `#[ignore = "reason this is ignored"]`
366        reason: Option<Symbol>,
367    },
368
369    /// Represents `#[inline]` and `#[rustc_force_inline]`.
370    Inline(InlineAttr, Span),
371
372    /// Represents `#[link_name]`.
373    LinkName { name: Symbol, span: Span },
374
375    /// Represents `#[link_ordinal]`.
376    LinkOrdinal { ordinal: u16, span: Span },
377
378    /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
379    LinkSection { name: Symbol, span: Span },
380
381    /// Represents `#[linkage]`.
382    Linkage(Linkage, Span),
383
384    /// Represents `#[loop_match]`.
385    LoopMatch(Span),
386
387    /// Represents `#[macro_escape]`.
388    MacroEscape(Span),
389
390    /// Represents `#[rustc_macro_transparency]`.
391    MacroTransparency(Transparency),
392
393    /// Represents `#[macro_use]`.
394    MacroUse { span: Span, arguments: MacroUseArgs },
395
396    /// Represents `#[marker]`.
397    Marker(Span),
398
399    /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
400    MayDangle(Span),
401
402    /// Represents `#[must_use]`.
403    MustUse {
404        span: Span,
405        /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
406        reason: Option<Symbol>,
407    },
408
409    /// Represents `#[naked]`
410    Naked(Span),
411
412    /// Represents `#[no_implicit_prelude]`
413    NoImplicitPrelude(Span),
414
415    /// Represents `#[no_mangle]`
416    NoMangle(Span),
417
418    /// Represents `#[non_exhaustive]`
419    NonExhaustive(Span),
420
421    /// Represents `#[optimize(size|speed)]`
422    Optimize(OptimizeAttr, Span),
423
424    /// Represents `#[rustc_paren_sugar]`.
425    ParenSugar(Span),
426
427    /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
428    PassByValue(Span),
429
430    /// Represents `#[path]`
431    Path(Symbol, Span),
432
433    /// Represents `#[pointee]`
434    Pointee(Span),
435
436    /// Represents `#[proc_macro]`
437    ProcMacro(Span),
438
439    /// Represents `#[proc_macro_attribute]`
440    ProcMacroAttribute(Span),
441
442    /// Represents `#[proc_macro_derive]`
443    ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span },
444
445    /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
446    PubTransparent(Span),
447
448    /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
449    Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
450
451    /// Represents `#[rustc_builtin_macro]`.
452    RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
453
454    /// Represents `#[rustc_layout_scalar_valid_range_end]`.
455    RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
456
457    /// Represents `#[rustc_layout_scalar_valid_range_start]`.
458    RustcLayoutScalarValidRangeStart(Box<u128>, Span),
459
460    /// Represents `#[rustc_object_lifetime_default]`.
461    RustcObjectLifetimeDefault,
462
463    /// Represents `#[should_panic]`
464    ShouldPanic { reason: Option<Symbol>, span: Span },
465
466    /// Represents `#[rustc_skip_during_method_dispatch]`.
467    SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
468
469    /// Represents `#[rustc_specialization_trait]`.
470    SpecializationTrait(Span),
471
472    /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
473    Stability {
474        stability: Stability,
475        /// Span of the attribute.
476        span: Span,
477    },
478
479    /// Represents `#[rustc_std_internal_symbol]`.
480    StdInternalSymbol(Span),
481
482    /// Represents `#[target_feature(enable = "...")]`
483    TargetFeature(ThinVec<(Symbol, Span)>, Span),
484
485    /// Represents `#[track_caller]`
486    TrackCaller(Span),
487
488    /// Represents `#[type_const]`.
489    TypeConst(Span),
490
491    /// Represents `#[rustc_unsafe_specialization_marker]`.
492    UnsafeSpecializationMarker(Span),
493
494    /// Represents `#[unstable_feature_bound]`.
495    UnstableFeatureBound(ThinVec<(Symbol, Span)>),
496
497    /// Represents `#[used]`
498    Used { used_by: UsedBy, span: Span },
499    // tidy-alphabetical-end
500}