rustc_hir/attrs/
data_structures.rs

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