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}