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::body::CoroutineParser;
20use crate::attributes::codegen_attrs::{
21 ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser,
22 TargetFeatureParser, TrackCallerParser, 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, LinkageParser, 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::{
37 AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
38};
39use crate::attributes::must_use::MustUseParser;
40use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
41use crate::attributes::non_exhaustive::NonExhaustiveParser;
42use crate::attributes::path::PathParser as PathAttributeParser;
43use crate::attributes::proc_macro_attrs::{
44 ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
45};
46use crate::attributes::repr::{AlignParser, ReprParser};
47use crate::attributes::rustc_internal::{
48 RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
49 RustcObjectLifetimeDefaultParser,
50};
51use crate::attributes::semantics::MayDangleParser;
52use crate::attributes::stability::{
53 BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
54};
55use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
56use crate::attributes::traits::{
57 AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
58 DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
59 ParenSugarParser, PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser,
60 TypeConstParser, UnsafeSpecializationMarkerParser,
61};
62use crate::attributes::transparency::TransparencyParser;
63use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
64use crate::parser::{ArgParser, MetaItemParser, PathParser};
65use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
66
67type GroupType<S> = LazyLock<GroupTypeInner<S>>;
68
69struct GroupTypeInner<S: Stage> {
70 accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
71 finalizers: Vec<FinalizeFn<S>>,
72}
73
74struct GroupTypeInnerAccept<S: Stage> {
75 template: AttributeTemplate,
76 accept_fn: AcceptFn<S>,
77}
78
79type AcceptFn<S> =
80 Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
81type FinalizeFn<S> =
82 Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
83
84macro_rules! attribute_parsers {
85 (
86 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
87 ) => {
88 mod early {
89 use super::*;
90 type Combine<T> = super::Combine<T, Early>;
91 type Single<T> = super::Single<T, Early>;
92 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
93
94 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
95 }
96 mod late {
97 use super::*;
98 type Combine<T> = super::Combine<T, Late>;
99 type Single<T> = super::Single<T, Late>;
100 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
101
102 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
103 }
104 };
105 (
106 @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
107 ) => {
108 pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
109 let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
110 let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
111 $(
112 {
113 thread_local! {
114 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
115 };
116
117 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
118 accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
119 template: *template,
120 accept_fn: Box::new(|cx, args| {
121 STATE_OBJECT.with_borrow_mut(|s| {
122 accept_fn(s, cx, args)
123 })
124 })
125 });
126 }
127
128 finalizes.push(Box::new(|cx| {
129 let state = STATE_OBJECT.take();
130 state.finalize(cx)
131 }));
132 }
133 )*
134
135 GroupTypeInner { accepters:accepts, finalizers:finalizes }
136 });
137 };
138}
139attribute_parsers!(
140 pub(crate) static ATTRIBUTE_PARSERS = [
141 AlignParser,
143 BodyStabilityParser,
144 ConfusablesParser,
145 ConstStabilityParser,
146 MacroUseParser,
147 NakedParser,
148 StabilityParser,
149 UsedParser,
150 Combine<AllowConstFnUnstableParser>,
154 Combine<AllowInternalUnstableParser>,
155 Combine<ReprParser>,
156 Combine<TargetFeatureParser>,
157 Combine<UnstableFeatureBoundParser>,
158 Single<CoverageParser>,
162 Single<DeprecationParser>,
163 Single<DummyParser>,
164 Single<ExportNameParser>,
165 Single<IgnoreParser>,
166 Single<InlineParser>,
167 Single<LinkNameParser>,
168 Single<LinkOrdinalParser>,
169 Single<LinkSectionParser>,
170 Single<LinkageParser>,
171 Single<MustUseParser>,
172 Single<OptimizeParser>,
173 Single<PathAttributeParser>,
174 Single<ProcMacroDeriveParser>,
175 Single<RustcBuiltinMacroParser>,
176 Single<RustcForceInlineParser>,
177 Single<RustcLayoutScalarValidRangeEnd>,
178 Single<RustcLayoutScalarValidRangeStart>,
179 Single<RustcObjectLifetimeDefaultParser>,
180 Single<ShouldPanicParser>,
181 Single<SkipDuringMethodDispatchParser>,
182 Single<TransparencyParser>,
183 Single<WithoutArgs<AllowIncoherentImplParser>>,
184 Single<WithoutArgs<AllowInternalUnsafeParser>>,
185 Single<WithoutArgs<AsPtrParser>>,
186 Single<WithoutArgs<AutomaticallyDerivedParser>>,
187 Single<WithoutArgs<CoherenceIsCoreParser>>,
188 Single<WithoutArgs<CoinductiveParser>>,
189 Single<WithoutArgs<ColdParser>>,
190 Single<WithoutArgs<ConstContinueParser>>,
191 Single<WithoutArgs<ConstStabilityIndirectParser>>,
192 Single<WithoutArgs<ConstTraitParser>>,
193 Single<WithoutArgs<CoroutineParser>>,
194 Single<WithoutArgs<DenyExplicitImplParser>>,
195 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
196 Single<WithoutArgs<ExportStableParser>>,
197 Single<WithoutArgs<FfiConstParser>>,
198 Single<WithoutArgs<FfiPureParser>>,
199 Single<WithoutArgs<FundamentalParser>>,
200 Single<WithoutArgs<LoopMatchParser>>,
201 Single<WithoutArgs<MacroEscapeParser>>,
202 Single<WithoutArgs<MarkerParser>>,
203 Single<WithoutArgs<MayDangleParser>>,
204 Single<WithoutArgs<NoImplicitPreludeParser>>,
205 Single<WithoutArgs<NoMangleParser>>,
206 Single<WithoutArgs<NonExhaustiveParser>>,
207 Single<WithoutArgs<ParenSugarParser>>,
208 Single<WithoutArgs<PassByValueParser>>,
209 Single<WithoutArgs<PointeeParser>>,
210 Single<WithoutArgs<ProcMacroAttributeParser>>,
211 Single<WithoutArgs<ProcMacroParser>>,
212 Single<WithoutArgs<PubTransparentParser>>,
213 Single<WithoutArgs<SpecializationTraitParser>>,
214 Single<WithoutArgs<StdInternalSymbolParser>>,
215 Single<WithoutArgs<TrackCallerParser>>,
216 Single<WithoutArgs<TypeConstParser>>,
217 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
218 ];
220);
221
222mod private {
223 pub trait Sealed {}
224 impl Sealed for super::Early {}
225 impl Sealed for super::Late {}
226}
227
228#[allow(private_interfaces)]
230pub trait Stage: Sized + 'static + Sealed {
231 type Id: Copy;
232
233 fn parsers() -> &'static GroupType<Self>;
234
235 fn emit_err<'sess>(
236 &self,
237 sess: &'sess Session,
238 diag: impl for<'x> Diagnostic<'x>,
239 ) -> ErrorGuaranteed;
240
241 fn should_emit(&self) -> ShouldEmit;
242}
243
244#[allow(private_interfaces)]
246impl Stage for Early {
247 type Id = NodeId;
248
249 fn parsers() -> &'static GroupType<Self> {
250 &early::ATTRIBUTE_PARSERS
251 }
252 fn emit_err<'sess>(
253 &self,
254 sess: &'sess Session,
255 diag: impl for<'x> Diagnostic<'x>,
256 ) -> ErrorGuaranteed {
257 if self.emit_errors.should_emit() {
258 sess.dcx().emit_err(diag)
259 } else {
260 sess.dcx().create_err(diag).delay_as_bug()
261 }
262 }
263
264 fn should_emit(&self) -> ShouldEmit {
265 self.emit_errors
266 }
267}
268
269#[allow(private_interfaces)]
271impl Stage for Late {
272 type Id = HirId;
273
274 fn parsers() -> &'static GroupType<Self> {
275 &late::ATTRIBUTE_PARSERS
276 }
277 fn emit_err<'sess>(
278 &self,
279 tcx: &'sess Session,
280 diag: impl for<'x> Diagnostic<'x>,
281 ) -> ErrorGuaranteed {
282 tcx.dcx().emit_err(diag)
283 }
284
285 fn should_emit(&self) -> ShouldEmit {
286 ShouldEmit::ErrorsAndLints
287 }
288}
289
290pub struct Early {
292 pub emit_errors: ShouldEmit,
296}
297pub struct Late;
299
300pub struct AcceptContext<'f, 'sess, S: Stage> {
304 pub(crate) shared: SharedContext<'f, 'sess, S>,
305 pub(crate) attr_span: Span,
307
308 pub(crate) template: &'f AttributeTemplate,
312
313 pub(crate) attr_path: AttrPath,
315}
316
317impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
318 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
319 self.stage.emit_err(&self.sess, diag)
320 }
321
322 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
326 if !self.stage.should_emit().should_emit() {
327 return;
328 }
329 let id = self.target_id;
330 (self.emit_lint)(AttributeLint { id, span, kind: lint });
331 }
332
333 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
334 self.emit_lint(
335 AttributeLintKind::UnusedDuplicate {
336 this: unused_span,
337 other: used_span,
338 warning: false,
339 },
340 unused_span,
341 )
342 }
343
344 pub(crate) fn warn_unused_duplicate_future_error(
345 &mut self,
346 used_span: Span,
347 unused_span: Span,
348 ) {
349 self.emit_lint(
350 AttributeLintKind::UnusedDuplicate {
351 this: unused_span,
352 other: used_span,
353 warning: true,
354 },
355 unused_span,
356 )
357 }
358}
359
360impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
361 pub(crate) fn unknown_key(
362 &self,
363 span: Span,
364 found: String,
365 options: &'static [&'static str],
366 ) -> ErrorGuaranteed {
367 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
368 }
369
370 pub(crate) fn expected_string_literal(
375 &self,
376 span: Span,
377 actual_literal: Option<&MetaItemLit>,
378 ) -> ErrorGuaranteed {
379 self.emit_err(AttributeParseError {
380 span,
381 attr_span: self.attr_span,
382 template: self.template.clone(),
383 attribute: self.attr_path.clone(),
384 reason: AttributeParseErrorReason::ExpectedStringLiteral {
385 byte_string: actual_literal.and_then(|i| {
386 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
387 }),
388 },
389 })
390 }
391
392 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
393 self.emit_err(AttributeParseError {
394 span,
395 attr_span: self.attr_span,
396 template: self.template.clone(),
397 attribute: self.attr_path.clone(),
398 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
399 })
400 }
401
402 pub(crate) fn expected_list(&self, span: Span) -> 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::ExpectedList,
409 })
410 }
411
412 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
413 self.emit_err(AttributeParseError {
414 span: args_span,
415 attr_span: self.attr_span,
416 template: self.template.clone(),
417 attribute: self.attr_path.clone(),
418 reason: AttributeParseErrorReason::ExpectedNoArgs,
419 })
420 }
421
422 pub(crate) fn expected_identifier(&self, span: Span) -> 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::ExpectedIdentifier,
430 })
431 }
432
433 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> 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::ExpectedNameValue(name),
442 })
443 }
444
445 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
447 self.emit_err(AttributeParseError {
448 span,
449 attr_span: self.attr_span,
450 template: self.template.clone(),
451 attribute: self.attr_path.clone(),
452 reason: AttributeParseErrorReason::DuplicateKey(key),
453 })
454 }
455
456 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
459 self.emit_err(AttributeParseError {
460 span,
461 attr_span: self.attr_span,
462 template: self.template.clone(),
463 attribute: self.attr_path.clone(),
464 reason: AttributeParseErrorReason::UnexpectedLiteral,
465 })
466 }
467
468 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
469 self.emit_err(AttributeParseError {
470 span,
471 attr_span: self.attr_span,
472 template: self.template.clone(),
473 attribute: self.attr_path.clone(),
474 reason: AttributeParseErrorReason::ExpectedSingleArgument,
475 })
476 }
477
478 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
479 self.emit_err(AttributeParseError {
480 span,
481 attr_span: self.attr_span,
482 template: self.template.clone(),
483 attribute: self.attr_path.clone(),
484 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
485 })
486 }
487
488 pub(crate) fn expected_specific_argument(
489 &self,
490 span: Span,
491 possibilities: Vec<&'static str>,
492 ) -> ErrorGuaranteed {
493 self.emit_err(AttributeParseError {
494 span,
495 attr_span: self.attr_span,
496 template: self.template.clone(),
497 attribute: self.attr_path.clone(),
498 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
499 possibilities,
500 strings: false,
501 list: false,
502 },
503 })
504 }
505
506 pub(crate) fn expected_specific_argument_and_list(
507 &self,
508 span: Span,
509 possibilities: Vec<&'static str>,
510 ) -> ErrorGuaranteed {
511 self.emit_err(AttributeParseError {
512 span,
513 attr_span: self.attr_span,
514 template: self.template.clone(),
515 attribute: self.attr_path.clone(),
516 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
517 possibilities,
518 strings: false,
519 list: true,
520 },
521 })
522 }
523
524 pub(crate) fn expected_specific_argument_strings(
525 &self,
526 span: Span,
527 possibilities: Vec<&'static str>,
528 ) -> ErrorGuaranteed {
529 self.emit_err(AttributeParseError {
530 span,
531 attr_span: self.attr_span,
532 template: self.template.clone(),
533 attribute: self.attr_path.clone(),
534 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
535 possibilities,
536 strings: true,
537 list: false,
538 },
539 })
540 }
541
542 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
543 self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
544 }
545}
546
547impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
548 type Target = SharedContext<'f, 'sess, S>;
549
550 fn deref(&self) -> &Self::Target {
551 &self.shared
552 }
553}
554
555impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
556 fn deref_mut(&mut self) -> &mut Self::Target {
557 &mut self.shared
558 }
559}
560
561pub struct SharedContext<'p, 'sess, S: Stage> {
566 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
569 pub(crate) target_span: Span,
571 pub(crate) target_id: S::Id,
573
574 emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
575}
576
577pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
582 pub(crate) shared: SharedContext<'p, 'sess, S>,
583
584 pub(crate) all_attrs: &'p [PathParser<'p>],
591}
592
593impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
594 type Target = SharedContext<'p, 'sess, S>;
595
596 fn deref(&self) -> &Self::Target {
597 &self.shared
598 }
599}
600
601impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
602 fn deref_mut(&mut self) -> &mut Self::Target {
603 &mut self.shared
604 }
605}
606
607impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
608 type Target = AttributeParser<'sess, S>;
609
610 fn deref(&self) -> &Self::Target {
611 self.cx
612 }
613}
614
615impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
616 fn deref_mut(&mut self) -> &mut Self::Target {
617 self.cx
618 }
619}
620
621#[derive(PartialEq, Clone, Copy, Debug)]
622pub enum OmitDoc {
623 Lower,
624 Skip,
625}
626
627#[derive(Copy, Clone)]
628pub enum ShouldEmit {
629 ErrorsAndLints,
632 Nothing,
635}
636
637impl ShouldEmit {
638 pub fn should_emit(&self) -> bool {
639 match self {
640 ShouldEmit::ErrorsAndLints => true,
641 ShouldEmit::Nothing => false,
642 }
643 }
644}
645
646pub struct AttributeParser<'sess, S: Stage = Late> {
649 pub(crate) tools: Vec<Symbol>,
650 features: Option<&'sess Features>,
651 sess: &'sess Session,
652 stage: S,
653
654 parse_only: Option<Symbol>,
658}
659
660impl<'sess> AttributeParser<'sess, Early> {
661 pub fn parse_limited(
676 sess: &'sess Session,
677 attrs: &[ast::Attribute],
678 sym: Symbol,
679 target_span: Span,
680 target_node_id: NodeId,
681 features: Option<&'sess Features>,
682 ) -> Option<Attribute> {
683 let mut p = Self {
684 features,
685 tools: Vec::new(),
686 parse_only: Some(sym),
687 sess,
688 stage: Early { emit_errors: ShouldEmit::Nothing },
689 };
690 let mut parsed = p.parse_attribute_list(
691 attrs,
692 target_span,
693 target_node_id,
694 OmitDoc::Skip,
695 std::convert::identity,
696 |_lint| {
697 panic!("can't emit lints here for now (nothing uses this atm)");
698 },
699 );
700 assert!(parsed.len() <= 1);
701
702 parsed.pop()
703 }
704
705 pub fn parse_single<T>(
706 sess: &'sess Session,
707 attr: &ast::Attribute,
708 target_span: Span,
709 target_node_id: NodeId,
710 features: Option<&'sess Features>,
711 emit_errors: ShouldEmit,
712 parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
713 template: &AttributeTemplate,
714 ) -> T {
715 let mut parser = Self {
716 features,
717 tools: Vec::new(),
718 parse_only: None,
719 sess,
720 stage: Early { emit_errors },
721 };
722 let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
723 panic!("parse_single called on a doc attr")
724 };
725 let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
726 let path = meta_parser.path();
727 let args = meta_parser.args();
728 let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
729 shared: SharedContext {
730 cx: &mut parser,
731 target_span,
732 target_id: target_node_id,
733 emit_lint: &mut |_lint| {
734 panic!("can't emit lints here for now (nothing uses this atm)");
735 },
736 },
737 attr_span: attr.span,
738 template,
739 attr_path: path.get_attribute_path(),
740 };
741 parse_fn(&mut cx, args)
742 }
743}
744
745impl<'sess, S: Stage> AttributeParser<'sess, S> {
746 pub fn new(
747 sess: &'sess Session,
748 features: &'sess Features,
749 tools: Vec<Symbol>,
750 stage: S,
751 ) -> Self {
752 Self { features: Some(features), tools, parse_only: None, sess, stage }
753 }
754
755 pub(crate) fn sess(&self) -> &'sess Session {
756 &self.sess
757 }
758
759 pub(crate) fn features(&self) -> &'sess Features {
760 self.features.expect("features not available at this point in the compiler")
761 }
762
763 pub(crate) fn features_option(&self) -> Option<&'sess Features> {
764 self.features
765 }
766
767 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
768 self.sess().dcx()
769 }
770
771 pub fn parse_attribute_list(
776 &mut self,
777 attrs: &[ast::Attribute],
778 target_span: Span,
779 target_id: S::Id,
780 omit_doc: OmitDoc,
781
782 lower_span: impl Copy + Fn(Span) -> Span,
783 mut emit_lint: impl FnMut(AttributeLint<S::Id>),
784 ) -> Vec<Attribute> {
785 let mut attributes = Vec::new();
786 let mut attr_paths = Vec::new();
787
788 for attr in attrs {
789 if let Some(expected) = self.parse_only {
791 if !attr.has_name(expected) {
792 continue;
793 }
794 }
795
796 if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
802 continue;
803 }
804
805 match &attr.kind {
806 ast::AttrKind::DocComment(comment_kind, symbol) => {
807 if omit_doc == OmitDoc::Skip {
808 continue;
809 }
810
811 attributes.push(Attribute::Parsed(AttributeKind::DocComment {
812 style: attr.style,
813 kind: *comment_kind,
814 span: lower_span(attr.span),
815 comment: *symbol,
816 }))
817 }
818 ast::AttrKind::Normal(n) => {
830 attr_paths.push(PathParser::Ast(&n.item.path));
831
832 let parser = MetaItemParser::from_attr(n, self.dcx());
833 let path = parser.path();
834 let args = parser.args();
835 let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
836
837 if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
838 for accept in accepts {
839 let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
840 shared: SharedContext {
841 cx: self,
842 target_span,
843 target_id,
844 emit_lint: &mut emit_lint,
845 },
846 attr_span: lower_span(attr.span),
847 template: &accept.template,
848 attr_path: path.get_attribute_path(),
849 };
850
851 (accept.accept_fn)(&mut cx, args)
852 }
853 } else {
854 attributes.push(Attribute::Unparsed(Box::new(AttrItem {
870 path: AttrPath::from_ast(&n.item.path),
871 args: self.lower_attr_args(&n.item.args, lower_span),
872 id: HashIgnoredAttrId { attr_id: attr.id },
873 style: attr.style,
874 span: lower_span(attr.span),
875 })));
876 }
877 }
878 }
879 }
880
881 let mut parsed_attributes = Vec::new();
882 for f in &S::parsers().finalizers {
883 if let Some(attr) = f(&mut FinalizeContext {
884 shared: SharedContext {
885 cx: self,
886 target_span,
887 target_id,
888 emit_lint: &mut emit_lint,
889 },
890 all_attrs: &attr_paths,
891 }) {
892 parsed_attributes.push(Attribute::Parsed(attr));
893 }
894 }
895
896 attributes.extend(parsed_attributes);
897
898 attributes
899 }
900
901 pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
903 Late::parsers().accepters.contains_key(path)
904 }
905
906 fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
907 match args {
908 ast::AttrArgs::Empty => AttrArgs::Empty,
909 ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
910 ast::AttrArgs::Eq { eq_span, expr } => {
914 let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
917 && let Ok(lit) =
918 ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
919 {
920 lit
921 } else {
922 let guar = self.dcx().span_delayed_bug(
923 args.span().unwrap_or(DUMMY_SP),
924 "expr in place where literal is expected (builtin attr parsing)",
925 );
926 ast::MetaItemLit {
927 symbol: sym::dummy,
928 suffix: None,
929 kind: ast::LitKind::Err(guar),
930 span: DUMMY_SP,
931 }
932 };
933 AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
934 }
935 }
936 }
937}
938
939pub(crate) fn parse_single_integer<S: Stage>(
946 cx: &mut AcceptContext<'_, '_, S>,
947 args: &ArgParser<'_>,
948) -> Option<u128> {
949 let Some(list) = args.list() else {
950 cx.expected_list(cx.attr_span);
951 return None;
952 };
953 let Some(single) = list.single() else {
954 cx.expected_single_argument(list.span);
955 return None;
956 };
957 let Some(lit) = single.lit() else {
958 cx.expected_integer_literal(single.span());
959 return None;
960 };
961 let LitKind::Int(num, _ty) = lit.kind else {
962 cx.expected_integer_literal(single.span());
963 return None;
964 };
965 Some(num.0)
966}