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::{Diag, Diagnostic, Level};
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, 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}
84
85type AcceptFn<S> =
86 Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
87type FinalizeFn<S> =
88 Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
89
90macro_rules! attribute_parsers {
91 (
92 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
93 ) => {
94 mod early {
95 use super::*;
96 type Combine<T> = super::Combine<T, Early>;
97 type Single<T> = super::Single<T, Early>;
98 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
99
100 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
101 }
102 mod late {
103 use super::*;
104 type Combine<T> = super::Combine<T, Late>;
105 type Single<T> = super::Single<T, Late>;
106 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
107
108 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
109 }
110 };
111 (
112 @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
113 ) => {
114 pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
115 let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
116 let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
117 $(
118 {
119 thread_local! {
120 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
121 };
122
123 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
124 accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
125 template: *template,
126 accept_fn: Box::new(|cx, args| {
127 STATE_OBJECT.with_borrow_mut(|s| {
128 accept_fn(s, cx, args)
129 })
130 }),
131 allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
132 });
133 }
134
135 finalizes.push(Box::new(|cx| {
136 let state = STATE_OBJECT.take();
137 state.finalize(cx)
138 }));
139 }
140 )*
141
142 GroupTypeInner { accepters:accepts, finalizers:finalizes }
143 });
144 };
145}
146attribute_parsers!(
147 pub(crate) static ATTRIBUTE_PARSERS = [
148 AlignParser,
150 BodyStabilityParser,
151 ConfusablesParser,
152 ConstStabilityParser,
153 MacroUseParser,
154 NakedParser,
155 StabilityParser,
156 UsedParser,
157 Combine<AllowConstFnUnstableParser>,
161 Combine<AllowInternalUnstableParser>,
162 Combine<ForceTargetFeatureParser>,
163 Combine<ReprParser>,
164 Combine<TargetFeatureParser>,
165 Combine<UnstableFeatureBoundParser>,
166 Single<CoverageParser>,
170 Single<CrateNameParser>,
171 Single<CustomMirParser>,
172 Single<DeprecationParser>,
173 Single<DummyParser>,
174 Single<ExportNameParser>,
175 Single<IgnoreParser>,
176 Single<InlineParser>,
177 Single<LinkNameParser>,
178 Single<LinkOrdinalParser>,
179 Single<LinkSectionParser>,
180 Single<LinkageParser>,
181 Single<MustUseParser>,
182 Single<OptimizeParser>,
183 Single<PathAttributeParser>,
184 Single<ProcMacroDeriveParser>,
185 Single<RustcBuiltinMacroParser>,
186 Single<RustcForceInlineParser>,
187 Single<RustcLayoutScalarValidRangeEnd>,
188 Single<RustcLayoutScalarValidRangeStart>,
189 Single<RustcObjectLifetimeDefaultParser>,
190 Single<SanitizeParser>,
191 Single<ShouldPanicParser>,
192 Single<SkipDuringMethodDispatchParser>,
193 Single<TransparencyParser>,
194 Single<WithoutArgs<AllowIncoherentImplParser>>,
195 Single<WithoutArgs<AllowInternalUnsafeParser>>,
196 Single<WithoutArgs<AsPtrParser>>,
197 Single<WithoutArgs<AutomaticallyDerivedParser>>,
198 Single<WithoutArgs<CoherenceIsCoreParser>>,
199 Single<WithoutArgs<CoinductiveParser>>,
200 Single<WithoutArgs<ColdParser>>,
201 Single<WithoutArgs<ConstContinueParser>>,
202 Single<WithoutArgs<ConstStabilityIndirectParser>>,
203 Single<WithoutArgs<ConstTraitParser>>,
204 Single<WithoutArgs<CoroutineParser>>,
205 Single<WithoutArgs<DenyExplicitImplParser>>,
206 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
207 Single<WithoutArgs<ExportStableParser>>,
208 Single<WithoutArgs<FfiConstParser>>,
209 Single<WithoutArgs<FfiPureParser>>,
210 Single<WithoutArgs<FundamentalParser>>,
211 Single<WithoutArgs<LoopMatchParser>>,
212 Single<WithoutArgs<MacroEscapeParser>>,
213 Single<WithoutArgs<MarkerParser>>,
214 Single<WithoutArgs<MayDangleParser>>,
215 Single<WithoutArgs<NoImplicitPreludeParser>>,
216 Single<WithoutArgs<NoMangleParser>>,
217 Single<WithoutArgs<NonExhaustiveParser>>,
218 Single<WithoutArgs<ParenSugarParser>>,
219 Single<WithoutArgs<PassByValueParser>>,
220 Single<WithoutArgs<PointeeParser>>,
221 Single<WithoutArgs<ProcMacroAttributeParser>>,
222 Single<WithoutArgs<ProcMacroParser>>,
223 Single<WithoutArgs<PubTransparentParser>>,
224 Single<WithoutArgs<SpecializationTraitParser>>,
225 Single<WithoutArgs<StdInternalSymbolParser>>,
226 Single<WithoutArgs<TrackCallerParser>>,
227 Single<WithoutArgs<TypeConstParser>>,
228 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
229 ];
231);
232
233mod private {
234 pub trait Sealed {}
235 impl Sealed for super::Early {}
236 impl Sealed for super::Late {}
237}
238
239#[allow(private_interfaces)]
241pub trait Stage: Sized + 'static + Sealed {
242 type Id: Copy;
243
244 fn parsers() -> &'static GroupType<Self>;
245
246 fn emit_err<'sess>(
247 &self,
248 sess: &'sess Session,
249 diag: impl for<'x> Diagnostic<'x>,
250 ) -> ErrorGuaranteed;
251
252 fn should_emit(&self) -> ShouldEmit;
253}
254
255#[allow(private_interfaces)]
257impl Stage for Early {
258 type Id = NodeId;
259
260 fn parsers() -> &'static GroupType<Self> {
261 &early::ATTRIBUTE_PARSERS
262 }
263 fn emit_err<'sess>(
264 &self,
265 sess: &'sess Session,
266 diag: impl for<'x> Diagnostic<'x>,
267 ) -> ErrorGuaranteed {
268 self.should_emit().emit_err(sess.dcx().create_err(diag))
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,
317
318 pub(crate) template: &'f AttributeTemplate,
322
323 pub(crate) attr_path: AttrPath,
325}
326
327impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
328 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
329 self.stage.emit_err(&self.sess, diag)
330 }
331
332 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
336 if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
337 return;
338 }
339 let id = self.target_id;
340 (self.emit_lint)(AttributeLint { id, span, kind: lint });
341 }
342
343 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
344 self.emit_lint(
345 AttributeLintKind::UnusedDuplicate {
346 this: unused_span,
347 other: used_span,
348 warning: false,
349 },
350 unused_span,
351 )
352 }
353
354 pub(crate) fn warn_unused_duplicate_future_error(
355 &mut self,
356 used_span: Span,
357 unused_span: Span,
358 ) {
359 self.emit_lint(
360 AttributeLintKind::UnusedDuplicate {
361 this: unused_span,
362 other: used_span,
363 warning: true,
364 },
365 unused_span,
366 )
367 }
368}
369
370impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
371 pub(crate) fn unknown_key(
372 &self,
373 span: Span,
374 found: String,
375 options: &'static [&'static str],
376 ) -> ErrorGuaranteed {
377 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
378 }
379
380 pub(crate) fn expected_string_literal(
385 &self,
386 span: Span,
387 actual_literal: Option<&MetaItemLit>,
388 ) -> ErrorGuaranteed {
389 self.emit_err(AttributeParseError {
390 span,
391 attr_span: self.attr_span,
392 template: self.template.clone(),
393 attribute: self.attr_path.clone(),
394 reason: AttributeParseErrorReason::ExpectedStringLiteral {
395 byte_string: actual_literal.and_then(|i| {
396 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
397 }),
398 },
399 attr_style: self.attr_style,
400 })
401 }
402
403 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
404 self.emit_err(AttributeParseError {
405 span,
406 attr_span: self.attr_span,
407 template: self.template.clone(),
408 attribute: self.attr_path.clone(),
409 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
410 attr_style: self.attr_style,
411 })
412 }
413
414 pub(crate) fn expected_list(&self, span: Span) -> 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::ExpectedList,
421 attr_style: self.attr_style,
422 })
423 }
424
425 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
426 self.emit_err(AttributeParseError {
427 span: args_span,
428 attr_span: self.attr_span,
429 template: self.template.clone(),
430 attribute: self.attr_path.clone(),
431 reason: AttributeParseErrorReason::ExpectedNoArgs,
432 attr_style: self.attr_style,
433 })
434 }
435
436 pub(crate) fn expected_identifier(&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::ExpectedIdentifier,
444 attr_style: self.attr_style,
445 })
446 }
447
448 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> 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::ExpectedNameValue(name),
457 attr_style: self.attr_style,
458 })
459 }
460
461 pub(crate) fn duplicate_key(&self, span: Span, key: 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::DuplicateKey(key),
469 attr_style: self.attr_style,
470 })
471 }
472
473 pub(crate) fn unexpected_literal(&self, span: Span) -> 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::UnexpectedLiteral,
482 attr_style: self.attr_style,
483 })
484 }
485
486 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
487 self.emit_err(AttributeParseError {
488 span,
489 attr_span: self.attr_span,
490 template: self.template.clone(),
491 attribute: self.attr_path.clone(),
492 reason: AttributeParseErrorReason::ExpectedSingleArgument,
493 attr_style: self.attr_style,
494 })
495 }
496
497 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
498 self.emit_err(AttributeParseError {
499 span,
500 attr_span: self.attr_span,
501 template: self.template.clone(),
502 attribute: self.attr_path.clone(),
503 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
504 attr_style: self.attr_style,
505 })
506 }
507
508 pub(crate) fn expected_specific_argument(
510 &self,
511 span: Span,
512 possibilities: &[Symbol],
513 ) -> ErrorGuaranteed {
514 self.emit_err(AttributeParseError {
515 span,
516 attr_span: self.attr_span,
517 template: self.template.clone(),
518 attribute: self.attr_path.clone(),
519 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
520 possibilities,
521 strings: false,
522 list: false,
523 },
524 attr_style: self.attr_style,
525 })
526 }
527
528 pub(crate) fn expected_specific_argument_and_list(
531 &self,
532 span: Span,
533 possibilities: &[Symbol],
534 ) -> ErrorGuaranteed {
535 self.emit_err(AttributeParseError {
536 span,
537 attr_span: self.attr_span,
538 template: self.template.clone(),
539 attribute: self.attr_path.clone(),
540 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
541 possibilities,
542 strings: false,
543 list: true,
544 },
545 attr_style: self.attr_style,
546 })
547 }
548
549 pub(crate) fn expected_specific_argument_strings(
551 &self,
552 span: Span,
553 possibilities: &[Symbol],
554 ) -> ErrorGuaranteed {
555 self.emit_err(AttributeParseError {
556 span,
557 attr_span: self.attr_span,
558 template: self.template.clone(),
559 attribute: self.attr_path.clone(),
560 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
561 possibilities,
562 strings: true,
563 list: false,
564 },
565 attr_style: self.attr_style,
566 })
567 }
568
569 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
570 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
571 }
572}
573
574impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
575 type Target = SharedContext<'f, 'sess, S>;
576
577 fn deref(&self) -> &Self::Target {
578 &self.shared
579 }
580}
581
582impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
583 fn deref_mut(&mut self) -> &mut Self::Target {
584 &mut self.shared
585 }
586}
587
588pub struct SharedContext<'p, 'sess, S: Stage> {
593 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
596 pub(crate) target_span: Span,
598 pub(crate) target_id: S::Id,
600
601 pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
602}
603
604pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
609 pub(crate) shared: SharedContext<'p, 'sess, S>,
610
611 pub(crate) all_attrs: &'p [PathParser<'p>],
618}
619
620impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
621 type Target = SharedContext<'p, 'sess, S>;
622
623 fn deref(&self) -> &Self::Target {
624 &self.shared
625 }
626}
627
628impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
629 fn deref_mut(&mut self) -> &mut Self::Target {
630 &mut self.shared
631 }
632}
633
634impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
635 type Target = AttributeParser<'sess, S>;
636
637 fn deref(&self) -> &Self::Target {
638 self.cx
639 }
640}
641
642impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
643 fn deref_mut(&mut self) -> &mut Self::Target {
644 self.cx
645 }
646}
647
648#[derive(PartialEq, Clone, Copy, Debug)]
649pub enum OmitDoc {
650 Lower,
651 Skip,
652}
653
654#[derive(Copy, Clone, Debug)]
655pub enum ShouldEmit {
656 EarlyFatal,
661 ErrorsAndLints,
664 Nothing,
667}
668
669impl ShouldEmit {
670 pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
671 match self {
672 ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
673 ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
674 ShouldEmit::ErrorsAndLints => diag.emit(),
675 ShouldEmit::Nothing => diag.delay_as_bug(),
676 }
677 }
678}