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}