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_errors::{DiagCtxtHandle, Diagnostic};
9use rustc_feature::{AttributeTemplate, Features};
10use rustc_hir::attrs::AttributeKind;
11use rustc_hir::lints::{AttributeLint, AttributeLintKind};
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::macro_attrs::{MacroEscapeParser, MacroUseParser};
37use crate::attributes::must_use::MustUseParser;
38use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
39use crate::attributes::non_exhaustive::NonExhaustiveParser;
40use crate::attributes::path::PathParser as PathAttributeParser;
41use crate::attributes::proc_macro_attrs::{
42 ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
43};
44use crate::attributes::repr::{AlignParser, ReprParser};
45use crate::attributes::rustc_internal::{
46 RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
47 RustcObjectLifetimeDefaultParser,
48};
49use crate::attributes::semantics::MayDangleParser;
50use crate::attributes::stability::{
51 BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
52};
53use crate::attributes::test_attrs::IgnoreParser;
54use crate::attributes::traits::{
55 AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
56 DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
57 ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
58 TypeConstParser, UnsafeSpecializationMarkerParser,
59};
60use crate::attributes::transparency::TransparencyParser;
61use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
62use crate::parser::{ArgParser, MetaItemParser, PathParser};
63use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
64
65macro_rules! group_type {
66 ($stage: ty) => {
67 LazyLock<(
68 BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>,
69 Vec<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $stage>) -> Option<AttributeKind>>>
70 )>
71 };
72}
73
74macro_rules! attribute_parsers {
75 (
76 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
77 ) => {
78 mod early {
79 use super::*;
80 type Combine<T> = super::Combine<T, Early>;
81 type Single<T> = super::Single<T, Early>;
82 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
83
84 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
85 }
86 mod late {
87 use super::*;
88 type Combine<T> = super::Combine<T, Late>;
89 type Single<T> = super::Single<T, Late>;
90 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
91
92 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
93 }
94 };
95 (
96 @[$ty: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
97 ) => {
98 pub(crate) static $name: group_type!($ty) = LazyLock::new(|| {
99 let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new();
100 let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $ty>) -> Option<AttributeKind>>>::new();
101 $(
102 {
103 thread_local! {
104 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
105 };
106
107 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
108 accepts.entry(*path).or_default().push((*template, Box::new(|cx, args| {
109 STATE_OBJECT.with_borrow_mut(|s| {
110 accept_fn(s, cx, args)
111 })
112 })));
113 }
114
115 finalizes.push(Box::new(|cx| {
116 let state = STATE_OBJECT.take();
117 state.finalize(cx)
118 }));
119 }
120 )*
121
122 (accepts, finalizes)
123 });
124 };
125}
126attribute_parsers!(
127 pub(crate) static ATTRIBUTE_PARSERS = [
128 AlignParser,
130 BodyStabilityParser,
131 ConfusablesParser,
132 ConstStabilityParser,
133 MacroUseParser,
134 NakedParser,
135 StabilityParser,
136 UsedParser,
137 Combine<AllowConstFnUnstableParser>,
141 Combine<AllowInternalUnstableParser>,
142 Combine<ReprParser>,
143 Combine<TargetFeatureParser>,
144 Combine<UnstableFeatureBoundParser>,
145 Single<CoverageParser>,
149 Single<DeprecationParser>,
150 Single<DummyParser>,
151 Single<ExportNameParser>,
152 Single<IgnoreParser>,
153 Single<InlineParser>,
154 Single<LinkNameParser>,
155 Single<LinkOrdinalParser>,
156 Single<LinkSectionParser>,
157 Single<MustUseParser>,
158 Single<OptimizeParser>,
159 Single<PathAttributeParser>,
160 Single<ProcMacroDeriveParser>,
161 Single<RustcBuiltinMacroParser>,
162 Single<RustcForceInlineParser>,
163 Single<RustcLayoutScalarValidRangeEnd>,
164 Single<RustcLayoutScalarValidRangeStart>,
165 Single<RustcObjectLifetimeDefaultParser>,
166 Single<SkipDuringMethodDispatchParser>,
167 Single<TransparencyParser>,
168 Single<WithoutArgs<AllowIncoherentImplParser>>,
169 Single<WithoutArgs<AsPtrParser>>,
170 Single<WithoutArgs<AutomaticallyDerivedParser>>,
171 Single<WithoutArgs<CoherenceIsCoreParser>>,
172 Single<WithoutArgs<CoinductiveParser>>,
173 Single<WithoutArgs<ColdParser>>,
174 Single<WithoutArgs<ConstContinueParser>>,
175 Single<WithoutArgs<ConstStabilityIndirectParser>>,
176 Single<WithoutArgs<ConstTraitParser>>,
177 Single<WithoutArgs<DenyExplicitImplParser>>,
178 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
179 Single<WithoutArgs<ExportStableParser>>,
180 Single<WithoutArgs<FfiConstParser>>,
181 Single<WithoutArgs<FfiPureParser>>,
182 Single<WithoutArgs<FundamentalParser>>,
183 Single<WithoutArgs<LoopMatchParser>>,
184 Single<WithoutArgs<MacroEscapeParser>>,
185 Single<WithoutArgs<MarkerParser>>,
186 Single<WithoutArgs<MayDangleParser>>,
187 Single<WithoutArgs<NoImplicitPreludeParser>>,
188 Single<WithoutArgs<NoMangleParser>>,
189 Single<WithoutArgs<NonExhaustiveParser>>,
190 Single<WithoutArgs<OmitGdbPrettyPrinterSectionParser>>,
191 Single<WithoutArgs<ParenSugarParser>>,
192 Single<WithoutArgs<PassByValueParser>>,
193 Single<WithoutArgs<PointeeParser>>,
194 Single<WithoutArgs<ProcMacroAttributeParser>>,
195 Single<WithoutArgs<ProcMacroParser>>,
196 Single<WithoutArgs<PubTransparentParser>>,
197 Single<WithoutArgs<SpecializationTraitParser>>,
198 Single<WithoutArgs<StdInternalSymbolParser>>,
199 Single<WithoutArgs<TrackCallerParser>>,
200 Single<WithoutArgs<TypeConstParser>>,
201 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
202 ];
204);
205
206mod private {
207 pub trait Sealed {}
208 impl Sealed for super::Early {}
209 impl Sealed for super::Late {}
210}
211
212#[allow(private_interfaces)]
214pub trait Stage: Sized + 'static + Sealed {
215 type Id: Copy;
216 const SHOULD_EMIT_LINTS: bool;
217
218 fn parsers() -> &'static group_type!(Self);
219
220 fn emit_err<'sess>(
221 &self,
222 sess: &'sess Session,
223 diag: impl for<'x> Diagnostic<'x>,
224 ) -> ErrorGuaranteed;
225}
226
227#[allow(private_interfaces)]
229impl Stage for Early {
230 type Id = NodeId;
231 const SHOULD_EMIT_LINTS: bool = false;
232
233 fn parsers() -> &'static group_type!(Self) {
234 &early::ATTRIBUTE_PARSERS
235 }
236 fn emit_err<'sess>(
237 &self,
238 sess: &'sess Session,
239 diag: impl for<'x> Diagnostic<'x>,
240 ) -> ErrorGuaranteed {
241 if self.emit_errors.should_emit() {
242 sess.dcx().emit_err(diag)
243 } else {
244 sess.dcx().create_err(diag).delay_as_bug()
245 }
246 }
247}
248
249#[allow(private_interfaces)]
251impl Stage for Late {
252 type Id = HirId;
253 const SHOULD_EMIT_LINTS: bool = true;
254
255 fn parsers() -> &'static group_type!(Self) {
256 &late::ATTRIBUTE_PARSERS
257 }
258 fn emit_err<'sess>(
259 &self,
260 tcx: &'sess Session,
261 diag: impl for<'x> Diagnostic<'x>,
262 ) -> ErrorGuaranteed {
263 tcx.dcx().emit_err(diag)
264 }
265}
266
267pub struct Early {
269 pub emit_errors: ShouldEmit,
273}
274pub struct Late;
276
277pub struct AcceptContext<'f, 'sess, S: Stage> {
281 pub(crate) shared: SharedContext<'f, 'sess, S>,
282 pub(crate) attr_span: Span,
284
285 pub(crate) template: &'f AttributeTemplate,
289
290 pub(crate) attr_path: AttrPath,
292}
293
294impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
295 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
296 self.stage.emit_err(&self.sess, diag)
297 }
298
299 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
303 if !S::SHOULD_EMIT_LINTS {
304 return;
305 }
306 let id = self.target_id;
307 (self.emit_lint)(AttributeLint { id, span, kind: lint });
308 }
309
310 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
311 self.emit_lint(
312 AttributeLintKind::UnusedDuplicate {
313 this: unused_span,
314 other: used_span,
315 warning: false,
316 },
317 unused_span,
318 )
319 }
320
321 pub(crate) fn warn_unused_duplicate_future_error(
322 &mut self,
323 used_span: Span,
324 unused_span: Span,
325 ) {
326 self.emit_lint(
327 AttributeLintKind::UnusedDuplicate {
328 this: unused_span,
329 other: used_span,
330 warning: true,
331 },
332 unused_span,
333 )
334 }
335}
336
337impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
338 pub(crate) fn unknown_key(
339 &self,
340 span: Span,
341 found: String,
342 options: &'static [&'static str],
343 ) -> ErrorGuaranteed {
344 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
345 }
346
347 pub(crate) fn expected_string_literal(
352 &self,
353 span: Span,
354 actual_literal: Option<&MetaItemLit>,
355 ) -> ErrorGuaranteed {
356 self.emit_err(AttributeParseError {
357 span,
358 attr_span: self.attr_span,
359 template: self.template.clone(),
360 attribute: self.attr_path.clone(),
361 reason: AttributeParseErrorReason::ExpectedStringLiteral {
362 byte_string: actual_literal.and_then(|i| {
363 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
364 }),
365 },
366 })
367 }
368
369 pub(crate) fn expected_integer_literal(&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::ExpectedIntegerLiteral,
376 })
377 }
378
379 pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
380 self.emit_err(AttributeParseError {
381 span,
382 attr_span: self.attr_span,
383 template: self.template.clone(),
384 attribute: self.attr_path.clone(),
385 reason: AttributeParseErrorReason::ExpectedList,
386 })
387 }
388
389 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
390 self.emit_err(AttributeParseError {
391 span: args_span,
392 attr_span: self.attr_span,
393 template: self.template.clone(),
394 attribute: self.attr_path.clone(),
395 reason: AttributeParseErrorReason::ExpectedNoArgs,
396 })
397 }
398
399 pub(crate) fn expected_identifier(&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::ExpectedIdentifier,
407 })
408 }
409
410 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
413 self.emit_err(AttributeParseError {
414 span,
415 attr_span: self.attr_span,
416 template: self.template.clone(),
417 attribute: self.attr_path.clone(),
418 reason: AttributeParseErrorReason::ExpectedNameValue(name),
419 })
420 }
421
422 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
424 self.emit_err(AttributeParseError {
425 span,
426 attr_span: self.attr_span,
427 template: self.template.clone(),
428 attribute: self.attr_path.clone(),
429 reason: AttributeParseErrorReason::DuplicateKey(key),
430 })
431 }
432
433 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
436 self.emit_err(AttributeParseError {
437 span,
438 attr_span: self.attr_span,
439 template: self.template.clone(),
440 attribute: self.attr_path.clone(),
441 reason: AttributeParseErrorReason::UnexpectedLiteral,
442 })
443 }
444
445 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
446 self.emit_err(AttributeParseError {
447 span,
448 attr_span: self.attr_span,
449 template: self.template.clone(),
450 attribute: self.attr_path.clone(),
451 reason: AttributeParseErrorReason::ExpectedSingleArgument,
452 })
453 }
454
455 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
456 self.emit_err(AttributeParseError {
457 span,
458 attr_span: self.attr_span,
459 template: self.template.clone(),
460 attribute: self.attr_path.clone(),
461 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
462 })
463 }
464
465 pub(crate) fn expected_specific_argument(
466 &self,
467 span: Span,
468 possibilities: Vec<&'static str>,
469 ) -> ErrorGuaranteed {
470 self.emit_err(AttributeParseError {
471 span,
472 attr_span: self.attr_span,
473 template: self.template.clone(),
474 attribute: self.attr_path.clone(),
475 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
476 possibilities,
477 strings: false,
478 list: false,
479 },
480 })
481 }
482
483 pub(crate) fn expected_specific_argument_and_list(
484 &self,
485 span: Span,
486 possibilities: Vec<&'static str>,
487 ) -> 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::ExpectedSpecificArgument {
494 possibilities,
495 strings: false,
496 list: true,
497 },
498 })
499 }
500
501 pub(crate) fn expected_specific_argument_strings(
502 &self,
503 span: Span,
504 possibilities: Vec<&'static str>,
505 ) -> ErrorGuaranteed {
506 self.emit_err(AttributeParseError {
507 span,
508 attr_span: self.attr_span,
509 template: self.template.clone(),
510 attribute: self.attr_path.clone(),
511 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
512 possibilities,
513 strings: true,
514 list: false,
515 },
516 })
517 }
518
519 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
520 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
521 }
522}
523
524impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
525 type Target = SharedContext<'f, 'sess, S>;
526
527 fn deref(&self) -> &Self::Target {
528 &self.shared
529 }
530}
531
532impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
533 fn deref_mut(&mut self) -> &mut Self::Target {
534 &mut self.shared
535 }
536}
537
538pub struct SharedContext<'p, 'sess, S: Stage> {
543 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
546 pub(crate) target_span: Span,
548 pub(crate) target_id: S::Id,
550
551 emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
552}
553
554pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
559 pub(crate) shared: SharedContext<'p, 'sess, S>,
560
561 pub(crate) all_attrs: &'p [PathParser<'p>],
568}
569
570impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
571 type Target = SharedContext<'p, 'sess, S>;
572
573 fn deref(&self) -> &Self::Target {
574 &self.shared
575 }
576}
577
578impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
579 fn deref_mut(&mut self) -> &mut Self::Target {
580 &mut self.shared
581 }
582}
583
584impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
585 type Target = AttributeParser<'sess, S>;
586
587 fn deref(&self) -> &Self::Target {
588 self.cx
589 }
590}
591
592impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
593 fn deref_mut(&mut self) -> &mut Self::Target {
594 self.cx
595 }
596}
597
598#[derive(PartialEq, Clone, Copy, Debug)]
599pub enum OmitDoc {
600 Lower,
601 Skip,
602}
603
604#[derive(Copy, Clone)]
605pub enum ShouldEmit {
606 ErrorsAndLints,
609 Nothing,
612}
613
614impl ShouldEmit {
615 pub fn should_emit(&self) -> bool {
616 match self {
617 ShouldEmit::ErrorsAndLints => true,
618 ShouldEmit::Nothing => false,
619 }
620 }
621}
622
623pub struct AttributeParser<'sess, S: Stage = Late> {
626 pub(crate) tools: Vec<Symbol>,
627 features: Option<&'sess Features>,
628 sess: &'sess Session,
629 stage: S,
630
631 parse_only: Option<Symbol>,
635}
636
637impl<'sess> AttributeParser<'sess, Early> {
638 pub fn parse_limited(
653 sess: &'sess Session,
654 attrs: &[ast::Attribute],
655 sym: Symbol,
656 target_span: Span,
657 target_node_id: NodeId,
658 features: Option<&'sess Features>,
659 ) -> Option<Attribute> {
660 let mut p = Self {
661 features,
662 tools: Vec::new(),
663 parse_only: Some(sym),
664 sess,
665 stage: Early { emit_errors: ShouldEmit::Nothing },
666 };
667 let mut parsed = p.parse_attribute_list(
668 attrs,
669 target_span,
670 target_node_id,
671 OmitDoc::Skip,
672 std::convert::identity,
673 |_lint| {
674 panic!("can't emit lints here for now (nothing uses this atm)");
675 },
676 );
677 assert!(parsed.len() <= 1);
678
679 parsed.pop()
680 }
681
682 pub fn parse_single<T>(
683 sess: &'sess Session,
684 attr: &ast::Attribute,
685 target_span: Span,
686 target_node_id: NodeId,
687 features: Option<&'sess Features>,
688 emit_errors: ShouldEmit,
689 parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
690 template: &AttributeTemplate,
691 ) -> T {
692 let mut parser = Self {
693 features,
694 tools: Vec::new(),
695 parse_only: None,
696 sess,
697 stage: Early { emit_errors },
698 };
699 let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
700 panic!("parse_single called on a doc attr")
701 };
702 let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
703 let path = meta_parser.path();
704 let args = meta_parser.args();
705 let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
706 shared: SharedContext {
707 cx: &mut parser,
708 target_span,
709 target_id: target_node_id,
710 emit_lint: &mut |_lint| {
711 panic!("can't emit lints here for now (nothing uses this atm)");
712 },
713 },
714 attr_span: attr.span,
715 template,
716 attr_path: path.get_attribute_path(),
717 };
718 parse_fn(&mut cx, args)
719 }
720}
721
722impl<'sess, S: Stage> AttributeParser<'sess, S> {
723 pub fn new(
724 sess: &'sess Session,
725 features: &'sess Features,
726 tools: Vec<Symbol>,
727 stage: S,
728 ) -> Self {
729 Self { features: Some(features), tools, parse_only: None, sess, stage }
730 }
731
732 pub(crate) fn sess(&self) -> &'sess Session {
733 &self.sess
734 }
735
736 pub(crate) fn features(&self) -> &'sess Features {
737 self.features.expect("features not available at this point in the compiler")
738 }
739
740 pub(crate) fn features_option(&self) -> Option<&'sess Features> {
741 self.features
742 }
743
744 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
745 self.sess().dcx()
746 }
747
748 pub fn parse_attribute_list(
753 &mut self,
754 attrs: &[ast::Attribute],
755 target_span: Span,
756 target_id: S::Id,
757 omit_doc: OmitDoc,
758
759 lower_span: impl Copy + Fn(Span) -> Span,
760 mut emit_lint: impl FnMut(AttributeLint<S::Id>),
761 ) -> Vec<Attribute> {
762 let mut attributes = Vec::new();
763 let mut attr_paths = Vec::new();
764
765 for attr in attrs {
766 if let Some(expected) = self.parse_only {
768 if !attr.has_name(expected) {
769 continue;
770 }
771 }
772
773 if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
779 continue;
780 }
781
782 match &attr.kind {
783 ast::AttrKind::DocComment(comment_kind, symbol) => {
784 if omit_doc == OmitDoc::Skip {
785 continue;
786 }
787
788 attributes.push(Attribute::Parsed(AttributeKind::DocComment {
789 style: attr.style,
790 kind: *comment_kind,
791 span: lower_span(attr.span),
792 comment: *symbol,
793 }))
794 }
795 ast::AttrKind::Normal(n) => {
807 attr_paths.push(PathParser::Ast(&n.item.path));
808
809 let parser = MetaItemParser::from_attr(n, self.dcx());
810 let path = parser.path();
811 let args = parser.args();
812 let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
813
814 if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
815 for (template, accept) in accepts {
816 let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
817 shared: SharedContext {
818 cx: self,
819 target_span,
820 target_id,
821 emit_lint: &mut emit_lint,
822 },
823 attr_span: lower_span(attr.span),
824 template,
825 attr_path: path.get_attribute_path(),
826 };
827
828 accept(&mut cx, args)
829 }
830 } else {
831 attributes.push(Attribute::Unparsed(Box::new(AttrItem {
847 path: AttrPath::from_ast(&n.item.path),
848 args: self.lower_attr_args(&n.item.args, lower_span),
849 id: HashIgnoredAttrId { attr_id: attr.id },
850 style: attr.style,
851 span: lower_span(attr.span),
852 })));
853 }
854 }
855 }
856 }
857
858 let mut parsed_attributes = Vec::new();
859 for f in &S::parsers().1 {
860 if let Some(attr) = f(&mut FinalizeContext {
861 shared: SharedContext {
862 cx: self,
863 target_span,
864 target_id,
865 emit_lint: &mut emit_lint,
866 },
867 all_attrs: &attr_paths,
868 }) {
869 parsed_attributes.push(Attribute::Parsed(attr));
870 }
871 }
872
873 attributes.extend(parsed_attributes);
874
875 attributes
876 }
877
878 pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
880 Late::parsers().0.contains_key(path)
881 }
882
883 fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
884 match args {
885 ast::AttrArgs::Empty => AttrArgs::Empty,
886 ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
887 ast::AttrArgs::Eq { eq_span, expr } => {
891 let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
894 && let Ok(lit) =
895 ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
896 {
897 lit
898 } else {
899 let guar = self.dcx().span_delayed_bug(
900 args.span().unwrap_or(DUMMY_SP),
901 "expr in place where literal is expected (builtin attr parsing)",
902 );
903 ast::MetaItemLit {
904 symbol: sym::dummy,
905 suffix: None,
906 kind: ast::LitKind::Err(guar),
907 span: DUMMY_SP,
908 }
909 };
910 AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
911 }
912 }
913 }
914}
915
916pub(crate) fn parse_single_integer<S: Stage>(
923 cx: &mut AcceptContext<'_, '_, S>,
924 args: &ArgParser<'_>,
925) -> Option<u128> {
926 let Some(list) = args.list() else {
927 cx.expected_list(cx.attr_span);
928 return None;
929 };
930 let Some(single) = list.single() else {
931 cx.expected_single_argument(list.span);
932 return None;
933 };
934 let Some(lit) = single.lit() else {
935 cx.expected_integer_literal(single.span());
936 return None;
937 };
938 let LitKind::Int(num, _ty) = lit.kind else {
939 cx.expected_integer_literal(single.span());
940 return None;
941 };
942 Some(num.0)
943}