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