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