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#[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
209#[derive(HashStable_Generic, PrintAttribute)]
210pub enum MirDialect {
211    Analysis,
212    Built,
213    Runtime,
214}
215
216#[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
217#[derive(HashStable_Generic, PrintAttribute)]
218pub enum MirPhase {
219    Initial,
220    PostCleanup,
221    Optimized,
222}
223
224/// Represents parsed *built-in* inert attributes.
225///
226/// ## Overview
227/// These attributes are markers that guide the compilation process and are never expanded into other code.
228/// They persist throughout the compilation phases, from AST to HIR and beyond.
229///
230/// ## Attribute Processing
231/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
232/// because different attributes have different internal structures. This enum represents the final,
233/// fully parsed form of these attributes, where each variant contains all the information and
234/// structure relevant for the specific attribute.
235///
236/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
237/// semantic attribute. For example:
238/// ```rust
239/// #[repr(C)]
240/// #[repr(packed)]
241/// struct S { }
242/// ```
243/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing
244/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the
245/// data structures defined in this enum.
246///
247/// ## Usage
248/// These parsed attributes are used throughout the compiler to:
249/// - Control code generation (e.g., `#[repr]`)
250/// - Mark API stability (`#[stable]`, `#[unstable]`)
251/// - Provide documentation (`#[doc]`)
252/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`)
253///
254/// ## Note on Attribute Organization
255/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately
256/// from this enum because they are used in specific compiler phases (like code generation) and don't
257/// need to persist throughout the entire compilation process. They are typically processed and
258/// converted into their final form earlier in the compilation pipeline.
259///
260/// For example:
261/// - `InlineAttr` is used during code generation to control function inlining
262/// - `OptimizeAttr` is used to control optimization levels
263/// - `InstructionSetAttr` is used for target-specific code generation
264///
265/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate
266/// and don't need to be preserved in the same way as the attributes in this enum.
267///
268/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate.
269///
270/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
271/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
272/// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html
273#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
274pub enum AttributeKind {
275    // tidy-alphabetical-start
276    /// Represents `#[align(N)]`.
277    // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
278    Align { align: Align, span: Span },
279
280    /// Represents `#[rustc_allow_const_fn_unstable]`.
281    AllowConstFnUnstable(ThinVec<Symbol>, Span),
282
283    /// Represents `#[rustc_allow_incoherent_impl]`.
284    AllowIncoherentImpl(Span),
285
286    /// Represents `#[allow_internal_unsafe]`.
287    AllowInternalUnsafe(Span),
288
289    /// Represents `#[allow_internal_unstable]`.
290    AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
291
292    /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
293    AsPtr(Span),
294
295    /// Represents `#[automatically_derived]`
296    AutomaticallyDerived(Span),
297
298    /// Represents `#[rustc_default_body_unstable]`.
299    BodyStability {
300        stability: DefaultBodyStability,
301        /// Span of the `#[rustc_default_body_unstable(...)]` attribute
302        span: Span,
303    },
304
305    /// Represents `#[rustc_coherence_is_core]`.
306    CoherenceIsCore,
307
308    /// Represents `#[rustc_coinductive]`.
309    Coinductive(Span),
310
311    /// Represents `#[cold]`.
312    Cold(Span),
313
314    /// Represents `#[rustc_confusables]`.
315    Confusables {
316        symbols: ThinVec<Symbol>,
317        // FIXME(jdonszelmann): remove when target validation code is moved
318        first_span: Span,
319    },
320
321    /// Represents `#[const_continue]`.
322    ConstContinue(Span),
323
324    /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
325    ConstStability {
326        stability: PartialConstStability,
327        /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
328        span: Span,
329    },
330
331    /// Represents `#[rustc_const_stable_indirect]`.
332    ConstStabilityIndirect,
333
334    /// Represents `#[const_trait]`.
335    ConstTrait(Span),
336
337    /// Represents `#[coroutine]`.
338    Coroutine(Span),
339
340    /// Represents `#[coverage(..)]`.
341    Coverage(Span, CoverageAttrKind),
342
343    /// Represents `#[custom_mir]`.
344    CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
345
346    ///Represents `#[rustc_deny_explicit_impl]`.
347    DenyExplicitImpl(Span),
348
349    /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
350    Deprecation { deprecation: Deprecation, span: Span },
351
352    /// Represents `#[rustc_do_not_implement_via_object]`.
353    DoNotImplementViaObject(Span),
354
355    /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
356    DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
357
358    /// Represents `#[rustc_dummy]`.
359    Dummy,
360
361    /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
362    ExportName {
363        /// The name to export this item with.
364        /// It may not contain \0 bytes as it will be converted to a null-terminated string.
365        name: Symbol,
366        span: Span,
367    },
368
369    /// Represents `#[export_stable]`.
370    ExportStable,
371
372    /// Represents `#[ffi_const]`.
373    FfiConst(Span),
374
375    /// Represents `#[ffi_pure]`.
376    FfiPure(Span),
377
378    /// Represents `#[fundamental]`.
379    Fundamental,
380
381    /// Represents `#[ignore]`
382    Ignore {
383        span: Span,
384        /// ignore can optionally have a reason: `#[ignore = "reason this is ignored"]`
385        reason: Option<Symbol>,
386    },
387
388    /// Represents `#[inline]` and `#[rustc_force_inline]`.
389    Inline(InlineAttr, Span),
390
391    /// Represents `#[link_name]`.
392    LinkName { name: Symbol, span: Span },
393
394    /// Represents `#[link_ordinal]`.
395    LinkOrdinal { ordinal: u16, span: Span },
396
397    /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
398    LinkSection { name: Symbol, span: Span },
399
400    /// Represents `#[linkage]`.
401    Linkage(Linkage, Span),
402
403    /// Represents `#[loop_match]`.
404    LoopMatch(Span),
405
406    /// Represents `#[macro_escape]`.
407    MacroEscape(Span),
408
409    /// Represents `#[rustc_macro_transparency]`.
410    MacroTransparency(Transparency),
411
412    /// Represents `#[macro_use]`.
413    MacroUse { span: Span, arguments: MacroUseArgs },
414
415    /// Represents `#[marker]`.
416    Marker(Span),
417
418    /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
419    MayDangle(Span),
420
421    /// Represents `#[must_use]`.
422    MustUse {
423        span: Span,
424        /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
425        reason: Option<Symbol>,
426    },
427
428    /// Represents `#[naked]`
429    Naked(Span),
430
431    /// Represents `#[no_implicit_prelude]`
432    NoImplicitPrelude(Span),
433
434    /// Represents `#[no_mangle]`
435    NoMangle(Span),
436
437    /// Represents `#[non_exhaustive]`
438    NonExhaustive(Span),
439
440    /// Represents `#[optimize(size|speed)]`
441    Optimize(OptimizeAttr, Span),
442
443    /// Represents `#[rustc_paren_sugar]`.
444    ParenSugar(Span),
445
446    /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
447    PassByValue(Span),
448
449    /// Represents `#[path]`
450    Path(Symbol, Span),
451
452    /// Represents `#[pointee]`
453    Pointee(Span),
454
455    /// Represents `#[proc_macro]`
456    ProcMacro(Span),
457
458    /// Represents `#[proc_macro_attribute]`
459    ProcMacroAttribute(Span),
460
461    /// Represents `#[proc_macro_derive]`
462    ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span },
463
464    /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
465    PubTransparent(Span),
466
467    /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
468    Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
469
470    /// Represents `#[rustc_builtin_macro]`.
471    RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
472
473    /// Represents `#[rustc_layout_scalar_valid_range_end]`.
474    RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
475
476    /// Represents `#[rustc_layout_scalar_valid_range_start]`.
477    RustcLayoutScalarValidRangeStart(Box<u128>, Span),
478
479    /// Represents `#[rustc_object_lifetime_default]`.
480    RustcObjectLifetimeDefault,
481
482    /// Represents `#[should_panic]`
483    ShouldPanic { reason: Option<Symbol>, span: Span },
484
485    /// Represents `#[rustc_skip_during_method_dispatch]`.
486    SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
487
488    /// Represents `#[rustc_specialization_trait]`.
489    SpecializationTrait(Span),
490
491    /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
492    Stability {
493        stability: Stability,
494        /// Span of the attribute.
495        span: Span,
496    },
497
498    /// Represents `#[rustc_std_internal_symbol]`.
499    StdInternalSymbol(Span),
500
501    /// Represents `#[target_feature(enable = "...")]`
502    TargetFeature(ThinVec<(Symbol, Span)>, Span),
503
504    /// Represents `#[track_caller]`
505    TrackCaller(Span),
506
507    /// Represents `#[type_const]`.
508    TypeConst(Span),
509
510    /// Represents `#[rustc_unsafe_specialization_marker]`.
511    UnsafeSpecializationMarker(Span),
512
513    /// Represents `#[unstable_feature_bound]`.
514    UnstableFeatureBound(ThinVec<(Symbol, Span)>),
515
516    /// Represents `#[used]`
517    Used { used_by: UsedBy, span: Span },
518    // tidy-alphabetical-end
519}