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