1use std::cell::RefCell;
2use std::collections::BTreeMap;
3use std::ops::{Deref, DerefMut};
4use std::sync::LazyLock;
5
6use private::Sealed;
7use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
8use rustc_errors::{Diag, Diagnostic, Level};
9use rustc_feature::{AttributeTemplate, AttributeType};
10use rustc_hir::attrs::AttributeKind;
11use rustc_hir::lints::{AttributeLint, AttributeLintKind};
12use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
13use rustc_session::Session;
14use rustc_span::{ErrorGuaranteed, Span, Symbol};
15
16use crate::AttributeParser;
17use crate::attributes::allow_unstable::{
18 AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
19};
20use crate::attributes::body::CoroutineParser;
21use crate::attributes::codegen_attrs::{
22 ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
23 NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
24 UsedParser,
25};
26use crate::attributes::confusables::ConfusablesParser;
27use crate::attributes::crate_level::{
28 CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
29 RecursionLimitParser, TypeLengthLimitParser,
30};
31use crate::attributes::deprecation::DeprecationParser;
32use crate::attributes::dummy::DummyParser;
33use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
34use crate::attributes::link_attrs::{
35 ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
36 LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
37};
38use crate::attributes::lint_helpers::{
39 AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
40};
41use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
42use crate::attributes::macro_attrs::{
43 AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
44};
45use crate::attributes::must_use::MustUseParser;
46use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
47use crate::attributes::non_exhaustive::NonExhaustiveParser;
48use crate::attributes::path::PathParser as PathAttributeParser;
49use crate::attributes::proc_macro_attrs::{
50 ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
51};
52use crate::attributes::prototype::CustomMirParser;
53use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
54use crate::attributes::rustc_internal::{
55 RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
56 RustcObjectLifetimeDefaultParser,
57};
58use crate::attributes::semantics::MayDangleParser;
59use crate::attributes::stability::{
60 BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
61};
62use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
63use crate::attributes::traits::{
64 AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
65 DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
66 ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
67 TypeConstParser, UnsafeSpecializationMarkerParser,
68};
69use crate::attributes::transparency::TransparencyParser;
70use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
71use crate::parser::{ArgParser, PathParser};
72use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
73use crate::target_checking::AllowedTargets;
74
75type GroupType<S> = LazyLock<GroupTypeInner<S>>;
76
77pub(super) struct GroupTypeInner<S: Stage> {
78 pub(super) accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
79 pub(super) finalizers: Vec<FinalizeFn<S>>,
80}
81
82pub(super) struct GroupTypeInnerAccept<S: Stage> {
83 pub(super) template: AttributeTemplate,
84 pub(super) accept_fn: AcceptFn<S>,
85 pub(super) allowed_targets: AllowedTargets,
86 pub(super) attribute_type: AttributeType,
87}
88
89type AcceptFn<S> =
90 Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
91type FinalizeFn<S> =
92 Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
93
94macro_rules! attribute_parsers {
95 (
96 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
97 ) => {
98 mod early {
99 use super::*;
100 type Combine<T> = super::Combine<T, Early>;
101 type Single<T> = super::Single<T, Early>;
102 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
103
104 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
105 }
106 mod late {
107 use super::*;
108 type Combine<T> = super::Combine<T, Late>;
109 type Single<T> = super::Single<T, Late>;
110 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
111
112 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
113 }
114 };
115 (
116 @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
117 ) => {
118 pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
119 let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
120 let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
121 $(
122 {
123 thread_local! {
124 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
125 };
126
127 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
128 accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
129 template: *template,
130 accept_fn: Box::new(|cx, args| {
131 STATE_OBJECT.with_borrow_mut(|s| {
132 accept_fn(s, cx, args)
133 })
134 }),
135 allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
136 attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
137 });
138 }
139
140 finalizes.push(Box::new(|cx| {
141 let state = STATE_OBJECT.take();
142 state.finalize(cx)
143 }));
144 }
145 )*
146
147 GroupTypeInner { accepters:accepts, finalizers:finalizes }
148 });
149 };
150}
151attribute_parsers!(
152 pub(crate) static ATTRIBUTE_PARSERS = [
153 AlignParser,
155 AlignStaticParser,
156 BodyStabilityParser,
157 ConfusablesParser,
158 ConstStabilityParser,
159 MacroUseParser,
160 NakedParser,
161 StabilityParser,
162 UsedParser,
163 Combine<AllowConstFnUnstableParser>,
167 Combine<AllowInternalUnstableParser>,
168 Combine<ForceTargetFeatureParser>,
169 Combine<LinkParser>,
170 Combine<ReprParser>,
171 Combine<TargetFeatureParser>,
172 Combine<UnstableFeatureBoundParser>,
173 Single<CoverageParser>,
177 Single<CrateNameParser>,
178 Single<CustomMirParser>,
179 Single<DeprecationParser>,
180 Single<DummyParser>,
181 Single<ExportNameParser>,
182 Single<IgnoreParser>,
183 Single<InlineParser>,
184 Single<LinkNameParser>,
185 Single<LinkOrdinalParser>,
186 Single<LinkSectionParser>,
187 Single<LinkageParser>,
188 Single<MoveSizeLimitParser>,
189 Single<MustUseParser>,
190 Single<OptimizeParser>,
191 Single<PathAttributeParser>,
192 Single<PatternComplexityLimitParser>,
193 Single<ProcMacroDeriveParser>,
194 Single<RecursionLimitParser>,
195 Single<RustcBuiltinMacroParser>,
196 Single<RustcForceInlineParser>,
197 Single<RustcLayoutScalarValidRangeEnd>,
198 Single<RustcLayoutScalarValidRangeStart>,
199 Single<RustcObjectLifetimeDefaultParser>,
200 Single<SanitizeParser>,
201 Single<ShouldPanicParser>,
202 Single<SkipDuringMethodDispatchParser>,
203 Single<TransparencyParser>,
204 Single<TypeLengthLimitParser>,
205 Single<WithoutArgs<AllowIncoherentImplParser>>,
206 Single<WithoutArgs<AllowInternalUnsafeParser>>,
207 Single<WithoutArgs<AsPtrParser>>,
208 Single<WithoutArgs<AutomaticallyDerivedParser>>,
209 Single<WithoutArgs<CoherenceIsCoreParser>>,
210 Single<WithoutArgs<CoinductiveParser>>,
211 Single<WithoutArgs<ColdParser>>,
212 Single<WithoutArgs<ConstContinueParser>>,
213 Single<WithoutArgs<ConstStabilityIndirectParser>>,
214 Single<WithoutArgs<ConstTraitParser>>,
215 Single<WithoutArgs<CoroutineParser>>,
216 Single<WithoutArgs<DenyExplicitImplParser>>,
217 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
218 Single<WithoutArgs<ExportStableParser>>,
219 Single<WithoutArgs<FfiConstParser>>,
220 Single<WithoutArgs<FfiPureParser>>,
221 Single<WithoutArgs<FundamentalParser>>,
222 Single<WithoutArgs<LoopMatchParser>>,
223 Single<WithoutArgs<MacroEscapeParser>>,
224 Single<WithoutArgs<MarkerParser>>,
225 Single<WithoutArgs<MayDangleParser>>,
226 Single<WithoutArgs<NoCoreParser>>,
227 Single<WithoutArgs<NoImplicitPreludeParser>>,
228 Single<WithoutArgs<NoMangleParser>>,
229 Single<WithoutArgs<NoStdParser>>,
230 Single<WithoutArgs<NonExhaustiveParser>>,
231 Single<WithoutArgs<ParenSugarParser>>,
232 Single<WithoutArgs<PassByValueParser>>,
233 Single<WithoutArgs<PointeeParser>>,
234 Single<WithoutArgs<ProcMacroAttributeParser>>,
235 Single<WithoutArgs<ProcMacroParser>>,
236 Single<WithoutArgs<PubTransparentParser>>,
237 Single<WithoutArgs<SpecializationTraitParser>>,
238 Single<WithoutArgs<StdInternalSymbolParser>>,
239 Single<WithoutArgs<TrackCallerParser>>,
240 Single<WithoutArgs<TypeConstParser>>,
241 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
242 ];
244);
245
246mod private {
247 pub trait Sealed {}
248 impl Sealed for super::Early {}
249 impl Sealed for super::Late {}
250}
251
252#[allow(private_interfaces)]
254pub trait Stage: Sized + 'static + Sealed {
255 type Id: Copy;
256
257 fn parsers() -> &'static GroupType<Self>;
258
259 fn emit_err<'sess>(
260 &self,
261 sess: &'sess Session,
262 diag: impl for<'x> Diagnostic<'x>,
263 ) -> ErrorGuaranteed;
264
265 fn should_emit(&self) -> ShouldEmit;
266
267 fn id_is_crate_root(id: Self::Id) -> bool;
268}
269
270#[allow(private_interfaces)]
272impl Stage for Early {
273 type Id = NodeId;
274
275 fn parsers() -> &'static GroupType<Self> {
276 &early::ATTRIBUTE_PARSERS
277 }
278 fn emit_err<'sess>(
279 &self,
280 sess: &'sess Session,
281 diag: impl for<'x> Diagnostic<'x>,
282 ) -> ErrorGuaranteed {
283 self.should_emit().emit_err(sess.dcx().create_err(diag))
284 }
285
286 fn should_emit(&self) -> ShouldEmit {
287 self.emit_errors
288 }
289
290 fn id_is_crate_root(id: Self::Id) -> bool {
291 id == CRATE_NODE_ID
292 }
293}
294
295#[allow(private_interfaces)]
297impl Stage for Late {
298 type Id = HirId;
299
300 fn parsers() -> &'static GroupType<Self> {
301 &late::ATTRIBUTE_PARSERS
302 }
303 fn emit_err<'sess>(
304 &self,
305 tcx: &'sess Session,
306 diag: impl for<'x> Diagnostic<'x>,
307 ) -> ErrorGuaranteed {
308 tcx.dcx().emit_err(diag)
309 }
310
311 fn should_emit(&self) -> ShouldEmit {
312 ShouldEmit::ErrorsAndLints
313 }
314
315 fn id_is_crate_root(id: Self::Id) -> bool {
316 id == CRATE_HIR_ID
317 }
318}
319
320pub struct Early {
322 pub emit_errors: ShouldEmit,
326}
327pub struct Late;
329
330pub struct AcceptContext<'f, 'sess, S: Stage> {
334 pub(crate) shared: SharedContext<'f, 'sess, S>,
335 pub(crate) attr_span: Span,
337
338 pub(crate) attr_style: AttrStyle,
340
341 pub(crate) template: &'f AttributeTemplate,
345
346 pub(crate) attr_path: AttrPath,
348}
349
350impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
351 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
352 self.stage.emit_err(&self.sess, diag)
353 }
354
355 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
359 if !matches!(
360 self.stage.should_emit(),
361 ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
362 ) {
363 return;
364 }
365 let id = self.target_id;
366 (self.emit_lint)(AttributeLint { id, span, kind: lint });
367 }
368
369 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
370 self.emit_lint(
371 AttributeLintKind::UnusedDuplicate {
372 this: unused_span,
373 other: used_span,
374 warning: false,
375 },
376 unused_span,
377 )
378 }
379
380 pub(crate) fn warn_unused_duplicate_future_error(
381 &mut self,
382 used_span: Span,
383 unused_span: Span,
384 ) {
385 self.emit_lint(
386 AttributeLintKind::UnusedDuplicate {
387 this: unused_span,
388 other: used_span,
389 warning: true,
390 },
391 unused_span,
392 )
393 }
394}
395
396impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
397 pub(crate) fn unknown_key(
398 &self,
399 span: Span,
400 found: String,
401 options: &'static [&'static str],
402 ) -> ErrorGuaranteed {
403 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
404 }
405
406 pub(crate) fn expected_string_literal(
411 &self,
412 span: Span,
413 actual_literal: Option<&MetaItemLit>,
414 ) -> ErrorGuaranteed {
415 self.emit_err(AttributeParseError {
416 span,
417 attr_span: self.attr_span,
418 template: self.template.clone(),
419 attribute: self.attr_path.clone(),
420 reason: AttributeParseErrorReason::ExpectedStringLiteral {
421 byte_string: actual_literal.and_then(|i| {
422 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
423 }),
424 },
425 attr_style: self.attr_style,
426 })
427 }
428
429 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
430 self.emit_err(AttributeParseError {
431 span,
432 attr_span: self.attr_span,
433 template: self.template.clone(),
434 attribute: self.attr_path.clone(),
435 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
436 attr_style: self.attr_style,
437 })
438 }
439
440 pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
441 self.emit_err(AttributeParseError {
442 span,
443 attr_span: self.attr_span,
444 template: self.template.clone(),
445 attribute: self.attr_path.clone(),
446 reason: AttributeParseErrorReason::ExpectedList,
447 attr_style: self.attr_style,
448 })
449 }
450
451 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
452 self.emit_err(AttributeParseError {
453 span: args_span,
454 attr_span: self.attr_span,
455 template: self.template.clone(),
456 attribute: self.attr_path.clone(),
457 reason: AttributeParseErrorReason::ExpectedNoArgs,
458 attr_style: self.attr_style,
459 })
460 }
461
462 pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
464 self.emit_err(AttributeParseError {
465 span,
466 attr_span: self.attr_span,
467 template: self.template.clone(),
468 attribute: self.attr_path.clone(),
469 reason: AttributeParseErrorReason::ExpectedIdentifier,
470 attr_style: self.attr_style,
471 })
472 }
473
474 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
477 self.emit_err(AttributeParseError {
478 span,
479 attr_span: self.attr_span,
480 template: self.template.clone(),
481 attribute: self.attr_path.clone(),
482 reason: AttributeParseErrorReason::ExpectedNameValue(name),
483 attr_style: self.attr_style,
484 })
485 }
486
487 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
489 self.emit_err(AttributeParseError {
490 span,
491 attr_span: self.attr_span,
492 template: self.template.clone(),
493 attribute: self.attr_path.clone(),
494 reason: AttributeParseErrorReason::DuplicateKey(key),
495 attr_style: self.attr_style,
496 })
497 }
498
499 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
502 self.emit_err(AttributeParseError {
503 span,
504 attr_span: self.attr_span,
505 template: self.template.clone(),
506 attribute: self.attr_path.clone(),
507 reason: AttributeParseErrorReason::UnexpectedLiteral,
508 attr_style: self.attr_style,
509 })
510 }
511
512 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
513 self.emit_err(AttributeParseError {
514 span,
515 attr_span: self.attr_span,
516 template: self.template.clone(),
517 attribute: self.attr_path.clone(),
518 reason: AttributeParseErrorReason::ExpectedSingleArgument,
519 attr_style: self.attr_style,
520 })
521 }
522
523 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
524 self.emit_err(AttributeParseError {
525 span,
526 attr_span: self.attr_span,
527 template: self.template.clone(),
528 attribute: self.attr_path.clone(),
529 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
530 attr_style: self.attr_style,
531 })
532 }
533
534 pub(crate) fn expected_specific_argument(
536 &self,
537 span: Span,
538 possibilities: &[Symbol],
539 ) -> ErrorGuaranteed {
540 self.emit_err(AttributeParseError {
541 span,
542 attr_span: self.attr_span,
543 template: self.template.clone(),
544 attribute: self.attr_path.clone(),
545 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
546 possibilities,
547 strings: false,
548 list: false,
549 },
550 attr_style: self.attr_style,
551 })
552 }
553
554 pub(crate) fn expected_specific_argument_and_list(
557 &self,
558 span: Span,
559 possibilities: &[Symbol],
560 ) -> ErrorGuaranteed {
561 self.emit_err(AttributeParseError {
562 span,
563 attr_span: self.attr_span,
564 template: self.template.clone(),
565 attribute: self.attr_path.clone(),
566 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
567 possibilities,
568 strings: false,
569 list: true,
570 },
571 attr_style: self.attr_style,
572 })
573 }
574
575 pub(crate) fn expected_specific_argument_strings(
577 &self,
578 span: Span,
579 possibilities: &[Symbol],
580 ) -> ErrorGuaranteed {
581 self.emit_err(AttributeParseError {
582 span,
583 attr_span: self.attr_span,
584 template: self.template.clone(),
585 attribute: self.attr_path.clone(),
586 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
587 possibilities,
588 strings: true,
589 list: false,
590 },
591 attr_style: self.attr_style,
592 })
593 }
594
595 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
596 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
597 }
598}
599
600impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
601 type Target = SharedContext<'f, 'sess, S>;
602
603 fn deref(&self) -> &Self::Target {
604 &self.shared
605 }
606}
607
608impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
609 fn deref_mut(&mut self) -> &mut Self::Target {
610 &mut self.shared
611 }
612}
613
614pub struct SharedContext<'p, 'sess, S: Stage> {
619 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
622 pub(crate) target_span: Span,
624 pub(crate) target_id: S::Id,
626
627 pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
628}
629
630pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
635 pub(crate) shared: SharedContext<'p, 'sess, S>,
636
637 pub(crate) all_attrs: &'p [PathParser<'p>],
644}
645
646impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
647 type Target = SharedContext<'p, 'sess, S>;
648
649 fn deref(&self) -> &Self::Target {
650 &self.shared
651 }
652}
653
654impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
655 fn deref_mut(&mut self) -> &mut Self::Target {
656 &mut self.shared
657 }
658}
659
660impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
661 type Target = AttributeParser<'sess, S>;
662
663 fn deref(&self) -> &Self::Target {
664 self.cx
665 }
666}
667
668impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
669 fn deref_mut(&mut self) -> &mut Self::Target {
670 self.cx
671 }
672}
673
674#[derive(PartialEq, Clone, Copy, Debug)]
675pub enum OmitDoc {
676 Lower,
677 Skip,
678}
679
680#[derive(Copy, Clone, Debug)]
681pub enum ShouldEmit {
682 EarlyFatal { also_emit_lints: bool },
687 ErrorsAndLints,
690 Nothing,
693}
694
695impl ShouldEmit {
696 pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
697 match self {
698 ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
699 ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
700 ShouldEmit::ErrorsAndLints => diag.emit(),
701 ShouldEmit::Nothing => diag.delay_as_bug(),
702 }
703 }
704}