rustc_hir/attrs/
data_structures.rs

1use std::borrow::Cow;
2use std::fmt;
3use std::path::PathBuf;
4
5pub use ReprAttr::*;
6use rustc_abi::Align;
7use rustc_ast::token::DocFragmentKind;
8use rustc_ast::{AttrStyle, ast};
9use rustc_data_structures::fx::FxIndexMap;
10use rustc_error_messages::{DiagArgValue, IntoDiagArg};
11use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
12use rustc_span::def_id::DefId;
13use rustc_span::hygiene::Transparency;
14use rustc_span::{Ident, Span, Symbol};
15pub use rustc_target::spec::SanitizerSet;
16use thin_vec::ThinVec;
17
18use crate::attrs::pretty_printing::PrintAttribute;
19use crate::limit::Limit;
20use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability};
21
22#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
23pub struct EiiImpl {
24    pub eii_macro: DefId,
25    pub impl_marked_unsafe: bool,
26    pub span: Span,
27    pub inner_span: Span,
28    pub is_default: bool,
29}
30
31#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
32pub struct EiiDecl {
33    pub eii_extern_target: DefId,
34    /// whether or not it is unsafe to implement this EII
35    pub impl_unsafe: bool,
36    pub span: Span,
37}
38
39#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)]
40pub enum InlineAttr {
41    None,
42    Hint,
43    Always,
44    Never,
45    /// `#[rustc_force_inline]` forces inlining to happen in the MIR inliner - it reports an error
46    /// if the inlining cannot happen. It is limited to only free functions so that the calls
47    /// can always be resolved.
48    Force {
49        attr_span: Span,
50        reason: Option<Symbol>,
51    },
52}
53
54impl InlineAttr {
55    pub fn always(&self) -> bool {
56        match self {
57            InlineAttr::Always | InlineAttr::Force { .. } => true,
58            InlineAttr::None | InlineAttr::Hint | InlineAttr::Never => false,
59        }
60    }
61}
62
63#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)]
64pub enum InstructionSetAttr {
65    ArmA32,
66    ArmT32,
67}
68
69#[derive(Copy, Clone, Debug, PartialEq, Eq, Default, PrintAttribute)]
70#[derive(Encodable, Decodable, HashStable_Generic)]
71pub enum OptimizeAttr {
72    /// No `#[optimize(..)]` attribute
73    #[default]
74    Default,
75    /// `#[optimize(none)]`
76    DoNotOptimize,
77    /// `#[optimize(speed)]`
78    Speed,
79    /// `#[optimize(size)]`
80    Size,
81}
82
83impl OptimizeAttr {
84    pub fn do_not_optimize(&self) -> bool {
85        matches!(self, Self::DoNotOptimize)
86    }
87}
88
89#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, HashStable_Generic, PrintAttribute)]
90pub enum ReprAttr {
91    ReprInt(IntType),
92    ReprRust,
93    ReprC,
94    ReprPacked(Align),
95    ReprSimd,
96    ReprTransparent,
97    ReprAlign(Align),
98}
99
100pub enum TransparencyError {
101    UnknownTransparency(Symbol, Span),
102    MultipleTransparencyAttrs(Span, Span),
103}
104
105#[derive(Eq, PartialEq, Debug, Copy, Clone)]
106#[derive(Encodable, Decodable, HashStable_Generic, PrintAttribute)]
107pub enum IntType {
108    SignedInt(ast::IntTy),
109    UnsignedInt(ast::UintTy),
110}
111
112#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
113pub struct Deprecation {
114    pub since: DeprecatedSince,
115    /// The note to issue a reason.
116    pub note: Option<Symbol>,
117    /// A text snippet used to completely replace any use of the deprecated item in an expression.
118    ///
119    /// This is currently unstable.
120    pub suggestion: Option<Symbol>,
121}
122
123/// Release in which an API is deprecated.
124#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
125pub enum DeprecatedSince {
126    RustcVersion(RustcVersion),
127    /// Deprecated in the future ("to be determined").
128    Future,
129    /// `feature(staged_api)` is off. Deprecation versions outside the standard
130    /// library are allowed to be arbitrary strings, for better or worse.
131    NonStandard(Symbol),
132    /// Deprecation version is unspecified but optional.
133    Unspecified,
134    /// Failed to parse a deprecation version, or the deprecation version is
135    /// unspecified and required. An error has already been emitted.
136    Err,
137}
138
139/// Successfully-parsed value of a `#[coverage(..)]` attribute.
140#[derive(Copy, Debug, Eq, PartialEq, Encodable, Decodable, Clone)]
141#[derive(HashStable_Generic, PrintAttribute)]
142pub enum CoverageAttrKind {
143    On,
144    Off,
145}
146
147impl Deprecation {
148    /// Whether an item marked with #[deprecated(since = "X")] is currently
149    /// deprecated (i.e., whether X is not greater than the current rustc
150    /// version).
151    pub fn is_in_effect(&self) -> bool {
152        match self.since {
153            DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
154            DeprecatedSince::Future => false,
155            // The `since` field doesn't have semantic purpose without `#![staged_api]`.
156            DeprecatedSince::NonStandard(_) => true,
157            // Assume deprecation is in effect if "since" field is absent or invalid.
158            DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
159        }
160    }
161
162    pub fn is_since_rustc_version(&self) -> bool {
163        matches!(self.since, DeprecatedSince::RustcVersion(_))
164    }
165}
166
167/// There are three valid forms of the attribute:
168/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not.
169/// `#[used(compiler)]`
170/// `#[used(linker)]`
171#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
172#[derive(HashStable_Generic, PrintAttribute)]
173pub enum UsedBy {
174    Default,
175    Compiler,
176    Linker,
177}
178
179#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
180#[derive(HashStable_Generic, PrintAttribute)]
181pub enum MacroUseArgs {
182    UseAll,
183    UseSpecific(ThinVec<Ident>),
184}
185
186impl Default for MacroUseArgs {
187    fn default() -> Self {
188        Self::UseSpecific(ThinVec::new())
189    }
190}
191
192#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
193pub struct StrippedCfgItem<ModId = DefId> {
194    pub parent_module: ModId,
195    pub ident: Ident,
196    pub cfg: (CfgEntry, Span),
197}
198
199impl<ModId> StrippedCfgItem<ModId> {
200    pub fn map_mod_id<New>(self, f: impl FnOnce(ModId) -> New) -> StrippedCfgItem<New> {
201        StrippedCfgItem { parent_module: f(self.parent_module), ident: self.ident, cfg: self.cfg }
202    }
203}
204
205#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
206#[derive(HashStable_Generic, PrintAttribute)]
207pub enum CfgEntry {
208    All(ThinVec<CfgEntry>, Span),
209    Any(ThinVec<CfgEntry>, Span),
210    Not(Box<CfgEntry>, Span),
211    Bool(bool, Span),
212    NameValue { name: Symbol, value: Option<Symbol>, span: Span },
213    Version(Option<RustcVersion>, Span),
214}
215
216impl CfgEntry {
217    pub fn span(&self) -> Span {
218        let (Self::All(_, span)
219        | Self::Any(_, span)
220        | Self::Not(_, span)
221        | Self::Bool(_, span)
222        | Self::NameValue { span, .. }
223        | Self::Version(_, span)) = self;
224        *span
225    }
226
227    /// Same as `PartialEq` but doesn't check spans and ignore order of cfgs.
228    pub fn is_equivalent_to(&self, other: &Self) -> bool {
229        match (self, other) {
230            (Self::All(a, _), Self::All(b, _)) | (Self::Any(a, _), Self::Any(b, _)) => {
231                a.len() == b.len() && a.iter().all(|a| b.iter().any(|b| a.is_equivalent_to(b)))
232            }
233            (Self::Not(a, _), Self::Not(b, _)) => a.is_equivalent_to(b),
234            (Self::Bool(a, _), Self::Bool(b, _)) => a == b,
235            (
236                Self::NameValue { name: name1, value: value1, .. },
237                Self::NameValue { name: name2, value: value2, .. },
238            ) => name1 == name2 && value1 == value2,
239            (Self::Version(a, _), Self::Version(b, _)) => a == b,
240            _ => false,
241        }
242    }
243}
244
245impl fmt::Display for CfgEntry {
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247        fn write_entries(
248            name: &str,
249            entries: &[CfgEntry],
250            f: &mut fmt::Formatter<'_>,
251        ) -> fmt::Result {
252            write!(f, "{name}(")?;
253            for (nb, entry) in entries.iter().enumerate() {
254                if nb != 0 {
255                    f.write_str(", ")?;
256                }
257                entry.fmt(f)?;
258            }
259            f.write_str(")")
260        }
261        match self {
262            Self::All(entries, _) => write_entries("all", entries, f),
263            Self::Any(entries, _) => write_entries("any", entries, f),
264            Self::Not(entry, _) => write!(f, "not({entry})"),
265            Self::Bool(value, _) => write!(f, "{value}"),
266            Self::NameValue { name, value, .. } => {
267                match value {
268                    // We use `as_str` and debug display to have characters escaped and `"`
269                    // characters surrounding the string.
270                    Some(value) => write!(f, "{name} = {:?}", value.as_str()),
271                    None => write!(f, "{name}"),
272                }
273            }
274            Self::Version(version, _) => match version {
275                Some(version) => write!(f, "{version}"),
276                None => Ok(()),
277            },
278        }
279    }
280}
281
282/// Possible values for the `#[linkage]` attribute, allowing to specify the
283/// linkage type for a `MonoItem`.
284///
285/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
286#[derive(Encodable, Decodable, Clone, Copy, Debug, PartialEq, Eq, Hash)]
287#[derive(HashStable_Generic, PrintAttribute)]
288pub enum Linkage {
289    AvailableExternally,
290    Common,
291    ExternalWeak,
292    External,
293    Internal,
294    LinkOnceAny,
295    LinkOnceODR,
296    WeakAny,
297    WeakODR,
298}
299
300#[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
301#[derive(HashStable_Generic, PrintAttribute)]
302pub enum MirDialect {
303    Analysis,
304    Built,
305    Runtime,
306}
307
308impl IntoDiagArg for MirDialect {
309    fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
310        let arg = match self {
311            MirDialect::Analysis => "analysis",
312            MirDialect::Built => "built",
313            MirDialect::Runtime => "runtime",
314        };
315        DiagArgValue::Str(Cow::Borrowed(arg))
316    }
317}
318
319#[derive(Clone, Copy, Decodable, Debug, Encodable, PartialEq)]
320#[derive(HashStable_Generic, PrintAttribute)]
321pub enum MirPhase {
322    Initial,
323    PostCleanup,
324    Optimized,
325}
326
327impl IntoDiagArg for MirPhase {
328    fn into_diag_arg(self, _path: &mut Option<PathBuf>) -> DiagArgValue {
329        let arg = match self {
330            MirPhase::Initial => "initial",
331            MirPhase::PostCleanup => "post-cleanup",
332            MirPhase::Optimized => "optimized",
333        };
334        DiagArgValue::Str(Cow::Borrowed(arg))
335    }
336}
337
338/// Different ways that the PE Format can decorate a symbol name.
339/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
340#[derive(
341    Copy,
342    Clone,
343    Debug,
344    Encodable,
345    Decodable,
346    HashStable_Generic,
347    PartialEq,
348    Eq,
349    PrintAttribute
350)]
351pub enum PeImportNameType {
352    /// IMPORT_ORDINAL
353    /// Uses the ordinal (i.e., a number) rather than the name.
354    Ordinal(u16),
355    /// Same as IMPORT_NAME
356    /// Name is decorated with all prefixes and suffixes.
357    Decorated,
358    /// Same as IMPORT_NAME_NOPREFIX
359    /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
360    NoPrefix,
361    /// Same as IMPORT_NAME_UNDECORATE
362    /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
363    /// trailing characters) are skipped.
364    Undecorated,
365}
366
367#[derive(
368    Copy,
369    Clone,
370    Debug,
371    PartialEq,
372    Eq,
373    PartialOrd,
374    Ord,
375    Hash,
376    Encodable,
377    Decodable,
378    PrintAttribute
379)]
380#[derive(HashStable_Generic)]
381pub enum NativeLibKind {
382    /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
383    Static {
384        /// Whether to bundle objects from static library into produced rlib
385        bundle: Option<bool>,
386        /// Whether to link static library without throwing any object files away
387        whole_archive: Option<bool>,
388    },
389    /// Dynamic library (e.g. `libfoo.so` on Linux)
390    /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
391    Dylib {
392        /// Whether the dynamic library will be linked only if it satisfies some undefined symbols
393        as_needed: Option<bool>,
394    },
395    /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
396    /// On Linux, it refers to a generated shared library stub.
397    RawDylib {
398        /// Whether the dynamic library will be linked only if it satisfies some undefined symbols
399        as_needed: Option<bool>,
400    },
401    /// A macOS-specific kind of dynamic libraries.
402    Framework {
403        /// Whether the framework will be linked only if it satisfies some undefined symbols
404        as_needed: Option<bool>,
405    },
406    /// Argument which is passed to linker, relative order with libraries and other arguments
407    /// is preserved
408    LinkArg,
409
410    /// Module imported from WebAssembly
411    WasmImportModule,
412
413    /// The library kind wasn't specified, `Dylib` is currently used as a default.
414    Unspecified,
415}
416
417impl NativeLibKind {
418    pub fn has_modifiers(&self) -> bool {
419        match self {
420            NativeLibKind::Static { bundle, whole_archive } => {
421                bundle.is_some() || whole_archive.is_some()
422            }
423            NativeLibKind::Dylib { as_needed }
424            | NativeLibKind::Framework { as_needed }
425            | NativeLibKind::RawDylib { as_needed } => as_needed.is_some(),
426            NativeLibKind::Unspecified
427            | NativeLibKind::LinkArg
428            | NativeLibKind::WasmImportModule => false,
429        }
430    }
431
432    pub fn is_statically_included(&self) -> bool {
433        matches!(self, NativeLibKind::Static { .. })
434    }
435
436    pub fn is_dllimport(&self) -> bool {
437        matches!(
438            self,
439            NativeLibKind::Dylib { .. }
440                | NativeLibKind::RawDylib { .. }
441                | NativeLibKind::Unspecified
442        )
443    }
444}
445
446#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
447pub struct LinkEntry {
448    pub span: Span,
449    pub kind: NativeLibKind,
450    pub name: Symbol,
451    pub cfg: Option<CfgEntry>,
452    pub verbatim: Option<bool>,
453    pub import_name_type: Option<(PeImportNameType, Span)>,
454}
455
456#[derive(HashStable_Generic, PrintAttribute)]
457#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
458pub enum DebuggerVisualizerType {
459    Natvis,
460    GdbPrettyPrinter,
461}
462
463#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
464pub struct DebugVisualizer {
465    pub span: Span,
466    pub visualizer_type: DebuggerVisualizerType,
467    pub path: Symbol,
468}
469
470#[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)]
471#[derive(HashStable_Generic, PrintAttribute)]
472#[derive_const(Default)]
473pub enum RtsanSetting {
474    Nonblocking,
475    Blocking,
476    #[default]
477    Caller,
478}
479
480#[derive(Eq, PartialEq, Debug, Copy, Clone)]
481#[derive(Encodable, Decodable, HashStable_Generic, PrintAttribute)]
482pub enum WindowsSubsystemKind {
483    Console,
484    Windows,
485}
486
487impl WindowsSubsystemKind {
488    pub fn as_str(&self) -> &'static str {
489        match self {
490            WindowsSubsystemKind::Console => "console",
491            WindowsSubsystemKind::Windows => "windows",
492        }
493    }
494}
495
496#[derive(Copy, Clone, Debug, PartialEq)]
497#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)]
498pub enum DocInline {
499    Inline,
500    NoInline,
501}
502
503#[derive(Copy, Clone, Debug, PartialEq)]
504#[derive(HashStable_Generic, Encodable, Decodable, PrintAttribute)]
505pub enum HideOrShow {
506    Hide,
507    Show,
508}
509
510#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
511pub struct CfgInfo {
512    pub name: Symbol,
513    pub name_span: Span,
514    pub value: Option<(Symbol, Span)>,
515}
516
517impl CfgInfo {
518    pub fn span_for_name_and_value(&self) -> Span {
519        if let Some((_, value_span)) = self.value {
520            self.name_span.with_hi(value_span.hi())
521        } else {
522            self.name_span
523        }
524    }
525}
526
527#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
528pub struct CfgHideShow {
529    pub kind: HideOrShow,
530    pub values: ThinVec<CfgInfo>,
531}
532
533#[derive(Clone, Debug, Default, HashStable_Generic, Decodable, PrintAttribute)]
534pub struct DocAttribute {
535    pub aliases: FxIndexMap<Symbol, Span>,
536    pub hidden: Option<Span>,
537    // Because we need to emit the error if there is more than one `inline` attribute on an item
538    // at the same time as the other doc attributes, we store a list instead of using `Option`.
539    pub inline: ThinVec<(DocInline, Span)>,
540
541    // unstable
542    pub cfg: ThinVec<CfgEntry>,
543    pub auto_cfg: ThinVec<(CfgHideShow, Span)>,
544    /// This is for `#[doc(auto_cfg = false|true)]`/`#[doc(auto_cfg)]`.
545    pub auto_cfg_change: ThinVec<(bool, Span)>,
546
547    // builtin
548    pub fake_variadic: Option<Span>,
549    pub keyword: Option<(Symbol, Span)>,
550    pub attribute: Option<(Symbol, Span)>,
551    pub masked: Option<Span>,
552    pub notable_trait: Option<Span>,
553    pub search_unbox: Option<Span>,
554
555    // valid on crate
556    pub html_favicon_url: Option<(Symbol, Span)>,
557    pub html_logo_url: Option<(Symbol, Span)>,
558    pub html_playground_url: Option<(Symbol, Span)>,
559    pub html_root_url: Option<(Symbol, Span)>,
560    pub html_no_source: Option<Span>,
561    pub issue_tracker_base_url: Option<(Symbol, Span)>,
562    pub rust_logo: Option<Span>,
563
564    // #[doc(test(...))]
565    pub test_attrs: ThinVec<Span>,
566    pub no_crate_inject: Option<Span>,
567}
568
569impl<E: rustc_span::SpanEncoder> rustc_serialize::Encodable<E> for DocAttribute {
570    fn encode(&self, encoder: &mut E) {
571        let DocAttribute {
572            aliases,
573            hidden,
574            inline,
575            cfg,
576            auto_cfg,
577            auto_cfg_change,
578            fake_variadic,
579            keyword,
580            attribute,
581            masked,
582            notable_trait,
583            search_unbox,
584            html_favicon_url,
585            html_logo_url,
586            html_playground_url,
587            html_root_url,
588            html_no_source,
589            issue_tracker_base_url,
590            rust_logo,
591            test_attrs,
592            no_crate_inject,
593        } = self;
594        rustc_serialize::Encodable::<E>::encode(aliases, encoder);
595        rustc_serialize::Encodable::<E>::encode(hidden, encoder);
596
597        // FIXME: The `doc(inline)` attribute is never encoded, but is it actually the right thing
598        // to do? I suspect the condition was broken, should maybe instead not encode anything if we
599        // have `doc(no_inline)`.
600        let inline: ThinVec<_> =
601            inline.iter().filter(|(i, _)| *i != DocInline::Inline).cloned().collect();
602        rustc_serialize::Encodable::<E>::encode(&inline, encoder);
603
604        rustc_serialize::Encodable::<E>::encode(cfg, encoder);
605        rustc_serialize::Encodable::<E>::encode(auto_cfg, encoder);
606        rustc_serialize::Encodable::<E>::encode(auto_cfg_change, encoder);
607        rustc_serialize::Encodable::<E>::encode(fake_variadic, encoder);
608        rustc_serialize::Encodable::<E>::encode(keyword, encoder);
609        rustc_serialize::Encodable::<E>::encode(attribute, encoder);
610        rustc_serialize::Encodable::<E>::encode(masked, encoder);
611        rustc_serialize::Encodable::<E>::encode(notable_trait, encoder);
612        rustc_serialize::Encodable::<E>::encode(search_unbox, encoder);
613        rustc_serialize::Encodable::<E>::encode(html_favicon_url, encoder);
614        rustc_serialize::Encodable::<E>::encode(html_logo_url, encoder);
615        rustc_serialize::Encodable::<E>::encode(html_playground_url, encoder);
616        rustc_serialize::Encodable::<E>::encode(html_root_url, encoder);
617        rustc_serialize::Encodable::<E>::encode(html_no_source, encoder);
618        rustc_serialize::Encodable::<E>::encode(issue_tracker_base_url, encoder);
619        rustc_serialize::Encodable::<E>::encode(rust_logo, encoder);
620        rustc_serialize::Encodable::<E>::encode(test_attrs, encoder);
621        rustc_serialize::Encodable::<E>::encode(no_crate_inject, encoder);
622    }
623}
624
625/// Represents parsed *built-in* inert attributes.
626///
627/// ## Overview
628/// These attributes are markers that guide the compilation process and are never expanded into other code.
629/// They persist throughout the compilation phases, from AST to HIR and beyond.
630///
631/// ## Attribute Processing
632/// While attributes are initially parsed by [`rustc_parse`] into [`ast::Attribute`], they still contain raw token streams
633/// because different attributes have different internal structures. This enum represents the final,
634/// fully parsed form of these attributes, where each variant contains all the information and
635/// structure relevant for the specific attribute.
636///
637/// Some attributes can be applied multiple times to the same item, and they are "collapsed" into a single
638/// semantic attribute. For example:
639/// ```rust
640/// #[repr(C)]
641/// #[repr(packed)]
642/// struct S { }
643/// ```
644/// This is equivalent to `#[repr(C, packed)]` and results in a single [`AttributeKind::Repr`] containing
645/// both `C` and `packed` annotations. This collapsing happens during parsing and is reflected in the
646/// data structures defined in this enum.
647///
648/// ## Usage
649/// These parsed attributes are used throughout the compiler to:
650/// - Control code generation (e.g., `#[repr]`)
651/// - Mark API stability (`#[stable]`, `#[unstable]`)
652/// - Provide documentation (`#[doc]`)
653/// - Guide compiler behavior (e.g., `#[allow_internal_unstable]`)
654///
655/// ## Note on Attribute Organization
656/// Some attributes like `InlineAttr`, `OptimizeAttr`, and `InstructionSetAttr` are defined separately
657/// from this enum because they are used in specific compiler phases (like code generation) and don't
658/// need to persist throughout the entire compilation process. They are typically processed and
659/// converted into their final form earlier in the compilation pipeline.
660///
661/// For example:
662/// - `InlineAttr` is used during code generation to control function inlining
663/// - `OptimizeAttr` is used to control optimization levels
664/// - `InstructionSetAttr` is used for target-specific code generation
665///
666/// These attributes are handled by their respective compiler passes in the [`rustc_codegen_ssa`] crate
667/// and don't need to be preserved in the same way as the attributes in this enum.
668///
669/// For more details on attribute parsing, see the [`rustc_attr_parsing`] crate.
670///
671/// [`rustc_parse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/index.html
672/// [`rustc_codegen_ssa`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/index.html
673/// [`rustc_attr_parsing`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/index.html
674#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
675pub enum AttributeKind {
676    // tidy-alphabetical-start
677    /// Represents `#[align(N)]`.
678    // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
679    Align { align: Align, span: Span },
680
681    /// Represents `#[rustc_allow_const_fn_unstable]`.
682    AllowConstFnUnstable(ThinVec<Symbol>, Span),
683
684    /// Represents `#[rustc_allow_incoherent_impl]`.
685    AllowIncoherentImpl(Span),
686
687    /// Represents `#[allow_internal_unsafe]`.
688    AllowInternalUnsafe(Span),
689
690    /// Represents `#[allow_internal_unstable]`.
691    AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
692
693    /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint).
694    AsPtr(Span),
695
696    /// Represents `#[automatically_derived]`
697    AutomaticallyDerived(Span),
698
699    /// Represents `#[rustc_default_body_unstable]`.
700    BodyStability {
701        stability: DefaultBodyStability,
702        /// Span of the `#[rustc_default_body_unstable(...)]` attribute
703        span: Span,
704    },
705
706    /// Represents `#[cfi_encoding]`
707    CfiEncoding { encoding: Symbol },
708
709    /// Represents `#[rustc_coinductive]`.
710    Coinductive(Span),
711
712    /// Represents `#[cold]`.
713    Cold(Span),
714
715    /// Represents `#[rustc_confusables]`.
716    Confusables {
717        symbols: ThinVec<Symbol>,
718        // FIXME(jdonszelmann): remove when target validation code is moved
719        first_span: Span,
720    },
721
722    /// Represents `#[const_continue]`.
723    ConstContinue(Span),
724
725    /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`.
726    ConstStability {
727        stability: PartialConstStability,
728        /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute
729        span: Span,
730    },
731
732    /// Represents `#[rustc_const_stable_indirect]`.
733    ConstStabilityIndirect,
734
735    /// Represents `#[coroutine]`.
736    Coroutine(Span),
737
738    /// Represents `#[coverage(..)]`.
739    Coverage(Span, CoverageAttrKind),
740
741    /// Represents `#[crate_name = ...]`
742    CrateName { name: Symbol, name_span: Span, attr_span: Span },
743
744    /// Represents `#[custom_mir]`.
745    CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
746
747    /// Represents `#[debugger_visualizer]`.
748    DebuggerVisualizer(ThinVec<DebugVisualizer>),
749
750    /// Represents `#[rustc_deny_explicit_impl]`.
751    DenyExplicitImpl(Span),
752
753    /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
754    Deprecation { deprecation: Deprecation, span: Span },
755
756    /// Represents `#[rustc_do_not_implement_via_object]`.
757    DoNotImplementViaObject(Span),
758
759    /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
760    /// Represents all other uses of the [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html)
761    /// attribute.
762    Doc(Box<DocAttribute>),
763
764    /// Represents specifically [`#[doc = "..."]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
765    /// i.e. doc comments.
766    DocComment { style: AttrStyle, kind: DocFragmentKind, span: Span, comment: Symbol },
767
768    /// Represents `#[rustc_dummy]`.
769    Dummy,
770
771    /// Implementation detail of `#[eii]`
772    EiiExternItem,
773
774    /// Implementation detail of `#[eii]`
775    EiiExternTarget(EiiDecl),
776
777    /// Implementation detail of `#[eii]`
778    EiiImpls(ThinVec<EiiImpl>),
779
780    /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
781    ExportName {
782        /// The name to export this item with.
783        /// It may not contain \0 bytes as it will be converted to a null-terminated string.
784        name: Symbol,
785        span: Span,
786    },
787
788    /// Represents `#[export_stable]`.
789    ExportStable,
790
791    /// Represents `#[ffi_const]`.
792    FfiConst(Span),
793
794    /// Represents `#[ffi_pure]`.
795    FfiPure(Span),
796
797    /// Represents `#[fundamental]`.
798    Fundamental,
799
800    /// Represents `#[ignore]`
801    Ignore {
802        span: Span,
803        /// ignore can optionally have a reason: `#[ignore = "reason this is ignored"]`
804        reason: Option<Symbol>,
805    },
806
807    /// Represents `#[inline]` and `#[rustc_force_inline]`.
808    Inline(InlineAttr, Span),
809
810    /// Represents `#[link]`.
811    Link(ThinVec<LinkEntry>, Span),
812
813    /// Represents `#[link_name]`.
814    LinkName { name: Symbol, span: Span },
815
816    /// Represents `#[link_ordinal]`.
817    LinkOrdinal { ordinal: u16, span: Span },
818
819    /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
820    LinkSection { name: Symbol, span: Span },
821
822    /// Represents `#[linkage]`.
823    Linkage(Linkage, Span),
824
825    /// Represents `#[loop_match]`.
826    LoopMatch(Span),
827
828    /// Represents `#[macro_escape]`.
829    MacroEscape(Span),
830
831    /// Represents [`#[macro_export]`](https://doc.rust-lang.org/reference/macros-by-example.html#r-macro.decl.scope.path).
832    MacroExport { span: Span, local_inner_macros: bool },
833
834    /// Represents `#[rustc_macro_transparency]`.
835    MacroTransparency(Transparency),
836
837    /// Represents `#[macro_use]`.
838    MacroUse { span: Span, arguments: MacroUseArgs },
839
840    /// Represents `#[marker]`.
841    Marker(Span),
842
843    /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
844    MayDangle(Span),
845
846    /// Represents `#[move_size_limit]`
847    MoveSizeLimit { attr_span: Span, limit_span: Span, limit: Limit },
848
849    /// Represents `#[must_use]`.
850    MustUse {
851        span: Span,
852        /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]`
853        reason: Option<Symbol>,
854    },
855
856    /// Represents `#[naked]`
857    Naked(Span),
858
859    /// Represents `#[no_core]`
860    NoCore(Span),
861
862    /// Represents `#[no_implicit_prelude]`
863    NoImplicitPrelude(Span),
864
865    /// Represents `#[no_link]`
866    NoLink,
867
868    /// Represents `#[no_mangle]`
869    NoMangle(Span),
870
871    /// Represents `#[no_std]`
872    NoStd(Span),
873
874    /// Represents `#[non_exhaustive]`
875    NonExhaustive(Span),
876
877    /// Represents `#[rustc_objc_class]`
878    ObjcClass { classname: Symbol, span: Span },
879
880    /// Represents `#[rustc_objc_selector]`
881    ObjcSelector { methname: Symbol, span: Span },
882
883    /// Represents `#[optimize(size|speed)]`
884    Optimize(OptimizeAttr, Span),
885
886    /// Represents `#[rustc_paren_sugar]`.
887    ParenSugar(Span),
888
889    /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
890    PassByValue(Span),
891
892    /// Represents `#[path]`
893    Path(Symbol, Span),
894
895    /// Represents `#[pattern_complexity_limit]`
896    PatternComplexityLimit { attr_span: Span, limit_span: Span, limit: Limit },
897
898    /// Represents `#[pin_v2]`
899    PinV2(Span),
900
901    /// Represents `#[pointee]`
902    Pointee(Span),
903
904    /// Represents `#[proc_macro]`
905    ProcMacro(Span),
906
907    /// Represents `#[proc_macro_attribute]`
908    ProcMacroAttribute(Span),
909
910    /// Represents `#[proc_macro_derive]`
911    ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span },
912
913    /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
914    PubTransparent(Span),
915
916    /// Represents [`#[recursion_limit]`](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute)
917    RecursionLimit { attr_span: Span, limit_span: Span, limit: Limit },
918
919    /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
920    Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
921
922    /// Represents `#[rustc_builtin_macro]`.
923    RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
924
925    /// Represents `#[rustc_coherence_is_core]`
926    RustcCoherenceIsCore(Span),
927
928    /// Represents `#[rustc_layout_scalar_valid_range_end]`.
929    RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
930
931    /// Represents `#[rustc_layout_scalar_valid_range_start]`.
932    RustcLayoutScalarValidRangeStart(Box<u128>, Span),
933
934    /// Represents `#[rustc_legacy_const_generics]`
935    RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span },
936
937    /// Represents `#[rustc_lint_diagnostics]`
938    RustcLintDiagnostics,
939
940    /// Represents `#[rustc_lint_opt_deny_field_access]`
941    RustcLintOptDenyFieldAccess { lint_message: Symbol },
942
943    /// Represents `#[rustc_lint_opt_ty]`
944    RustcLintOptTy,
945
946    /// Represents `#[rustc_lint_query_instability]`
947    RustcLintQueryInstability,
948
949    /// Represents `#[rustc_lint_untracked_query_information]`
950    RustcLintUntrackedQueryInformation,
951
952    /// Represents `#[rustc_main]`.
953    RustcMain,
954
955    /// Represents `#[rustc_never_returns_null_ptr]`
956    RustcNeverReturnsNullPointer,
957
958    /// Represents `#[rustc_no_implicit_autorefs]`
959    RustcNoImplicitAutorefs,
960
961    /// Represents `#[rustc_object_lifetime_default]`.
962    RustcObjectLifetimeDefault,
963
964    /// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]`
965    RustcPassIndirectlyInNonRusticAbis(Span),
966
967    /// Represents `#[rustc_scalable_vector(N)]`
968    RustcScalableVector {
969        /// The base multiple of lanes that are in a scalable vector, if provided. `element_count`
970        /// is not provided for representing tuple types.
971        element_count: Option<u16>,
972        span: Span,
973    },
974
975    /// Represents `#[rustc_should_not_be_called_on_const_items]`
976    RustcShouldNotBeCalledOnConstItems(Span),
977
978    /// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`.
979    RustcSimdMonomorphizeLaneLimit(Limit),
980
981    /// Represents `#[sanitize]`
982    ///
983    /// the on set and off set are distjoint since there's a third option: unset.
984    /// a node may not set the sanitizer setting in which case it inherits from parents.
985    /// rtsan is unset if None
986    Sanitize {
987        on_set: SanitizerSet,
988        off_set: SanitizerSet,
989        rtsan: Option<RtsanSetting>,
990        span: Span,
991    },
992
993    /// Represents `#[should_panic]`
994    ShouldPanic { reason: Option<Symbol>, span: Span },
995
996    /// Represents `#[rustc_skip_during_method_dispatch]`.
997    SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
998
999    /// Represents `#[rustc_specialization_trait]`.
1000    SpecializationTrait(Span),
1001
1002    /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
1003    Stability {
1004        stability: Stability,
1005        /// Span of the attribute.
1006        span: Span,
1007    },
1008
1009    /// Represents `#[rustc_std_internal_symbol]`.
1010    StdInternalSymbol(Span),
1011
1012    /// Represents `#[target_feature(enable = "...")]` and
1013    /// `#[unsafe(force_target_feature(enable = "...")]`.
1014    TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool },
1015
1016    /// Represents `#[thread_local]`
1017    ThreadLocal,
1018
1019    /// Represents `#[track_caller]`
1020    TrackCaller(Span),
1021
1022    /// Represents `#[type_const]`.
1023    TypeConst(Span),
1024
1025    /// Represents `#[type_length_limit]`
1026    TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit },
1027
1028    /// Represents `#[rustc_unsafe_specialization_marker]`.
1029    UnsafeSpecializationMarker(Span),
1030
1031    /// Represents `#[unstable_feature_bound]`.
1032    UnstableFeatureBound(ThinVec<(Symbol, Span)>),
1033
1034    /// Represents `#[used]`
1035    Used { used_by: UsedBy, span: Span },
1036
1037    /// Represents `#[windows_subsystem]`.
1038    WindowsSubsystem(WindowsSubsystemKind, Span),
1039    // tidy-alphabetical-end
1040}