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, 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::repr::{AlignParser, ReprParser};
50use crate::attributes::rustc_internal::{
51 RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
52 RustcObjectLifetimeDefaultParser,
53};
54use crate::attributes::semantics::MayDangleParser;
55use crate::attributes::stability::{
56 BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
57};
58use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
59use crate::attributes::traits::{
60 AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
61 DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
62 ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
63 TypeConstParser, UnsafeSpecializationMarkerParser,
64};
65use crate::attributes::transparency::TransparencyParser;
66use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
67use crate::context::MaybeWarn::{Allow, Error, Warn};
68use crate::parser::{ArgParser, MetaItemParser, PathParser};
69use crate::session_diagnostics::{
70 AttributeParseError, AttributeParseErrorReason, InvalidTarget, UnknownMetaItem,
71};
72
73type GroupType<S> = LazyLock<GroupTypeInner<S>>;
74
75struct GroupTypeInner<S: Stage> {
76 accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
77 finalizers: Vec<FinalizeFn<S>>,
78}
79
80struct GroupTypeInnerAccept<S: Stage> {
81 template: AttributeTemplate,
82 accept_fn: AcceptFn<S>,
83 allowed_targets: AllowedTargets,
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 });
134 }
135
136 finalizes.push(Box::new(|cx| {
137 let state = STATE_OBJECT.take();
138 state.finalize(cx)
139 }));
140 }
141 )*
142
143 GroupTypeInner { accepters:accepts, finalizers:finalizes }
144 });
145 };
146}
147attribute_parsers!(
148 pub(crate) static ATTRIBUTE_PARSERS = [
149 AlignParser,
151 BodyStabilityParser,
152 ConfusablesParser,
153 ConstStabilityParser,
154 MacroUseParser,
155 NakedParser,
156 StabilityParser,
157 UsedParser,
158 Combine<AllowConstFnUnstableParser>,
162 Combine<AllowInternalUnstableParser>,
163 Combine<ReprParser>,
164 Combine<TargetFeatureParser>,
165 Combine<UnstableFeatureBoundParser>,
166 Single<CoverageParser>,
170 Single<DeprecationParser>,
171 Single<DummyParser>,
172 Single<ExportNameParser>,
173 Single<IgnoreParser>,
174 Single<InlineParser>,
175 Single<LinkNameParser>,
176 Single<LinkOrdinalParser>,
177 Single<LinkSectionParser>,
178 Single<LinkageParser>,
179 Single<MustUseParser>,
180 Single<OptimizeParser>,
181 Single<PathAttributeParser>,
182 Single<ProcMacroDeriveParser>,
183 Single<RustcBuiltinMacroParser>,
184 Single<RustcForceInlineParser>,
185 Single<RustcLayoutScalarValidRangeEnd>,
186 Single<RustcLayoutScalarValidRangeStart>,
187 Single<RustcObjectLifetimeDefaultParser>,
188 Single<ShouldPanicParser>,
189 Single<SkipDuringMethodDispatchParser>,
190 Single<TransparencyParser>,
191 Single<WithoutArgs<AllowIncoherentImplParser>>,
192 Single<WithoutArgs<AllowInternalUnsafeParser>>,
193 Single<WithoutArgs<AsPtrParser>>,
194 Single<WithoutArgs<AutomaticallyDerivedParser>>,
195 Single<WithoutArgs<CoherenceIsCoreParser>>,
196 Single<WithoutArgs<CoinductiveParser>>,
197 Single<WithoutArgs<ColdParser>>,
198 Single<WithoutArgs<ConstContinueParser>>,
199 Single<WithoutArgs<ConstStabilityIndirectParser>>,
200 Single<WithoutArgs<ConstTraitParser>>,
201 Single<WithoutArgs<CoroutineParser>>,
202 Single<WithoutArgs<DenyExplicitImplParser>>,
203 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
204 Single<WithoutArgs<ExportStableParser>>,
205 Single<WithoutArgs<FfiConstParser>>,
206 Single<WithoutArgs<FfiPureParser>>,
207 Single<WithoutArgs<FundamentalParser>>,
208 Single<WithoutArgs<LoopMatchParser>>,
209 Single<WithoutArgs<MacroEscapeParser>>,
210 Single<WithoutArgs<MarkerParser>>,
211 Single<WithoutArgs<MayDangleParser>>,
212 Single<WithoutArgs<NoImplicitPreludeParser>>,
213 Single<WithoutArgs<NoMangleParser>>,
214 Single<WithoutArgs<NonExhaustiveParser>>,
215 Single<WithoutArgs<ParenSugarParser>>,
216 Single<WithoutArgs<PassByValueParser>>,
217 Single<WithoutArgs<PointeeParser>>,
218 Single<WithoutArgs<ProcMacroAttributeParser>>,
219 Single<WithoutArgs<ProcMacroParser>>,
220 Single<WithoutArgs<PubTransparentParser>>,
221 Single<WithoutArgs<SpecializationTraitParser>>,
222 Single<WithoutArgs<StdInternalSymbolParser>>,
223 Single<WithoutArgs<TrackCallerParser>>,
224 Single<WithoutArgs<TypeConstParser>>,
225 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
226 ];
228);
229
230mod private {
231 pub trait Sealed {}
232 impl Sealed for super::Early {}
233 impl Sealed for super::Late {}
234}
235
236#[allow(private_interfaces)]
238pub trait Stage: Sized + 'static + Sealed {
239 type Id: Copy;
240
241 fn parsers() -> &'static GroupType<Self>;
242
243 fn emit_err<'sess>(
244 &self,
245 sess: &'sess Session,
246 diag: impl for<'x> Diagnostic<'x>,
247 ) -> ErrorGuaranteed;
248
249 fn should_emit(&self) -> ShouldEmit;
250}
251
252#[allow(private_interfaces)]
254impl Stage for Early {
255 type Id = NodeId;
256
257 fn parsers() -> &'static GroupType<Self> {
258 &early::ATTRIBUTE_PARSERS
259 }
260 fn emit_err<'sess>(
261 &self,
262 sess: &'sess Session,
263 diag: impl for<'x> Diagnostic<'x>,
264 ) -> ErrorGuaranteed {
265 if self.emit_errors.should_emit() {
266 sess.dcx().emit_err(diag)
267 } else {
268 sess.dcx().create_err(diag).delay_as_bug()
269 }
270 }
271
272 fn should_emit(&self) -> ShouldEmit {
273 self.emit_errors
274 }
275}
276
277#[allow(private_interfaces)]
279impl Stage for Late {
280 type Id = HirId;
281
282 fn parsers() -> &'static GroupType<Self> {
283 &late::ATTRIBUTE_PARSERS
284 }
285 fn emit_err<'sess>(
286 &self,
287 tcx: &'sess Session,
288 diag: impl for<'x> Diagnostic<'x>,
289 ) -> ErrorGuaranteed {
290 tcx.dcx().emit_err(diag)
291 }
292
293 fn should_emit(&self) -> ShouldEmit {
294 ShouldEmit::ErrorsAndLints
295 }
296}
297
298pub struct Early {
300 pub emit_errors: ShouldEmit,
304}
305pub struct Late;
307
308pub struct AcceptContext<'f, 'sess, S: Stage> {
312 pub(crate) shared: SharedContext<'f, 'sess, S>,
313 pub(crate) attr_span: Span,
315
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 })
398 }
399
400 pub(crate) fn expected_integer_literal(&self, span: Span) -> 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::ExpectedIntegerLiteral,
407 })
408 }
409
410 pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
411 self.emit_err(AttributeParseError {
412 span,
413 attr_span: self.attr_span,
414 template: self.template.clone(),
415 attribute: self.attr_path.clone(),
416 reason: AttributeParseErrorReason::ExpectedList,
417 })
418 }
419
420 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
421 self.emit_err(AttributeParseError {
422 span: args_span,
423 attr_span: self.attr_span,
424 template: self.template.clone(),
425 attribute: self.attr_path.clone(),
426 reason: AttributeParseErrorReason::ExpectedNoArgs,
427 })
428 }
429
430 pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
432 self.emit_err(AttributeParseError {
433 span,
434 attr_span: self.attr_span,
435 template: self.template.clone(),
436 attribute: self.attr_path.clone(),
437 reason: AttributeParseErrorReason::ExpectedIdentifier,
438 })
439 }
440
441 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
444 self.emit_err(AttributeParseError {
445 span,
446 attr_span: self.attr_span,
447 template: self.template.clone(),
448 attribute: self.attr_path.clone(),
449 reason: AttributeParseErrorReason::ExpectedNameValue(name),
450 })
451 }
452
453 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
455 self.emit_err(AttributeParseError {
456 span,
457 attr_span: self.attr_span,
458 template: self.template.clone(),
459 attribute: self.attr_path.clone(),
460 reason: AttributeParseErrorReason::DuplicateKey(key),
461 })
462 }
463
464 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
467 self.emit_err(AttributeParseError {
468 span,
469 attr_span: self.attr_span,
470 template: self.template.clone(),
471 attribute: self.attr_path.clone(),
472 reason: AttributeParseErrorReason::UnexpectedLiteral,
473 })
474 }
475
476 pub(crate) fn expected_single_argument(&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::ExpectedSingleArgument,
483 })
484 }
485
486 pub(crate) fn expected_at_least_one_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::ExpectedAtLeastOneArgument,
493 })
494 }
495
496 pub(crate) fn expected_specific_argument(
497 &self,
498 span: Span,
499 possibilities: Vec<&'static str>,
500 ) -> ErrorGuaranteed {
501 self.emit_err(AttributeParseError {
502 span,
503 attr_span: self.attr_span,
504 template: self.template.clone(),
505 attribute: self.attr_path.clone(),
506 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
507 possibilities,
508 strings: false,
509 list: false,
510 },
511 })
512 }
513
514 pub(crate) fn expected_specific_argument_and_list(
515 &self,
516 span: Span,
517 possibilities: Vec<&'static str>,
518 ) -> ErrorGuaranteed {
519 self.emit_err(AttributeParseError {
520 span,
521 attr_span: self.attr_span,
522 template: self.template.clone(),
523 attribute: self.attr_path.clone(),
524 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
525 possibilities,
526 strings: false,
527 list: true,
528 },
529 })
530 }
531
532 pub(crate) fn expected_specific_argument_strings(
533 &self,
534 span: Span,
535 possibilities: Vec<&'static str>,
536 ) -> ErrorGuaranteed {
537 self.emit_err(AttributeParseError {
538 span,
539 attr_span: self.attr_span,
540 template: self.template.clone(),
541 attribute: self.attr_path.clone(),
542 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
543 possibilities,
544 strings: true,
545 list: false,
546 },
547 })
548 }
549
550 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
551 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
552 }
553}
554
555impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
556 type Target = SharedContext<'f, 'sess, S>;
557
558 fn deref(&self) -> &Self::Target {
559 &self.shared
560 }
561}
562
563impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
564 fn deref_mut(&mut self) -> &mut Self::Target {
565 &mut self.shared
566 }
567}
568
569pub struct SharedContext<'p, 'sess, S: Stage> {
574 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
577 pub(crate) target_span: Span,
579 pub(crate) target_id: S::Id,
581
582 emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
583}
584
585pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
590 pub(crate) shared: SharedContext<'p, 'sess, S>,
591
592 pub(crate) all_attrs: &'p [PathParser<'p>],
599}
600
601impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
602 type Target = SharedContext<'p, 'sess, S>;
603
604 fn deref(&self) -> &Self::Target {
605 &self.shared
606 }
607}
608
609impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
610 fn deref_mut(&mut self) -> &mut Self::Target {
611 &mut self.shared
612 }
613}
614
615impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
616 type Target = AttributeParser<'sess, S>;
617
618 fn deref(&self) -> &Self::Target {
619 self.cx
620 }
621}
622
623impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
624 fn deref_mut(&mut self) -> &mut Self::Target {
625 self.cx
626 }
627}
628
629#[derive(PartialEq, Clone, Copy, Debug)]
630pub enum OmitDoc {
631 Lower,
632 Skip,
633}
634
635#[derive(Copy, Clone)]
636pub enum ShouldEmit {
637 ErrorsAndLints,
640 Nothing,
643}
644
645impl ShouldEmit {
646 pub fn should_emit(&self) -> bool {
647 match self {
648 ShouldEmit::ErrorsAndLints => true,
649 ShouldEmit::Nothing => false,
650 }
651 }
652}
653
654#[derive(Debug)]
655pub(crate) enum AllowedTargets {
656 AllowList(&'static [MaybeWarn]),
657 AllowListWarnRest(&'static [MaybeWarn]),
658}
659
660pub(crate) enum AllowedResult {
661 Allowed,
662 Warn,
663 Error,
664}
665
666impl AllowedTargets {
667 pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult {
668 match self {
669 AllowedTargets::AllowList(list) => {
670 if list.contains(&Allow(target)) {
671 AllowedResult::Allowed
672 } else if list.contains(&Warn(target)) {
673 AllowedResult::Warn
674 } else {
675 AllowedResult::Error
676 }
677 }
678 AllowedTargets::AllowListWarnRest(list) => {
679 if list.contains(&Allow(target)) {
680 AllowedResult::Allowed
681 } else if list.contains(&Error(target)) {
682 AllowedResult::Error
683 } else {
684 AllowedResult::Warn
685 }
686 }
687 }
688 }
689
690 pub(crate) fn allowed_targets(&self) -> Vec<Target> {
691 match self {
692 AllowedTargets::AllowList(list) => list,
693 AllowedTargets::AllowListWarnRest(list) => list,
694 }
695 .iter()
696 .filter_map(|target| match target {
697 Allow(target) => Some(*target),
698 Warn(_) => None,
699 Error(_) => None,
700 })
701 .collect()
702 }
703}
704
705#[derive(Debug, Eq, PartialEq)]
706pub(crate) enum MaybeWarn {
707 Allow(Target),
708 Warn(Target),
709 Error(Target),
710}
711
712pub struct AttributeParser<'sess, S: Stage = Late> {
715 pub(crate) tools: Vec<Symbol>,
716 features: Option<&'sess Features>,
717 sess: &'sess Session,
718 stage: S,
719
720 parse_only: Option<Symbol>,
724}
725
726impl<'sess> AttributeParser<'sess, Early> {
727 pub fn parse_limited(
742 sess: &'sess Session,
743 attrs: &[ast::Attribute],
744 sym: Symbol,
745 target_span: Span,
746 target_node_id: NodeId,
747 features: Option<&'sess Features>,
748 ) -> Option<Attribute> {
749 let mut p = Self {
750 features,
751 tools: Vec::new(),
752 parse_only: Some(sym),
753 sess,
754 stage: Early { emit_errors: ShouldEmit::Nothing },
755 };
756 let mut parsed = p.parse_attribute_list(
757 attrs,
758 target_span,
759 target_node_id,
760 Target::Crate, OmitDoc::Skip,
762 std::convert::identity,
763 |_lint| {
764 panic!("can't emit lints here for now (nothing uses this atm)");
765 },
766 );
767 assert!(parsed.len() <= 1);
768
769 parsed.pop()
770 }
771
772 pub fn parse_single<T>(
773 sess: &'sess Session,
774 attr: &ast::Attribute,
775 target_span: Span,
776 target_node_id: NodeId,
777 features: Option<&'sess Features>,
778 emit_errors: ShouldEmit,
779 parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
780 template: &AttributeTemplate,
781 ) -> T {
782 let mut parser = Self {
783 features,
784 tools: Vec::new(),
785 parse_only: None,
786 sess,
787 stage: Early { emit_errors },
788 };
789 let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
790 panic!("parse_single called on a doc attr")
791 };
792 let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
793 let path = meta_parser.path();
794 let args = meta_parser.args();
795 let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
796 shared: SharedContext {
797 cx: &mut parser,
798 target_span,
799 target_id: target_node_id,
800 emit_lint: &mut |_lint| {
801 panic!("can't emit lints here for now (nothing uses this atm)");
802 },
803 },
804 attr_span: attr.span,
805 template,
806 attr_path: path.get_attribute_path(),
807 };
808 parse_fn(&mut cx, args)
809 }
810}
811
812impl<'sess, S: Stage> AttributeParser<'sess, S> {
813 pub fn new(
814 sess: &'sess Session,
815 features: &'sess Features,
816 tools: Vec<Symbol>,
817 stage: S,
818 ) -> Self {
819 Self { features: Some(features), tools, parse_only: None, sess, stage }
820 }
821
822 pub(crate) fn sess(&self) -> &'sess Session {
823 &self.sess
824 }
825
826 pub(crate) fn features(&self) -> &'sess Features {
827 self.features.expect("features not available at this point in the compiler")
828 }
829
830 pub(crate) fn features_option(&self) -> Option<&'sess Features> {
831 self.features
832 }
833
834 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
835 self.sess().dcx()
836 }
837
838 pub fn parse_attribute_list(
843 &mut self,
844 attrs: &[ast::Attribute],
845 target_span: Span,
846 target_id: S::Id,
847 target: Target,
848 omit_doc: OmitDoc,
849
850 lower_span: impl Copy + Fn(Span) -> Span,
851 mut emit_lint: impl FnMut(AttributeLint<S::Id>),
852 ) -> Vec<Attribute> {
853 let mut attributes = Vec::new();
854 let mut attr_paths = Vec::new();
855
856 for attr in attrs {
857 if let Some(expected) = self.parse_only {
859 if !attr.has_name(expected) {
860 continue;
861 }
862 }
863
864 if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
870 continue;
871 }
872
873 match &attr.kind {
874 ast::AttrKind::DocComment(comment_kind, symbol) => {
875 if omit_doc == OmitDoc::Skip {
876 continue;
877 }
878
879 attributes.push(Attribute::Parsed(AttributeKind::DocComment {
880 style: attr.style,
881 kind: *comment_kind,
882 span: lower_span(attr.span),
883 comment: *symbol,
884 }))
885 }
886 ast::AttrKind::Normal(n) => {
898 attr_paths.push(PathParser::Ast(&n.item.path));
899
900 let parser = MetaItemParser::from_attr(n, self.dcx());
901 let path = parser.path();
902 let args = parser.args();
903 let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
904
905 if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
906 for accept in accepts {
907 let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
908 shared: SharedContext {
909 cx: self,
910 target_span,
911 target_id,
912 emit_lint: &mut emit_lint,
913 },
914 attr_span: lower_span(attr.span),
915 template: &accept.template,
916 attr_path: path.get_attribute_path(),
917 };
918
919 (accept.accept_fn)(&mut cx, args);
920
921 if self.stage.should_emit().should_emit() {
922 match accept.allowed_targets.is_allowed(target) {
923 AllowedResult::Allowed => {}
924 AllowedResult::Warn => {
925 let allowed_targets =
926 accept.allowed_targets.allowed_targets();
927 let (applied, only) = allowed_targets_applied(
928 allowed_targets,
929 target,
930 self.features,
931 );
932 emit_lint(AttributeLint {
933 id: target_id,
934 span: attr.span,
935 kind: AttributeLintKind::InvalidTarget {
936 name: parts[0],
937 target,
938 only: if only { "only " } else { "" },
939 applied,
940 },
941 });
942 }
943 AllowedResult::Error => {
944 let allowed_targets =
945 accept.allowed_targets.allowed_targets();
946 let (applied, only) = allowed_targets_applied(
947 allowed_targets,
948 target,
949 self.features,
950 );
951 self.dcx().emit_err(InvalidTarget {
952 span: attr.span,
953 name: parts[0],
954 target: target.plural_name(),
955 only: if only { "only " } else { "" },
956 applied,
957 });
958 }
959 }
960 }
961 }
962 } else {
963 attributes.push(Attribute::Unparsed(Box::new(AttrItem {
979 path: AttrPath::from_ast(&n.item.path),
980 args: self.lower_attr_args(&n.item.args, lower_span),
981 id: HashIgnoredAttrId { attr_id: attr.id },
982 style: attr.style,
983 span: lower_span(attr.span),
984 })));
985 }
986 }
987 }
988 }
989
990 let mut parsed_attributes = Vec::new();
991 for f in &S::parsers().finalizers {
992 if let Some(attr) = f(&mut FinalizeContext {
993 shared: SharedContext {
994 cx: self,
995 target_span,
996 target_id,
997 emit_lint: &mut emit_lint,
998 },
999 all_attrs: &attr_paths,
1000 }) {
1001 parsed_attributes.push(Attribute::Parsed(attr));
1002 }
1003 }
1004
1005 attributes.extend(parsed_attributes);
1006
1007 attributes
1008 }
1009
1010 pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
1012 Late::parsers().accepters.contains_key(path)
1013 }
1014
1015 fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
1016 match args {
1017 ast::AttrArgs::Empty => AttrArgs::Empty,
1018 ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
1019 ast::AttrArgs::Eq { eq_span, expr } => {
1023 let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
1026 && let Ok(lit) =
1027 ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
1028 {
1029 lit
1030 } else {
1031 let guar = self.dcx().span_delayed_bug(
1032 args.span().unwrap_or(DUMMY_SP),
1033 "expr in place where literal is expected (builtin attr parsing)",
1034 );
1035 ast::MetaItemLit {
1036 symbol: sym::dummy,
1037 suffix: None,
1038 kind: ast::LitKind::Err(guar),
1039 span: DUMMY_SP,
1040 }
1041 };
1042 AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
1043 }
1044 }
1045 }
1046}
1047
1048pub(crate) fn allowed_targets_applied(
1051 mut allowed_targets: Vec<Target>,
1052 target: Target,
1053 features: Option<&Features>,
1054) -> (String, bool) {
1055 if let Some(features) = features {
1057 if !features.fn_delegation() {
1058 allowed_targets.retain(|t| !matches!(t, Target::Delegation { .. }));
1059 }
1060 if !features.stmt_expr_attributes() {
1061 allowed_targets.retain(|t| !matches!(t, Target::Expression | Target::Statement));
1062 }
1063 }
1064
1065 const FUNCTION_LIKE: &[Target] = &[
1069 Target::Fn,
1070 Target::Closure,
1071 Target::ForeignFn,
1072 Target::Method(MethodKind::Inherent),
1073 Target::Method(MethodKind::Trait { body: false }),
1074 Target::Method(MethodKind::Trait { body: true }),
1075 Target::Method(MethodKind::TraitImpl),
1076 ];
1077 const METHOD_LIKE: &[Target] = &[
1078 Target::Method(MethodKind::Inherent),
1079 Target::Method(MethodKind::Trait { body: false }),
1080 Target::Method(MethodKind::Trait { body: true }),
1081 Target::Method(MethodKind::TraitImpl),
1082 ];
1083 const IMPL_LIKE: &[Target] =
1084 &[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }];
1085 const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum];
1086
1087 let mut added_fake_targets = Vec::new();
1088 filter_targets(
1089 &mut allowed_targets,
1090 FUNCTION_LIKE,
1091 "functions",
1092 target,
1093 &mut added_fake_targets,
1094 );
1095 filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets);
1096 filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets);
1097 filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets);
1098
1099 (
1101 added_fake_targets
1102 .iter()
1103 .copied()
1104 .chain(allowed_targets.iter().map(|t| t.plural_name()))
1105 .join(", "),
1106 allowed_targets.len() + added_fake_targets.len() == 1,
1107 )
1108}
1109
1110fn filter_targets(
1111 allowed_targets: &mut Vec<Target>,
1112 target_group: &'static [Target],
1113 target_group_name: &'static str,
1114 target: Target,
1115 added_fake_targets: &mut Vec<&'static str>,
1116) {
1117 if target_group.contains(&target) {
1118 return;
1119 }
1120 if allowed_targets.iter().filter(|at| target_group.contains(at)).count() < 2 {
1121 return;
1122 }
1123 allowed_targets.retain(|t| !target_group.contains(t));
1124 added_fake_targets.push(target_group_name);
1125}
1126
1127pub(crate) const ALL_TARGETS: &'static [MaybeWarn] = &[
1132 Allow(Target::ExternCrate),
1133 Allow(Target::Use),
1134 Allow(Target::Static),
1135 Allow(Target::Const),
1136 Allow(Target::Fn),
1137 Allow(Target::Closure),
1138 Allow(Target::Mod),
1139 Allow(Target::ForeignMod),
1140 Allow(Target::GlobalAsm),
1141 Allow(Target::TyAlias),
1142 Allow(Target::Enum),
1143 Allow(Target::Variant),
1144 Allow(Target::Struct),
1145 Allow(Target::Field),
1146 Allow(Target::Union),
1147 Allow(Target::Trait),
1148 Allow(Target::TraitAlias),
1149 Allow(Target::Impl { of_trait: false }),
1150 Allow(Target::Impl { of_trait: true }),
1151 Allow(Target::Expression),
1152 Allow(Target::Statement),
1153 Allow(Target::Arm),
1154 Allow(Target::AssocConst),
1155 Allow(Target::Method(MethodKind::Inherent)),
1156 Allow(Target::Method(MethodKind::Trait { body: false })),
1157 Allow(Target::Method(MethodKind::Trait { body: true })),
1158 Allow(Target::Method(MethodKind::TraitImpl)),
1159 Allow(Target::AssocTy),
1160 Allow(Target::ForeignFn),
1161 Allow(Target::ForeignStatic),
1162 Allow(Target::ForeignTy),
1163 Allow(Target::MacroDef),
1164 Allow(Target::Param),
1165 Allow(Target::PatField),
1166 Allow(Target::ExprField),
1167 Allow(Target::WherePredicate),
1168 Allow(Target::MacroCall),
1169 Allow(Target::Crate),
1170 Allow(Target::Delegation { mac: false }),
1171 Allow(Target::Delegation { mac: true }),
1172];
1173
1174pub(crate) fn parse_single_integer<S: Stage>(
1181 cx: &mut AcceptContext<'_, '_, S>,
1182 args: &ArgParser<'_>,
1183) -> Option<u128> {
1184 let Some(list) = args.list() else {
1185 cx.expected_list(cx.attr_span);
1186 return None;
1187 };
1188 let Some(single) = list.single() else {
1189 cx.expected_single_argument(list.span);
1190 return None;
1191 };
1192 let Some(lit) = single.lit() else {
1193 cx.expected_integer_literal(single.span());
1194 return None;
1195 };
1196 let LitKind::Int(num, _ty) = lit.kind else {
1197 cx.expected_integer_literal(single.span());
1198 return None;
1199 };
1200 Some(num.0)
1201}