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