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, PatternComplexityLimitParser, RecursionLimitParser,
29 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, 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 BodyStabilityParser,
156 ConfusablesParser,
157 ConstStabilityParser,
158 MacroUseParser,
159 NakedParser,
160 StabilityParser,
161 UsedParser,
162 Combine<AllowConstFnUnstableParser>,
166 Combine<AllowInternalUnstableParser>,
167 Combine<ForceTargetFeatureParser>,
168 Combine<LinkParser>,
169 Combine<ReprParser>,
170 Combine<TargetFeatureParser>,
171 Combine<UnstableFeatureBoundParser>,
172 Single<CoverageParser>,
176 Single<CrateNameParser>,
177 Single<CustomMirParser>,
178 Single<DeprecationParser>,
179 Single<DummyParser>,
180 Single<ExportNameParser>,
181 Single<IgnoreParser>,
182 Single<InlineParser>,
183 Single<LinkNameParser>,
184 Single<LinkOrdinalParser>,
185 Single<LinkSectionParser>,
186 Single<LinkageParser>,
187 Single<MoveSizeLimitParser>,
188 Single<MustUseParser>,
189 Single<OptimizeParser>,
190 Single<PathAttributeParser>,
191 Single<PatternComplexityLimitParser>,
192 Single<ProcMacroDeriveParser>,
193 Single<RecursionLimitParser>,
194 Single<RustcBuiltinMacroParser>,
195 Single<RustcForceInlineParser>,
196 Single<RustcLayoutScalarValidRangeEnd>,
197 Single<RustcLayoutScalarValidRangeStart>,
198 Single<RustcObjectLifetimeDefaultParser>,
199 Single<SanitizeParser>,
200 Single<ShouldPanicParser>,
201 Single<SkipDuringMethodDispatchParser>,
202 Single<TransparencyParser>,
203 Single<TypeLengthLimitParser>,
204 Single<WithoutArgs<AllowIncoherentImplParser>>,
205 Single<WithoutArgs<AllowInternalUnsafeParser>>,
206 Single<WithoutArgs<AsPtrParser>>,
207 Single<WithoutArgs<AutomaticallyDerivedParser>>,
208 Single<WithoutArgs<CoherenceIsCoreParser>>,
209 Single<WithoutArgs<CoinductiveParser>>,
210 Single<WithoutArgs<ColdParser>>,
211 Single<WithoutArgs<ConstContinueParser>>,
212 Single<WithoutArgs<ConstStabilityIndirectParser>>,
213 Single<WithoutArgs<ConstTraitParser>>,
214 Single<WithoutArgs<CoroutineParser>>,
215 Single<WithoutArgs<DenyExplicitImplParser>>,
216 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
217 Single<WithoutArgs<ExportStableParser>>,
218 Single<WithoutArgs<FfiConstParser>>,
219 Single<WithoutArgs<FfiPureParser>>,
220 Single<WithoutArgs<FundamentalParser>>,
221 Single<WithoutArgs<LoopMatchParser>>,
222 Single<WithoutArgs<MacroEscapeParser>>,
223 Single<WithoutArgs<MarkerParser>>,
224 Single<WithoutArgs<MayDangleParser>>,
225 Single<WithoutArgs<NoImplicitPreludeParser>>,
226 Single<WithoutArgs<NoMangleParser>>,
227 Single<WithoutArgs<NonExhaustiveParser>>,
228 Single<WithoutArgs<ParenSugarParser>>,
229 Single<WithoutArgs<PassByValueParser>>,
230 Single<WithoutArgs<PointeeParser>>,
231 Single<WithoutArgs<ProcMacroAttributeParser>>,
232 Single<WithoutArgs<ProcMacroParser>>,
233 Single<WithoutArgs<PubTransparentParser>>,
234 Single<WithoutArgs<SpecializationTraitParser>>,
235 Single<WithoutArgs<StdInternalSymbolParser>>,
236 Single<WithoutArgs<TrackCallerParser>>,
237 Single<WithoutArgs<TypeConstParser>>,
238 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
239 ];
241);
242
243mod private {
244 pub trait Sealed {}
245 impl Sealed for super::Early {}
246 impl Sealed for super::Late {}
247}
248
249#[allow(private_interfaces)]
251pub trait Stage: Sized + 'static + Sealed {
252 type Id: Copy;
253
254 fn parsers() -> &'static GroupType<Self>;
255
256 fn emit_err<'sess>(
257 &self,
258 sess: &'sess Session,
259 diag: impl for<'x> Diagnostic<'x>,
260 ) -> ErrorGuaranteed;
261
262 fn should_emit(&self) -> ShouldEmit;
263
264 fn id_is_crate_root(id: Self::Id) -> bool;
265}
266
267#[allow(private_interfaces)]
269impl Stage for Early {
270 type Id = NodeId;
271
272 fn parsers() -> &'static GroupType<Self> {
273 &early::ATTRIBUTE_PARSERS
274 }
275 fn emit_err<'sess>(
276 &self,
277 sess: &'sess Session,
278 diag: impl for<'x> Diagnostic<'x>,
279 ) -> ErrorGuaranteed {
280 self.should_emit().emit_err(sess.dcx().create_err(diag))
281 }
282
283 fn should_emit(&self) -> ShouldEmit {
284 self.emit_errors
285 }
286
287 fn id_is_crate_root(id: Self::Id) -> bool {
288 id == CRATE_NODE_ID
289 }
290}
291
292#[allow(private_interfaces)]
294impl Stage for Late {
295 type Id = HirId;
296
297 fn parsers() -> &'static GroupType<Self> {
298 &late::ATTRIBUTE_PARSERS
299 }
300 fn emit_err<'sess>(
301 &self,
302 tcx: &'sess Session,
303 diag: impl for<'x> Diagnostic<'x>,
304 ) -> ErrorGuaranteed {
305 tcx.dcx().emit_err(diag)
306 }
307
308 fn should_emit(&self) -> ShouldEmit {
309 ShouldEmit::ErrorsAndLints
310 }
311
312 fn id_is_crate_root(id: Self::Id) -> bool {
313 id == CRATE_HIR_ID
314 }
315}
316
317pub struct Early {
319 pub emit_errors: ShouldEmit,
323}
324pub struct Late;
326
327pub struct AcceptContext<'f, 'sess, S: Stage> {
331 pub(crate) shared: SharedContext<'f, 'sess, S>,
332 pub(crate) attr_span: Span,
334
335 pub(crate) attr_style: AttrStyle,
337
338 pub(crate) template: &'f AttributeTemplate,
342
343 pub(crate) attr_path: AttrPath,
345}
346
347impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
348 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
349 self.stage.emit_err(&self.sess, diag)
350 }
351
352 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
356 if !matches!(
357 self.stage.should_emit(),
358 ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
359 ) {
360 return;
361 }
362 let id = self.target_id;
363 (self.emit_lint)(AttributeLint { id, span, kind: lint });
364 }
365
366 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
367 self.emit_lint(
368 AttributeLintKind::UnusedDuplicate {
369 this: unused_span,
370 other: used_span,
371 warning: false,
372 },
373 unused_span,
374 )
375 }
376
377 pub(crate) fn warn_unused_duplicate_future_error(
378 &mut self,
379 used_span: Span,
380 unused_span: Span,
381 ) {
382 self.emit_lint(
383 AttributeLintKind::UnusedDuplicate {
384 this: unused_span,
385 other: used_span,
386 warning: true,
387 },
388 unused_span,
389 )
390 }
391}
392
393impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
394 pub(crate) fn unknown_key(
395 &self,
396 span: Span,
397 found: String,
398 options: &'static [&'static str],
399 ) -> ErrorGuaranteed {
400 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
401 }
402
403 pub(crate) fn expected_string_literal(
408 &self,
409 span: Span,
410 actual_literal: Option<&MetaItemLit>,
411 ) -> ErrorGuaranteed {
412 self.emit_err(AttributeParseError {
413 span,
414 attr_span: self.attr_span,
415 template: self.template.clone(),
416 attribute: self.attr_path.clone(),
417 reason: AttributeParseErrorReason::ExpectedStringLiteral {
418 byte_string: actual_literal.and_then(|i| {
419 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
420 }),
421 },
422 attr_style: self.attr_style,
423 })
424 }
425
426 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
427 self.emit_err(AttributeParseError {
428 span,
429 attr_span: self.attr_span,
430 template: self.template.clone(),
431 attribute: self.attr_path.clone(),
432 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
433 attr_style: self.attr_style,
434 })
435 }
436
437 pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
438 self.emit_err(AttributeParseError {
439 span,
440 attr_span: self.attr_span,
441 template: self.template.clone(),
442 attribute: self.attr_path.clone(),
443 reason: AttributeParseErrorReason::ExpectedList,
444 attr_style: self.attr_style,
445 })
446 }
447
448 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
449 self.emit_err(AttributeParseError {
450 span: args_span,
451 attr_span: self.attr_span,
452 template: self.template.clone(),
453 attribute: self.attr_path.clone(),
454 reason: AttributeParseErrorReason::ExpectedNoArgs,
455 attr_style: self.attr_style,
456 })
457 }
458
459 pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
461 self.emit_err(AttributeParseError {
462 span,
463 attr_span: self.attr_span,
464 template: self.template.clone(),
465 attribute: self.attr_path.clone(),
466 reason: AttributeParseErrorReason::ExpectedIdentifier,
467 attr_style: self.attr_style,
468 })
469 }
470
471 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
474 self.emit_err(AttributeParseError {
475 span,
476 attr_span: self.attr_span,
477 template: self.template.clone(),
478 attribute: self.attr_path.clone(),
479 reason: AttributeParseErrorReason::ExpectedNameValue(name),
480 attr_style: self.attr_style,
481 })
482 }
483
484 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
486 self.emit_err(AttributeParseError {
487 span,
488 attr_span: self.attr_span,
489 template: self.template.clone(),
490 attribute: self.attr_path.clone(),
491 reason: AttributeParseErrorReason::DuplicateKey(key),
492 attr_style: self.attr_style,
493 })
494 }
495
496 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
499 self.emit_err(AttributeParseError {
500 span,
501 attr_span: self.attr_span,
502 template: self.template.clone(),
503 attribute: self.attr_path.clone(),
504 reason: AttributeParseErrorReason::UnexpectedLiteral,
505 attr_style: self.attr_style,
506 })
507 }
508
509 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
510 self.emit_err(AttributeParseError {
511 span,
512 attr_span: self.attr_span,
513 template: self.template.clone(),
514 attribute: self.attr_path.clone(),
515 reason: AttributeParseErrorReason::ExpectedSingleArgument,
516 attr_style: self.attr_style,
517 })
518 }
519
520 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
521 self.emit_err(AttributeParseError {
522 span,
523 attr_span: self.attr_span,
524 template: self.template.clone(),
525 attribute: self.attr_path.clone(),
526 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
527 attr_style: self.attr_style,
528 })
529 }
530
531 pub(crate) fn expected_specific_argument(
533 &self,
534 span: Span,
535 possibilities: &[Symbol],
536 ) -> ErrorGuaranteed {
537 self.emit_err(AttributeParseError {
538 span,
539 attr_span: self.attr_span,
540 template: self.template.clone(),
541 attribute: self.attr_path.clone(),
542 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
543 possibilities,
544 strings: false,
545 list: false,
546 },
547 attr_style: self.attr_style,
548 })
549 }
550
551 pub(crate) fn expected_specific_argument_and_list(
554 &self,
555 span: Span,
556 possibilities: &[Symbol],
557 ) -> ErrorGuaranteed {
558 self.emit_err(AttributeParseError {
559 span,
560 attr_span: self.attr_span,
561 template: self.template.clone(),
562 attribute: self.attr_path.clone(),
563 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
564 possibilities,
565 strings: false,
566 list: true,
567 },
568 attr_style: self.attr_style,
569 })
570 }
571
572 pub(crate) fn expected_specific_argument_strings(
574 &self,
575 span: Span,
576 possibilities: &[Symbol],
577 ) -> ErrorGuaranteed {
578 self.emit_err(AttributeParseError {
579 span,
580 attr_span: self.attr_span,
581 template: self.template.clone(),
582 attribute: self.attr_path.clone(),
583 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
584 possibilities,
585 strings: true,
586 list: false,
587 },
588 attr_style: self.attr_style,
589 })
590 }
591
592 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
593 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
594 }
595}
596
597impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
598 type Target = SharedContext<'f, 'sess, S>;
599
600 fn deref(&self) -> &Self::Target {
601 &self.shared
602 }
603}
604
605impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
606 fn deref_mut(&mut self) -> &mut Self::Target {
607 &mut self.shared
608 }
609}
610
611pub struct SharedContext<'p, 'sess, S: Stage> {
616 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
619 pub(crate) target_span: Span,
621 pub(crate) target_id: S::Id,
623
624 pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
625}
626
627pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
632 pub(crate) shared: SharedContext<'p, 'sess, S>,
633
634 pub(crate) all_attrs: &'p [PathParser<'p>],
641}
642
643impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
644 type Target = SharedContext<'p, 'sess, S>;
645
646 fn deref(&self) -> &Self::Target {
647 &self.shared
648 }
649}
650
651impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
652 fn deref_mut(&mut self) -> &mut Self::Target {
653 &mut self.shared
654 }
655}
656
657impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
658 type Target = AttributeParser<'sess, S>;
659
660 fn deref(&self) -> &Self::Target {
661 self.cx
662 }
663}
664
665impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
666 fn deref_mut(&mut self) -> &mut Self::Target {
667 self.cx
668 }
669}
670
671#[derive(PartialEq, Clone, Copy, Debug)]
672pub enum OmitDoc {
673 Lower,
674 Skip,
675}
676
677#[derive(Copy, Clone, Debug)]
678pub enum ShouldEmit {
679 EarlyFatal { also_emit_lints: bool },
684 ErrorsAndLints,
687 Nothing,
690}
691
692impl ShouldEmit {
693 pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
694 match self {
695 ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
696 ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
697 ShouldEmit::ErrorsAndLints => diag.emit(),
698 ShouldEmit::Nothing => diag.delay_as_bug(),
699 }
700 }
701}