1use std::cell::RefCell;
2use std::collections::BTreeMap;
3use std::ops::{Deref, DerefMut};
4use std::sync::LazyLock;
5
6use private::Sealed;
7use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId};
8use rustc_attr_data_structures::AttributeKind;
9use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind};
10use rustc_errors::{DiagCtxtHandle, Diagnostic};
11use rustc_feature::{AttributeTemplate, Features};
12use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId};
13use rustc_session::Session;
14use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
15
16use crate::attributes::allow_unstable::{
17 AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
18};
19use crate::attributes::codegen_attrs::{
20 ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser,
21 OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser,
22 UsedParser,
23};
24use crate::attributes::confusables::ConfusablesParser;
25use crate::attributes::deprecation::DeprecationParser;
26use crate::attributes::dummy::DummyParser;
27use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
28use crate::attributes::link_attrs::{
29 ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
30 LinkSectionParser, StdInternalSymbolParser,
31};
32use crate::attributes::lint_helpers::{
33 AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
34};
35use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
36use crate::attributes::must_use::MustUseParser;
37use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
38use crate::attributes::non_exhaustive::NonExhaustiveParser;
39use crate::attributes::path::PathParser as PathAttributeParser;
40use crate::attributes::repr::{AlignParser, ReprParser};
41use crate::attributes::rustc_internal::{
42 RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
43 RustcObjectLifetimeDefaultParser,
44};
45use crate::attributes::semantics::MayDangleParser;
46use crate::attributes::stability::{
47 BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
48};
49use crate::attributes::test_attrs::IgnoreParser;
50use crate::attributes::traits::{
51 AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
52 DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
53 ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
54 TypeConstParser, UnsafeSpecializationMarkerParser,
55};
56use crate::attributes::transparency::TransparencyParser;
57use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
58use crate::parser::{ArgParser, MetaItemParser, PathParser};
59use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
60
61macro_rules! group_type {
62 ($stage: ty) => {
63 LazyLock<(
64 BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>,
65 Vec<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $stage>) -> Option<AttributeKind>>>
66 )>
67 };
68}
69
70macro_rules! attribute_parsers {
71 (
72 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
73 ) => {
74 mod early {
75 use super::*;
76 type Combine<T> = super::Combine<T, Early>;
77 type Single<T> = super::Single<T, Early>;
78 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
79
80 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
81 }
82 mod late {
83 use super::*;
84 type Combine<T> = super::Combine<T, Late>;
85 type Single<T> = super::Single<T, Late>;
86 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
87
88 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
89 }
90 };
91 (
92 @[$ty: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
93 ) => {
94 pub(crate) static $name: group_type!($ty) = LazyLock::new(|| {
95 let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new();
96 let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $ty>) -> Option<AttributeKind>>>::new();
97 $(
98 {
99 thread_local! {
100 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
101 };
102
103 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
104 accepts.entry(*path).or_default().push((*template, Box::new(|cx, args| {
105 STATE_OBJECT.with_borrow_mut(|s| {
106 accept_fn(s, cx, args)
107 })
108 })));
109 }
110
111 finalizes.push(Box::new(|cx| {
112 let state = STATE_OBJECT.take();
113 state.finalize(cx)
114 }));
115 }
116 )*
117
118 (accepts, finalizes)
119 });
120 };
121}
122attribute_parsers!(
123 pub(crate) static ATTRIBUTE_PARSERS = [
124 AlignParser,
126 BodyStabilityParser,
127 ConfusablesParser,
128 ConstStabilityParser,
129 NakedParser,
130 StabilityParser,
131 UsedParser,
132 Combine<AllowConstFnUnstableParser>,
136 Combine<AllowInternalUnstableParser>,
137 Combine<ReprParser>,
138 Combine<TargetFeatureParser>,
139 Combine<UnstableFeatureBoundParser>,
140 Single<CoverageParser>,
144 Single<DeprecationParser>,
145 Single<DummyParser>,
146 Single<ExportNameParser>,
147 Single<IgnoreParser>,
148 Single<InlineParser>,
149 Single<LinkNameParser>,
150 Single<LinkOrdinalParser>,
151 Single<LinkSectionParser>,
152 Single<MustUseParser>,
153 Single<OptimizeParser>,
154 Single<PathAttributeParser>,
155 Single<RustcForceInlineParser>,
156 Single<RustcLayoutScalarValidRangeEnd>,
157 Single<RustcLayoutScalarValidRangeStart>,
158 Single<RustcObjectLifetimeDefaultParser>,
159 Single<SkipDuringMethodDispatchParser>,
160 Single<TransparencyParser>,
161 Single<WithoutArgs<AllowIncoherentImplParser>>,
162 Single<WithoutArgs<AsPtrParser>>,
163 Single<WithoutArgs<AutomaticallyDerivedParser>>,
164 Single<WithoutArgs<CoherenceIsCoreParser>>,
165 Single<WithoutArgs<CoinductiveParser>>,
166 Single<WithoutArgs<ColdParser>>,
167 Single<WithoutArgs<ConstContinueParser>>,
168 Single<WithoutArgs<ConstStabilityIndirectParser>>,
169 Single<WithoutArgs<ConstTraitParser>>,
170 Single<WithoutArgs<DenyExplicitImplParser>>,
171 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
172 Single<WithoutArgs<ExportStableParser>>,
173 Single<WithoutArgs<FfiConstParser>>,
174 Single<WithoutArgs<FfiPureParser>>,
175 Single<WithoutArgs<FundamentalParser>>,
176 Single<WithoutArgs<LoopMatchParser>>,
177 Single<WithoutArgs<MarkerParser>>,
178 Single<WithoutArgs<MayDangleParser>>,
179 Single<WithoutArgs<NoImplicitPreludeParser>>,
180 Single<WithoutArgs<NoMangleParser>>,
181 Single<WithoutArgs<NonExhaustiveParser>>,
182 Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>,
183 Single<WithoutArgs<ParenSugarParser>>,
184 Single<WithoutArgs<PassByValueParser>>,
185 Single<WithoutArgs<PointeeParser>>,
186 Single<WithoutArgs<PubTransparentParser>>,
187 Single<WithoutArgs<SpecializationTraitParser>>,
188 Single<WithoutArgs<StdInternalSymbolParser>>,
189 Single<WithoutArgs<TrackCallerParser>>,
190 Single<WithoutArgs<TypeConstParser>>,
191 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
192 ];
194);
195
196mod private {
197 pub trait Sealed {}
198 impl Sealed for super::Early {}
199 impl Sealed for super::Late {}
200}
201
202#[allow(private_interfaces)]
204pub trait Stage: Sized + 'static + Sealed {
205 type Id: Copy;
206 const SHOULD_EMIT_LINTS: bool;
207
208 fn parsers() -> &'static group_type!(Self);
209
210 fn emit_err<'sess>(
211 &self,
212 sess: &'sess Session,
213 diag: impl for<'x> Diagnostic<'x>,
214 ) -> ErrorGuaranteed;
215}
216
217#[allow(private_interfaces)]
219impl Stage for Early {
220 type Id = NodeId;
221 const SHOULD_EMIT_LINTS: bool = false;
222
223 fn parsers() -> &'static group_type!(Self) {
224 &early::ATTRIBUTE_PARSERS
225 }
226 fn emit_err<'sess>(
227 &self,
228 sess: &'sess Session,
229 diag: impl for<'x> Diagnostic<'x>,
230 ) -> ErrorGuaranteed {
231 if self.emit_errors.should_emit() {
232 sess.dcx().emit_err(diag)
233 } else {
234 sess.dcx().create_err(diag).delay_as_bug()
235 }
236 }
237}
238
239#[allow(private_interfaces)]
241impl Stage for Late {
242 type Id = HirId;
243 const SHOULD_EMIT_LINTS: bool = true;
244
245 fn parsers() -> &'static group_type!(Self) {
246 &late::ATTRIBUTE_PARSERS
247 }
248 fn emit_err<'sess>(
249 &self,
250 tcx: &'sess Session,
251 diag: impl for<'x> Diagnostic<'x>,
252 ) -> ErrorGuaranteed {
253 tcx.dcx().emit_err(diag)
254 }
255}
256
257pub struct Early {
259 pub emit_errors: ShouldEmit,
263}
264pub struct Late;
266
267pub struct AcceptContext<'f, 'sess, S: Stage> {
271 pub(crate) shared: SharedContext<'f, 'sess, S>,
272 pub(crate) attr_span: Span,
274
275 pub(crate) template: &'f AttributeTemplate,
279
280 pub(crate) attr_path: AttrPath,
282}
283
284impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
285 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
286 self.stage.emit_err(&self.sess, diag)
287 }
288
289 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
293 if !S::SHOULD_EMIT_LINTS {
294 return;
295 }
296 let id = self.target_id;
297 (self.emit_lint)(AttributeLint { id, span, kind: lint });
298 }
299
300 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
301 self.emit_lint(
302 AttributeLintKind::UnusedDuplicate {
303 this: unused_span,
304 other: used_span,
305 warning: false,
306 },
307 unused_span,
308 )
309 }
310
311 pub(crate) fn warn_unused_duplicate_future_error(
312 &mut self,
313 used_span: Span,
314 unused_span: Span,
315 ) {
316 self.emit_lint(
317 AttributeLintKind::UnusedDuplicate {
318 this: unused_span,
319 other: used_span,
320 warning: true,
321 },
322 unused_span,
323 )
324 }
325}
326
327impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
328 pub(crate) fn unknown_key(
329 &self,
330 span: Span,
331 found: String,
332 options: &'static [&'static str],
333 ) -> ErrorGuaranteed {
334 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
335 }
336
337 pub(crate) fn expected_string_literal(
342 &self,
343 span: Span,
344 actual_literal: Option<&MetaItemLit>,
345 ) -> ErrorGuaranteed {
346 self.emit_err(AttributeParseError {
347 span,
348 attr_span: self.attr_span,
349 template: self.template.clone(),
350 attribute: self.attr_path.clone(),
351 reason: AttributeParseErrorReason::ExpectedStringLiteral {
352 byte_string: actual_literal.and_then(|i| {
353 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
354 }),
355 },
356 })
357 }
358
359 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
360 self.emit_err(AttributeParseError {
361 span,
362 attr_span: self.attr_span,
363 template: self.template.clone(),
364 attribute: self.attr_path.clone(),
365 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
366 })
367 }
368
369 pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
370 self.emit_err(AttributeParseError {
371 span,
372 attr_span: self.attr_span,
373 template: self.template.clone(),
374 attribute: self.attr_path.clone(),
375 reason: AttributeParseErrorReason::ExpectedList,
376 })
377 }
378
379 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
380 self.emit_err(AttributeParseError {
381 span: args_span,
382 attr_span: self.attr_span,
383 template: self.template.clone(),
384 attribute: self.attr_path.clone(),
385 reason: AttributeParseErrorReason::ExpectedNoArgs,
386 })
387 }
388
389 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
392 self.emit_err(AttributeParseError {
393 span,
394 attr_span: self.attr_span,
395 template: self.template.clone(),
396 attribute: self.attr_path.clone(),
397 reason: AttributeParseErrorReason::ExpectedNameValue(name),
398 })
399 }
400
401 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
403 self.emit_err(AttributeParseError {
404 span,
405 attr_span: self.attr_span,
406 template: self.template.clone(),
407 attribute: self.attr_path.clone(),
408 reason: AttributeParseErrorReason::DuplicateKey(key),
409 })
410 }
411
412 pub(crate) fn unexpected_literal(&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::UnexpectedLiteral,
421 })
422 }
423
424 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
425 self.emit_err(AttributeParseError {
426 span,
427 attr_span: self.attr_span,
428 template: self.template.clone(),
429 attribute: self.attr_path.clone(),
430 reason: AttributeParseErrorReason::ExpectedSingleArgument,
431 })
432 }
433
434 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
435 self.emit_err(AttributeParseError {
436 span,
437 attr_span: self.attr_span,
438 template: self.template.clone(),
439 attribute: self.attr_path.clone(),
440 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
441 })
442 }
443
444 pub(crate) fn expected_specific_argument(
445 &self,
446 span: Span,
447 possibilities: Vec<&'static str>,
448 ) -> 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::ExpectedSpecificArgument {
455 possibilities,
456 strings: false,
457 list: false,
458 },
459 })
460 }
461
462 pub(crate) fn expected_specific_argument_and_list(
463 &self,
464 span: Span,
465 possibilities: Vec<&'static str>,
466 ) -> 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::ExpectedSpecificArgument {
473 possibilities,
474 strings: false,
475 list: true,
476 },
477 })
478 }
479
480 pub(crate) fn expected_specific_argument_strings(
481 &self,
482 span: Span,
483 possibilities: Vec<&'static str>,
484 ) -> 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::ExpectedSpecificArgument {
491 possibilities,
492 strings: true,
493 list: false,
494 },
495 })
496 }
497
498 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
499 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
500 }
501}
502
503impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
504 type Target = SharedContext<'f, 'sess, S>;
505
506 fn deref(&self) -> &Self::Target {
507 &self.shared
508 }
509}
510
511impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
512 fn deref_mut(&mut self) -> &mut Self::Target {
513 &mut self.shared
514 }
515}
516
517pub struct SharedContext<'p, 'sess, S: Stage> {
522 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
525 pub(crate) target_span: Span,
527 pub(crate) target_id: S::Id,
529
530 emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
531}
532
533pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
538 pub(crate) shared: SharedContext<'p, 'sess, S>,
539
540 pub(crate) all_attrs: &'p [PathParser<'p>],
547}
548
549impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
550 type Target = SharedContext<'p, 'sess, S>;
551
552 fn deref(&self) -> &Self::Target {
553 &self.shared
554 }
555}
556
557impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
558 fn deref_mut(&mut self) -> &mut Self::Target {
559 &mut self.shared
560 }
561}
562
563impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
564 type Target = AttributeParser<'sess, S>;
565
566 fn deref(&self) -> &Self::Target {
567 self.cx
568 }
569}
570
571impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
572 fn deref_mut(&mut self) -> &mut Self::Target {
573 self.cx
574 }
575}
576
577#[derive(PartialEq, Clone, Copy, Debug)]
578pub enum OmitDoc {
579 Lower,
580 Skip,
581}
582
583#[derive(Copy, Clone)]
584pub enum ShouldEmit {
585 ErrorsAndLints,
588 Nothing,
591}
592
593impl ShouldEmit {
594 pub fn should_emit(&self) -> bool {
595 match self {
596 ShouldEmit::ErrorsAndLints => true,
597 ShouldEmit::Nothing => false,
598 }
599 }
600}
601
602pub struct AttributeParser<'sess, S: Stage = Late> {
605 pub(crate) tools: Vec<Symbol>,
606 features: Option<&'sess Features>,
607 sess: &'sess Session,
608 stage: S,
609
610 parse_only: Option<Symbol>,
614}
615
616impl<'sess> AttributeParser<'sess, Early> {
617 pub fn parse_limited(
632 sess: &'sess Session,
633 attrs: &[ast::Attribute],
634 sym: Symbol,
635 target_span: Span,
636 target_node_id: NodeId,
637 features: Option<&'sess Features>,
638 ) -> Option<Attribute> {
639 let mut p = Self {
640 features,
641 tools: Vec::new(),
642 parse_only: Some(sym),
643 sess,
644 stage: Early { emit_errors: ShouldEmit::Nothing },
645 };
646 let mut parsed = p.parse_attribute_list(
647 attrs,
648 target_span,
649 target_node_id,
650 OmitDoc::Skip,
651 std::convert::identity,
652 |_lint| {
653 panic!("can't emit lints here for now (nothing uses this atm)");
654 },
655 );
656 assert!(parsed.len() <= 1);
657
658 parsed.pop()
659 }
660
661 pub fn parse_single<T>(
662 sess: &'sess Session,
663 attr: &ast::Attribute,
664 target_span: Span,
665 target_node_id: NodeId,
666 features: Option<&'sess Features>,
667 emit_errors: ShouldEmit,
668 parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
669 template: &AttributeTemplate,
670 ) -> T {
671 let mut parser = Self {
672 features,
673 tools: Vec::new(),
674 parse_only: None,
675 sess,
676 stage: Early { emit_errors },
677 };
678 let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
679 panic!("parse_single called on a doc attr")
680 };
681 let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
682 let path = meta_parser.path();
683 let args = meta_parser.args();
684 let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
685 shared: SharedContext {
686 cx: &mut parser,
687 target_span,
688 target_id: target_node_id,
689 emit_lint: &mut |_lint| {
690 panic!("can't emit lints here for now (nothing uses this atm)");
691 },
692 },
693 attr_span: attr.span,
694 template,
695 attr_path: path.get_attribute_path(),
696 };
697 parse_fn(&mut cx, args)
698 }
699}
700
701impl<'sess, S: Stage> AttributeParser<'sess, S> {
702 pub fn new(
703 sess: &'sess Session,
704 features: &'sess Features,
705 tools: Vec<Symbol>,
706 stage: S,
707 ) -> Self {
708 Self { features: Some(features), tools, parse_only: None, sess, stage }
709 }
710
711 pub(crate) fn sess(&self) -> &'sess Session {
712 &self.sess
713 }
714
715 pub(crate) fn features(&self) -> &'sess Features {
716 self.features.expect("features not available at this point in the compiler")
717 }
718
719 pub(crate) fn features_option(&self) -> Option<&'sess Features> {
720 self.features
721 }
722
723 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
724 self.sess().dcx()
725 }
726
727 pub fn parse_attribute_list(
732 &mut self,
733 attrs: &[ast::Attribute],
734 target_span: Span,
735 target_id: S::Id,
736 omit_doc: OmitDoc,
737
738 lower_span: impl Copy + Fn(Span) -> Span,
739 mut emit_lint: impl FnMut(AttributeLint<S::Id>),
740 ) -> Vec<Attribute> {
741 let mut attributes = Vec::new();
742 let mut attr_paths = Vec::new();
743
744 for attr in attrs {
745 if let Some(expected) = self.parse_only {
747 if !attr.has_name(expected) {
748 continue;
749 }
750 }
751
752 if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
758 continue;
759 }
760
761 match &attr.kind {
762 ast::AttrKind::DocComment(comment_kind, symbol) => {
763 if omit_doc == OmitDoc::Skip {
764 continue;
765 }
766
767 attributes.push(Attribute::Parsed(AttributeKind::DocComment {
768 style: attr.style,
769 kind: *comment_kind,
770 span: lower_span(attr.span),
771 comment: *symbol,
772 }))
773 }
774 ast::AttrKind::Normal(n) => {
786 attr_paths.push(PathParser::Ast(&n.item.path));
787
788 let parser = MetaItemParser::from_attr(n, self.dcx());
789 let path = parser.path();
790 let args = parser.args();
791 let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
792
793 if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
794 for (template, accept) in accepts {
795 let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
796 shared: SharedContext {
797 cx: self,
798 target_span,
799 target_id,
800 emit_lint: &mut emit_lint,
801 },
802 attr_span: lower_span(attr.span),
803 template,
804 attr_path: path.get_attribute_path(),
805 };
806
807 accept(&mut cx, args)
808 }
809 } else {
810 attributes.push(Attribute::Unparsed(Box::new(AttrItem {
826 path: AttrPath::from_ast(&n.item.path),
827 args: self.lower_attr_args(&n.item.args, lower_span),
828 id: HashIgnoredAttrId { attr_id: attr.id },
829 style: attr.style,
830 span: lower_span(attr.span),
831 })));
832 }
833 }
834 }
835 }
836
837 let mut parsed_attributes = Vec::new();
838 for f in &S::parsers().1 {
839 if let Some(attr) = f(&mut FinalizeContext {
840 shared: SharedContext {
841 cx: self,
842 target_span,
843 target_id,
844 emit_lint: &mut emit_lint,
845 },
846 all_attrs: &attr_paths,
847 }) {
848 parsed_attributes.push(Attribute::Parsed(attr));
849 }
850 }
851
852 attributes.extend(parsed_attributes);
853
854 attributes
855 }
856
857 pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
859 Late::parsers().0.contains_key(path)
860 }
861
862 fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
863 match args {
864 ast::AttrArgs::Empty => AttrArgs::Empty,
865 ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
866 ast::AttrArgs::Eq { eq_span, expr } => {
870 let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
873 && let Ok(lit) =
874 ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
875 {
876 lit
877 } else {
878 let guar = self.dcx().span_delayed_bug(
879 args.span().unwrap_or(DUMMY_SP),
880 "expr in place where literal is expected (builtin attr parsing)",
881 );
882 ast::MetaItemLit {
883 symbol: sym::dummy,
884 suffix: None,
885 kind: ast::LitKind::Err(guar),
886 span: DUMMY_SP,
887 }
888 };
889 AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
890 }
891 }
892 }
893}
894
895pub(crate) fn parse_single_integer<S: Stage>(
902 cx: &mut AcceptContext<'_, '_, S>,
903 args: &ArgParser<'_>,
904) -> Option<u128> {
905 let Some(list) = args.list() else {
906 cx.expected_list(cx.attr_span);
907 return None;
908 };
909 let Some(single) = list.single() else {
910 cx.expected_single_argument(list.span);
911 return None;
912 };
913 let Some(lit) = single.lit() else {
914 cx.expected_integer_literal(single.span());
915 return None;
916 };
917 let LitKind::Int(num, _ty) = lit.kind else {
918 cx.expected_integer_literal(single.span());
919 return None;
920 };
921 Some(num.0)
922}