1use std::cell::RefCell;
2use std::collections::BTreeMap;
3use std::ops::{Deref, DerefMut};
4use std::sync::LazyLock;
5
6use itertools::Itertools;
7use private::Sealed;
8use rustc_ast::{self as ast, AttrStyle, LitKind, MetaItemLit, NodeId};
9use rustc_errors::{DiagCtxtHandle, Diagnostic};
10use rustc_feature::{AttributeTemplate, Features};
11use rustc_hir::attrs::AttributeKind;
12use rustc_hir::lints::{AttributeLint, AttributeLintKind};
13use rustc_hir::{
14 AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId, MethodKind, Target,
15};
16use rustc_session::Session;
17use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
18
19use crate::attributes::allow_unstable::{
20 AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
21};
22use crate::attributes::body::CoroutineParser;
23use crate::attributes::codegen_attrs::{
24 ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser,
25 TargetFeatureParser, TrackCallerParser, UsedParser,
26};
27use crate::attributes::confusables::ConfusablesParser;
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::context::MaybeWarn::{Allow, Error, Warn};
69use crate::parser::{ArgParser, MetaItemParser, PathParser};
70use crate::session_diagnostics::{
71 AttributeParseError, AttributeParseErrorReason, InvalidTarget, UnknownMetaItem,
72};
73
74type GroupType<S> = LazyLock<GroupTypeInner<S>>;
75
76struct GroupTypeInner<S: Stage> {
77 accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
78 finalizers: Vec<FinalizeFn<S>>,
79}
80
81struct GroupTypeInnerAccept<S: Stage> {
82 template: AttributeTemplate,
83 accept_fn: AcceptFn<S>,
84 allowed_targets: AllowedTargets,
85}
86
87type AcceptFn<S> =
88 Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
89type FinalizeFn<S> =
90 Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
91
92macro_rules! attribute_parsers {
93 (
94 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
95 ) => {
96 mod early {
97 use super::*;
98 type Combine<T> = super::Combine<T, Early>;
99 type Single<T> = super::Single<T, Early>;
100 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
101
102 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
103 }
104 mod late {
105 use super::*;
106 type Combine<T> = super::Combine<T, Late>;
107 type Single<T> = super::Single<T, Late>;
108 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
109
110 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
111 }
112 };
113 (
114 @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
115 ) => {
116 pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
117 let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
118 let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
119 $(
120 {
121 thread_local! {
122 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
123 };
124
125 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
126 accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
127 template: *template,
128 accept_fn: Box::new(|cx, args| {
129 STATE_OBJECT.with_borrow_mut(|s| {
130 accept_fn(s, cx, args)
131 })
132 }),
133 allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
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<ReprParser>,
165 Combine<TargetFeatureParser>,
166 Combine<UnstableFeatureBoundParser>,
167 Single<CoverageParser>,
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<ShouldPanicParser>,
191 Single<SkipDuringMethodDispatchParser>,
192 Single<TransparencyParser>,
193 Single<WithoutArgs<AllowIncoherentImplParser>>,
194 Single<WithoutArgs<AllowInternalUnsafeParser>>,
195 Single<WithoutArgs<AsPtrParser>>,
196 Single<WithoutArgs<AutomaticallyDerivedParser>>,
197 Single<WithoutArgs<CoherenceIsCoreParser>>,
198 Single<WithoutArgs<CoinductiveParser>>,
199 Single<WithoutArgs<ColdParser>>,
200 Single<WithoutArgs<ConstContinueParser>>,
201 Single<WithoutArgs<ConstStabilityIndirectParser>>,
202 Single<WithoutArgs<ConstTraitParser>>,
203 Single<WithoutArgs<CoroutineParser>>,
204 Single<WithoutArgs<DenyExplicitImplParser>>,
205 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
206 Single<WithoutArgs<ExportStableParser>>,
207 Single<WithoutArgs<FfiConstParser>>,
208 Single<WithoutArgs<FfiPureParser>>,
209 Single<WithoutArgs<FundamentalParser>>,
210 Single<WithoutArgs<LoopMatchParser>>,
211 Single<WithoutArgs<MacroEscapeParser>>,
212 Single<WithoutArgs<MarkerParser>>,
213 Single<WithoutArgs<MayDangleParser>>,
214 Single<WithoutArgs<NoImplicitPreludeParser>>,
215 Single<WithoutArgs<NoMangleParser>>,
216 Single<WithoutArgs<NonExhaustiveParser>>,
217 Single<WithoutArgs<ParenSugarParser>>,
218 Single<WithoutArgs<PassByValueParser>>,
219 Single<WithoutArgs<PointeeParser>>,
220 Single<WithoutArgs<ProcMacroAttributeParser>>,
221 Single<WithoutArgs<ProcMacroParser>>,
222 Single<WithoutArgs<PubTransparentParser>>,
223 Single<WithoutArgs<SpecializationTraitParser>>,
224 Single<WithoutArgs<StdInternalSymbolParser>>,
225 Single<WithoutArgs<TrackCallerParser>>,
226 Single<WithoutArgs<TypeConstParser>>,
227 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
228 ];
230);
231
232mod private {
233 pub trait Sealed {}
234 impl Sealed for super::Early {}
235 impl Sealed for super::Late {}
236}
237
238#[allow(private_interfaces)]
240pub trait Stage: Sized + 'static + Sealed {
241 type Id: Copy;
242
243 fn parsers() -> &'static GroupType<Self>;
244
245 fn emit_err<'sess>(
246 &self,
247 sess: &'sess Session,
248 diag: impl for<'x> Diagnostic<'x>,
249 ) -> ErrorGuaranteed;
250
251 fn should_emit(&self) -> ShouldEmit;
252}
253
254#[allow(private_interfaces)]
256impl Stage for Early {
257 type Id = NodeId;
258
259 fn parsers() -> &'static GroupType<Self> {
260 &early::ATTRIBUTE_PARSERS
261 }
262 fn emit_err<'sess>(
263 &self,
264 sess: &'sess Session,
265 diag: impl for<'x> Diagnostic<'x>,
266 ) -> ErrorGuaranteed {
267 if self.emit_errors.should_emit() {
268 sess.dcx().emit_err(diag)
269 } else {
270 sess.dcx().create_err(diag).delay_as_bug()
271 }
272 }
273
274 fn should_emit(&self) -> ShouldEmit {
275 self.emit_errors
276 }
277}
278
279#[allow(private_interfaces)]
281impl Stage for Late {
282 type Id = HirId;
283
284 fn parsers() -> &'static GroupType<Self> {
285 &late::ATTRIBUTE_PARSERS
286 }
287 fn emit_err<'sess>(
288 &self,
289 tcx: &'sess Session,
290 diag: impl for<'x> Diagnostic<'x>,
291 ) -> ErrorGuaranteed {
292 tcx.dcx().emit_err(diag)
293 }
294
295 fn should_emit(&self) -> ShouldEmit {
296 ShouldEmit::ErrorsAndLints
297 }
298}
299
300pub struct Early {
302 pub emit_errors: ShouldEmit,
306}
307pub struct Late;
309
310pub struct AcceptContext<'f, 'sess, S: Stage> {
314 pub(crate) shared: SharedContext<'f, 'sess, S>,
315 pub(crate) attr_span: Span,
317
318 pub(crate) attr_style: AttrStyle,
319 pub(crate) template: &'f AttributeTemplate,
323
324 pub(crate) attr_path: AttrPath,
326}
327
328impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
329 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
330 self.stage.emit_err(&self.sess, diag)
331 }
332
333 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
337 if !self.stage.should_emit().should_emit() {
338 return;
339 }
340 let id = self.target_id;
341 (self.emit_lint)(AttributeLint { id, span, kind: lint });
342 }
343
344 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
345 self.emit_lint(
346 AttributeLintKind::UnusedDuplicate {
347 this: unused_span,
348 other: used_span,
349 warning: false,
350 },
351 unused_span,
352 )
353 }
354
355 pub(crate) fn warn_unused_duplicate_future_error(
356 &mut self,
357 used_span: Span,
358 unused_span: Span,
359 ) {
360 self.emit_lint(
361 AttributeLintKind::UnusedDuplicate {
362 this: unused_span,
363 other: used_span,
364 warning: true,
365 },
366 unused_span,
367 )
368 }
369}
370
371impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
372 pub(crate) fn unknown_key(
373 &self,
374 span: Span,
375 found: String,
376 options: &'static [&'static str],
377 ) -> ErrorGuaranteed {
378 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
379 }
380
381 pub(crate) fn expected_string_literal(
386 &self,
387 span: Span,
388 actual_literal: Option<&MetaItemLit>,
389 ) -> ErrorGuaranteed {
390 self.emit_err(AttributeParseError {
391 span,
392 attr_span: self.attr_span,
393 template: self.template.clone(),
394 attribute: self.attr_path.clone(),
395 reason: AttributeParseErrorReason::ExpectedStringLiteral {
396 byte_string: actual_literal.and_then(|i| {
397 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
398 }),
399 },
400 attr_style: self.attr_style,
401 })
402 }
403
404 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
405 self.emit_err(AttributeParseError {
406 span,
407 attr_span: self.attr_span,
408 template: self.template.clone(),
409 attribute: self.attr_path.clone(),
410 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
411 attr_style: self.attr_style,
412 })
413 }
414
415 pub(crate) fn expected_list(&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::ExpectedList,
422 attr_style: self.attr_style,
423 })
424 }
425
426 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
427 self.emit_err(AttributeParseError {
428 span: args_span,
429 attr_span: self.attr_span,
430 template: self.template.clone(),
431 attribute: self.attr_path.clone(),
432 reason: AttributeParseErrorReason::ExpectedNoArgs,
433 attr_style: self.attr_style,
434 })
435 }
436
437 pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
439 self.emit_err(AttributeParseError {
440 span,
441 attr_span: self.attr_span,
442 template: self.template.clone(),
443 attribute: self.attr_path.clone(),
444 reason: AttributeParseErrorReason::ExpectedIdentifier,
445 attr_style: self.attr_style,
446 })
447 }
448
449 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
452 self.emit_err(AttributeParseError {
453 span,
454 attr_span: self.attr_span,
455 template: self.template.clone(),
456 attribute: self.attr_path.clone(),
457 reason: AttributeParseErrorReason::ExpectedNameValue(name),
458 attr_style: self.attr_style,
459 })
460 }
461
462 pub(crate) fn duplicate_key(&self, span: Span, key: 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::DuplicateKey(key),
470 attr_style: self.attr_style,
471 })
472 }
473
474 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
477 self.emit_err(AttributeParseError {
478 span,
479 attr_span: self.attr_span,
480 template: self.template.clone(),
481 attribute: self.attr_path.clone(),
482 reason: AttributeParseErrorReason::UnexpectedLiteral,
483 attr_style: self.attr_style,
484 })
485 }
486
487 pub(crate) fn expected_single_argument(&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::ExpectedSingleArgument,
494 attr_style: self.attr_style,
495 })
496 }
497
498 pub(crate) fn expected_at_least_one_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::ExpectedAtLeastOneArgument,
505 attr_style: self.attr_style,
506 })
507 }
508
509 pub(crate) fn expected_specific_argument(
510 &self,
511 span: Span,
512 possibilities: Vec<&'static str>,
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(
529 &self,
530 span: Span,
531 possibilities: Vec<&'static str>,
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(
548 &self,
549 span: Span,
550 possibilities: Vec<&'static str>,
551 ) -> ErrorGuaranteed {
552 self.emit_err(AttributeParseError {
553 span,
554 attr_span: self.attr_span,
555 template: self.template.clone(),
556 attribute: self.attr_path.clone(),
557 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
558 possibilities,
559 strings: true,
560 list: false,
561 },
562 attr_style: self.attr_style,
563 })
564 }
565
566 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
567 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
568 }
569}
570
571impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
572 type Target = SharedContext<'f, 'sess, S>;
573
574 fn deref(&self) -> &Self::Target {
575 &self.shared
576 }
577}
578
579impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
580 fn deref_mut(&mut self) -> &mut Self::Target {
581 &mut self.shared
582 }
583}
584
585pub struct SharedContext<'p, 'sess, S: Stage> {
590 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
593 pub(crate) target_span: Span,
595 pub(crate) target_id: S::Id,
597
598 emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
599}
600
601pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
606 pub(crate) shared: SharedContext<'p, 'sess, S>,
607
608 pub(crate) all_attrs: &'p [PathParser<'p>],
615}
616
617impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
618 type Target = SharedContext<'p, 'sess, S>;
619
620 fn deref(&self) -> &Self::Target {
621 &self.shared
622 }
623}
624
625impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
626 fn deref_mut(&mut self) -> &mut Self::Target {
627 &mut self.shared
628 }
629}
630
631impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
632 type Target = AttributeParser<'sess, S>;
633
634 fn deref(&self) -> &Self::Target {
635 self.cx
636 }
637}
638
639impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
640 fn deref_mut(&mut self) -> &mut Self::Target {
641 self.cx
642 }
643}
644
645#[derive(PartialEq, Clone, Copy, Debug)]
646pub enum OmitDoc {
647 Lower,
648 Skip,
649}
650
651#[derive(Copy, Clone)]
652pub enum ShouldEmit {
653 ErrorsAndLints,
656 Nothing,
659}
660
661impl ShouldEmit {
662 pub fn should_emit(&self) -> bool {
663 match self {
664 ShouldEmit::ErrorsAndLints => true,
665 ShouldEmit::Nothing => false,
666 }
667 }
668}
669
670#[derive(Debug)]
671pub(crate) enum AllowedTargets {
672 AllowList(&'static [MaybeWarn]),
673 AllowListWarnRest(&'static [MaybeWarn]),
674}
675
676pub(crate) enum AllowedResult {
677 Allowed,
678 Warn,
679 Error,
680}
681
682impl AllowedTargets {
683 pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult {
684 match self {
685 AllowedTargets::AllowList(list) => {
686 if list.contains(&Allow(target)) {
687 AllowedResult::Allowed
688 } else if list.contains(&Warn(target)) {
689 AllowedResult::Warn
690 } else {
691 AllowedResult::Error
692 }
693 }
694 AllowedTargets::AllowListWarnRest(list) => {
695 if list.contains(&Allow(target)) {
696 AllowedResult::Allowed
697 } else if list.contains(&Error(target)) {
698 AllowedResult::Error
699 } else {
700 AllowedResult::Warn
701 }
702 }
703 }
704 }
705
706 pub(crate) fn allowed_targets(&self) -> Vec<Target> {
707 match self {
708 AllowedTargets::AllowList(list) => list,
709 AllowedTargets::AllowListWarnRest(list) => list,
710 }
711 .iter()
712 .filter_map(|target| match target {
713 Allow(target) => Some(*target),
714 Warn(_) => None,
715 Error(_) => None,
716 })
717 .collect()
718 }
719}
720
721#[derive(Debug, Eq, PartialEq)]
722pub(crate) enum MaybeWarn {
723 Allow(Target),
724 Warn(Target),
725 Error(Target),
726}
727
728pub struct AttributeParser<'sess, S: Stage = Late> {
731 pub(crate) tools: Vec<Symbol>,
732 features: Option<&'sess Features>,
733 sess: &'sess Session,
734 stage: S,
735
736 parse_only: Option<Symbol>,
740}
741
742impl<'sess> AttributeParser<'sess, Early> {
743 pub fn parse_limited(
758 sess: &'sess Session,
759 attrs: &[ast::Attribute],
760 sym: Symbol,
761 target_span: Span,
762 target_node_id: NodeId,
763 features: Option<&'sess Features>,
764 ) -> Option<Attribute> {
765 let mut p = Self {
766 features,
767 tools: Vec::new(),
768 parse_only: Some(sym),
769 sess,
770 stage: Early { emit_errors: ShouldEmit::Nothing },
771 };
772 let mut parsed = p.parse_attribute_list(
773 attrs,
774 target_span,
775 target_node_id,
776 Target::Crate, OmitDoc::Skip,
778 std::convert::identity,
779 |_lint| {
780 panic!("can't emit lints here for now (nothing uses this atm)");
781 },
782 );
783 assert!(parsed.len() <= 1);
784
785 parsed.pop()
786 }
787
788 pub fn parse_single<T>(
789 sess: &'sess Session,
790 attr: &ast::Attribute,
791 target_span: Span,
792 target_node_id: NodeId,
793 features: Option<&'sess Features>,
794 emit_errors: ShouldEmit,
795 parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
796 template: &AttributeTemplate,
797 ) -> T {
798 let mut parser = Self {
799 features,
800 tools: Vec::new(),
801 parse_only: None,
802 sess,
803 stage: Early { emit_errors },
804 };
805 let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
806 panic!("parse_single called on a doc attr")
807 };
808 let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
809 let path = meta_parser.path();
810 let args = meta_parser.args();
811 let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
812 shared: SharedContext {
813 cx: &mut parser,
814 target_span,
815 target_id: target_node_id,
816 emit_lint: &mut |_lint| {
817 panic!("can't emit lints here for now (nothing uses this atm)");
818 },
819 },
820 attr_span: attr.span,
821 attr_style: attr.style,
822 template,
823 attr_path: path.get_attribute_path(),
824 };
825 parse_fn(&mut cx, args)
826 }
827}
828
829impl<'sess, S: Stage> AttributeParser<'sess, S> {
830 pub fn new(
831 sess: &'sess Session,
832 features: &'sess Features,
833 tools: Vec<Symbol>,
834 stage: S,
835 ) -> Self {
836 Self { features: Some(features), tools, parse_only: None, sess, stage }
837 }
838
839 pub(crate) fn sess(&self) -> &'sess Session {
840 &self.sess
841 }
842
843 pub(crate) fn features(&self) -> &'sess Features {
844 self.features.expect("features not available at this point in the compiler")
845 }
846
847 pub(crate) fn features_option(&self) -> Option<&'sess Features> {
848 self.features
849 }
850
851 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
852 self.sess().dcx()
853 }
854
855 pub fn parse_attribute_list(
860 &mut self,
861 attrs: &[ast::Attribute],
862 target_span: Span,
863 target_id: S::Id,
864 target: Target,
865 omit_doc: OmitDoc,
866
867 lower_span: impl Copy + Fn(Span) -> Span,
868 mut emit_lint: impl FnMut(AttributeLint<S::Id>),
869 ) -> Vec<Attribute> {
870 let mut attributes = Vec::new();
871 let mut attr_paths = Vec::new();
872
873 for attr in attrs {
874 if let Some(expected) = self.parse_only {
876 if !attr.has_name(expected) {
877 continue;
878 }
879 }
880
881 if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
887 continue;
888 }
889
890 match &attr.kind {
891 ast::AttrKind::DocComment(comment_kind, symbol) => {
892 if omit_doc == OmitDoc::Skip {
893 continue;
894 }
895
896 attributes.push(Attribute::Parsed(AttributeKind::DocComment {
897 style: attr.style,
898 kind: *comment_kind,
899 span: lower_span(attr.span),
900 comment: *symbol,
901 }))
902 }
903 ast::AttrKind::Normal(n) => {
915 attr_paths.push(PathParser::Ast(&n.item.path));
916
917 let parser = MetaItemParser::from_attr(n, self.dcx());
918 let path = parser.path();
919 let args = parser.args();
920 let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
921
922 if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
923 for accept in accepts {
924 let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
925 shared: SharedContext {
926 cx: self,
927 target_span,
928 target_id,
929 emit_lint: &mut emit_lint,
930 },
931 attr_span: lower_span(attr.span),
932 attr_style: attr.style,
933 template: &accept.template,
934 attr_path: path.get_attribute_path(),
935 };
936
937 (accept.accept_fn)(&mut cx, args);
938
939 if self.stage.should_emit().should_emit() {
940 match accept.allowed_targets.is_allowed(target) {
941 AllowedResult::Allowed => {}
942 AllowedResult::Warn => {
943 let allowed_targets =
944 accept.allowed_targets.allowed_targets();
945 let (applied, only) = allowed_targets_applied(
946 allowed_targets,
947 target,
948 self.features,
949 );
950 emit_lint(AttributeLint {
951 id: target_id,
952 span: attr.span,
953 kind: AttributeLintKind::InvalidTarget {
954 name: parts[0],
955 target,
956 only: if only { "only " } else { "" },
957 applied,
958 },
959 });
960 }
961 AllowedResult::Error => {
962 let allowed_targets =
963 accept.allowed_targets.allowed_targets();
964 let (applied, only) = allowed_targets_applied(
965 allowed_targets,
966 target,
967 self.features,
968 );
969 self.dcx().emit_err(InvalidTarget {
970 span: attr.span,
971 name: parts[0],
972 target: target.plural_name(),
973 only: if only { "only " } else { "" },
974 applied,
975 });
976 }
977 }
978 }
979 }
980 } else {
981 attributes.push(Attribute::Unparsed(Box::new(AttrItem {
997 path: AttrPath::from_ast(&n.item.path),
998 args: self.lower_attr_args(&n.item.args, lower_span),
999 id: HashIgnoredAttrId { attr_id: attr.id },
1000 style: attr.style,
1001 span: lower_span(attr.span),
1002 })));
1003 }
1004 }
1005 }
1006 }
1007
1008 let mut parsed_attributes = Vec::new();
1009 for f in &S::parsers().finalizers {
1010 if let Some(attr) = f(&mut FinalizeContext {
1011 shared: SharedContext {
1012 cx: self,
1013 target_span,
1014 target_id,
1015 emit_lint: &mut emit_lint,
1016 },
1017 all_attrs: &attr_paths,
1018 }) {
1019 parsed_attributes.push(Attribute::Parsed(attr));
1020 }
1021 }
1022
1023 attributes.extend(parsed_attributes);
1024
1025 attributes
1026 }
1027
1028 pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
1030 Late::parsers().accepters.contains_key(path)
1031 }
1032
1033 fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
1034 match args {
1035 ast::AttrArgs::Empty => AttrArgs::Empty,
1036 ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
1037 ast::AttrArgs::Eq { eq_span, expr } => {
1041 let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
1044 && let Ok(lit) =
1045 ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
1046 {
1047 lit
1048 } else {
1049 let guar = self.dcx().span_delayed_bug(
1050 args.span().unwrap_or(DUMMY_SP),
1051 "expr in place where literal is expected (builtin attr parsing)",
1052 );
1053 ast::MetaItemLit {
1054 symbol: sym::dummy,
1055 suffix: None,
1056 kind: ast::LitKind::Err(guar),
1057 span: DUMMY_SP,
1058 }
1059 };
1060 AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
1061 }
1062 }
1063 }
1064}
1065
1066pub(crate) fn allowed_targets_applied(
1069 mut allowed_targets: Vec<Target>,
1070 target: Target,
1071 features: Option<&Features>,
1072) -> (String, bool) {
1073 if let Some(features) = features {
1075 if !features.fn_delegation() {
1076 allowed_targets.retain(|t| !matches!(t, Target::Delegation { .. }));
1077 }
1078 if !features.stmt_expr_attributes() {
1079 allowed_targets.retain(|t| !matches!(t, Target::Expression | Target::Statement));
1080 }
1081 if !features.extern_types() {
1082 allowed_targets.retain(|t| !matches!(t, Target::ForeignTy));
1083 }
1084 }
1085
1086 const FUNCTION_LIKE: &[Target] = &[
1090 Target::Fn,
1091 Target::Closure,
1092 Target::ForeignFn,
1093 Target::Method(MethodKind::Inherent),
1094 Target::Method(MethodKind::Trait { body: false }),
1095 Target::Method(MethodKind::Trait { body: true }),
1096 Target::Method(MethodKind::TraitImpl),
1097 ];
1098 const METHOD_LIKE: &[Target] = &[
1099 Target::Method(MethodKind::Inherent),
1100 Target::Method(MethodKind::Trait { body: false }),
1101 Target::Method(MethodKind::Trait { body: true }),
1102 Target::Method(MethodKind::TraitImpl),
1103 ];
1104 const IMPL_LIKE: &[Target] =
1105 &[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }];
1106 const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum];
1107
1108 let mut added_fake_targets = Vec::new();
1109 filter_targets(
1110 &mut allowed_targets,
1111 FUNCTION_LIKE,
1112 "functions",
1113 target,
1114 &mut added_fake_targets,
1115 );
1116 filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets);
1117 filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets);
1118 filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets);
1119
1120 (
1122 added_fake_targets
1123 .iter()
1124 .copied()
1125 .chain(allowed_targets.iter().map(|t| t.plural_name()))
1126 .join(", "),
1127 allowed_targets.len() + added_fake_targets.len() == 1,
1128 )
1129}
1130
1131fn filter_targets(
1132 allowed_targets: &mut Vec<Target>,
1133 target_group: &'static [Target],
1134 target_group_name: &'static str,
1135 target: Target,
1136 added_fake_targets: &mut Vec<&'static str>,
1137) {
1138 if target_group.contains(&target) {
1139 return;
1140 }
1141 if allowed_targets.iter().filter(|at| target_group.contains(at)).count() < 2 {
1142 return;
1143 }
1144 allowed_targets.retain(|t| !target_group.contains(t));
1145 added_fake_targets.push(target_group_name);
1146}
1147
1148pub(crate) const ALL_TARGETS: &'static [MaybeWarn] = &[
1153 Allow(Target::ExternCrate),
1154 Allow(Target::Use),
1155 Allow(Target::Static),
1156 Allow(Target::Const),
1157 Allow(Target::Fn),
1158 Allow(Target::Closure),
1159 Allow(Target::Mod),
1160 Allow(Target::ForeignMod),
1161 Allow(Target::GlobalAsm),
1162 Allow(Target::TyAlias),
1163 Allow(Target::Enum),
1164 Allow(Target::Variant),
1165 Allow(Target::Struct),
1166 Allow(Target::Field),
1167 Allow(Target::Union),
1168 Allow(Target::Trait),
1169 Allow(Target::TraitAlias),
1170 Allow(Target::Impl { of_trait: false }),
1171 Allow(Target::Impl { of_trait: true }),
1172 Allow(Target::Expression),
1173 Allow(Target::Statement),
1174 Allow(Target::Arm),
1175 Allow(Target::AssocConst),
1176 Allow(Target::Method(MethodKind::Inherent)),
1177 Allow(Target::Method(MethodKind::Trait { body: false })),
1178 Allow(Target::Method(MethodKind::Trait { body: true })),
1179 Allow(Target::Method(MethodKind::TraitImpl)),
1180 Allow(Target::AssocTy),
1181 Allow(Target::ForeignFn),
1182 Allow(Target::ForeignStatic),
1183 Allow(Target::ForeignTy),
1184 Allow(Target::MacroDef),
1185 Allow(Target::Param),
1186 Allow(Target::PatField),
1187 Allow(Target::ExprField),
1188 Allow(Target::WherePredicate),
1189 Allow(Target::MacroCall),
1190 Allow(Target::Crate),
1191 Allow(Target::Delegation { mac: false }),
1192 Allow(Target::Delegation { mac: true }),
1193];
1194
1195pub(crate) fn parse_single_integer<S: Stage>(
1202 cx: &mut AcceptContext<'_, '_, S>,
1203 args: &ArgParser<'_>,
1204) -> Option<u128> {
1205 let Some(list) = args.list() else {
1206 cx.expected_list(cx.attr_span);
1207 return None;
1208 };
1209 let Some(single) = list.single() else {
1210 cx.expected_single_argument(list.span);
1211 return None;
1212 };
1213 let Some(lit) = single.lit() else {
1214 cx.expected_integer_literal(single.span());
1215 return None;
1216 };
1217 let LitKind::Int(num, _ty) = lit.kind else {
1218 cx.expected_integer_literal(single.span());
1219 return None;
1220 };
1221 Some(num.0)
1222}