rustc_attr_parsing/
context.rs

1use std::cell::RefCell;
2use std::collections::BTreeMap;
3use std::marker::PhantomData;
4use std::ops::{Deref, DerefMut};
5use std::sync::LazyLock;
6
7use private::Sealed;
8use rustc_ast::{self as ast, MetaItemLit, NodeId};
9use rustc_attr_data_structures::AttributeKind;
10use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind};
11use rustc_errors::{DiagCtxtHandle, Diagnostic};
12use rustc_feature::{AttributeTemplate, Features};
13use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId};
14use rustc_session::Session;
15use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
16
17use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
18use crate::attributes::codegen_attrs::{
19    ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser,
20    UsedParser,
21};
22use crate::attributes::confusables::ConfusablesParser;
23use crate::attributes::deprecation::DeprecationParser;
24use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
25use crate::attributes::link_attrs::LinkNameParser;
26use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
27use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
28use crate::attributes::must_use::MustUseParser;
29use crate::attributes::repr::{AlignParser, ReprParser};
30use crate::attributes::semantics::MayDangleParser;
31use crate::attributes::stability::{
32    BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
33};
34use crate::attributes::traits::SkipDuringMethodDispatchParser;
35use crate::attributes::transparency::TransparencyParser;
36use crate::attributes::{AttributeParser as _, Combine, Single};
37use crate::parser::{ArgParser, MetaItemParser, PathParser};
38use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
39
40macro_rules! group_type {
41    ($stage: ty) => {
42         LazyLock<(
43            BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>,
44            Vec<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $stage>) -> Option<AttributeKind>>>
45        )>
46    };
47}
48
49macro_rules! attribute_parsers {
50    (
51        pub(crate) static $name: ident = [$($names: ty),* $(,)?];
52    ) => {
53        mod early {
54            use super::*;
55            type Combine<T> = super::Combine<T, Early>;
56            type Single<T> = super::Single<T, Early>;
57
58            attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
59        }
60        mod late {
61            use super::*;
62            type Combine<T> = super::Combine<T, Late>;
63            type Single<T> = super::Single<T, Late>;
64
65            attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
66        }
67    };
68    (
69        @[$ty: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
70    ) => {
71        pub(crate) static $name: group_type!($ty) = LazyLock::new(|| {
72            let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new();
73            let mut finalizes = Vec::<Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, $ty>) -> Option<AttributeKind>>>::new();
74            $(
75                {
76                    thread_local! {
77                        static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
78                    };
79
80                    for (path, template, accept_fn) in <$names>::ATTRIBUTES {
81                        accepts.entry(*path).or_default().push((*template, Box::new(|cx, args| {
82                            STATE_OBJECT.with_borrow_mut(|s| {
83                                accept_fn(s, cx, args)
84                            })
85                        })));
86                    }
87
88                    finalizes.push(Box::new(|cx| {
89                        let state = STATE_OBJECT.take();
90                        state.finalize(cx)
91                    }));
92                }
93            )*
94
95            (accepts, finalizes)
96        });
97    };
98}
99attribute_parsers!(
100    pub(crate) static ATTRIBUTE_PARSERS = [
101        // tidy-alphabetical-start
102        AlignParser,
103        BodyStabilityParser,
104        ConfusablesParser,
105        ConstStabilityParser,
106        NakedParser,
107        StabilityParser,
108        UsedParser,
109        // tidy-alphabetical-end
110
111        // tidy-alphabetical-start
112        Combine<AllowConstFnUnstableParser>,
113        Combine<AllowInternalUnstableParser>,
114        Combine<ReprParser>,
115        // tidy-alphabetical-end
116
117        // tidy-alphabetical-start
118        Single<AsPtrParser>,
119        Single<ColdParser>,
120        Single<ConstContinueParser>,
121        Single<ConstStabilityIndirectParser>,
122        Single<DeprecationParser>,
123        Single<ExportNameParser>,
124        Single<InlineParser>,
125        Single<LinkNameParser>,
126        Single<LoopMatchParser>,
127        Single<MayDangleParser>,
128        Single<MustUseParser>,
129        Single<NoMangleParser>,
130        Single<OptimizeParser>,
131        Single<PubTransparentParser>,
132        Single<RustcForceInlineParser>,
133        Single<SkipDuringMethodDispatchParser>,
134        Single<TrackCallerParser>,
135        Single<TransparencyParser>,
136        // tidy-alphabetical-end
137    ];
138);
139
140mod private {
141    pub trait Sealed {}
142    impl Sealed for super::Early {}
143    impl Sealed for super::Late {}
144}
145
146// allow because it's a sealed trait
147#[allow(private_interfaces)]
148pub trait Stage: Sized + 'static + Sealed {
149    type Id: Copy;
150
151    fn parsers() -> &'static group_type!(Self);
152
153    fn emit_err<'sess>(sess: &'sess Session, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed;
154}
155
156// allow because it's a sealed trait
157#[allow(private_interfaces)]
158impl Stage for Early {
159    type Id = NodeId;
160
161    fn parsers() -> &'static group_type!(Self) {
162        &early::ATTRIBUTE_PARSERS
163    }
164    fn emit_err<'sess>(sess: &'sess Session, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
165        sess.dcx().create_err(diag).delay_as_bug()
166    }
167}
168
169// allow because it's a sealed trait
170#[allow(private_interfaces)]
171impl Stage for Late {
172    type Id = HirId;
173
174    fn parsers() -> &'static group_type!(Self) {
175        &late::ATTRIBUTE_PARSERS
176    }
177    fn emit_err<'sess>(tcx: &'sess Session, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
178        tcx.dcx().emit_err(diag)
179    }
180}
181
182/// used when parsing attributes for miscelaneous things *before* ast lowering
183pub struct Early;
184/// used when parsing attributes during ast lowering
185pub struct Late;
186
187/// Context given to every attribute parser when accepting
188///
189/// Gives [`AttributeParser`]s enough information to create errors, for example.
190pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
191    pub(crate) shared: SharedContext<'f, 'sess, S>,
192    /// The span of the attribute currently being parsed
193    pub(crate) attr_span: Span,
194
195    /// The expected structure of the attribute.
196    ///
197    /// Used in reporting errors to give a hint to users what the attribute *should* look like.
198    pub(crate) template: &'f AttributeTemplate,
199
200    /// The name of the attribute we're currently accepting.
201    pub(crate) attr_path: AttrPath,
202}
203
204impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
205    pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
206        S::emit_err(&self.sess, diag)
207    }
208
209    /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
210    /// must be delayed until after HIR is built. This method will take care of the details of
211    /// that.
212    pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
213        let id = self.target_id;
214        (self.emit_lint)(AttributeLint { id, span, kind: lint });
215    }
216
217    pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
218        self.emit_lint(
219            AttributeLintKind::UnusedDuplicate {
220                this: unused_span,
221                other: used_span,
222                warning: false,
223            },
224            unused_span,
225        )
226    }
227
228    pub(crate) fn warn_unused_duplicate_future_error(
229        &mut self,
230        used_span: Span,
231        unused_span: Span,
232    ) {
233        self.emit_lint(
234            AttributeLintKind::UnusedDuplicate {
235                this: unused_span,
236                other: used_span,
237                warning: true,
238            },
239            unused_span,
240        )
241    }
242}
243
244impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
245    pub(crate) fn unknown_key(
246        &self,
247        span: Span,
248        found: String,
249        options: &'static [&'static str],
250    ) -> ErrorGuaranteed {
251        self.emit_err(UnknownMetaItem { span, item: found, expected: options })
252    }
253
254    /// error that a string literal was expected.
255    /// You can optionally give the literal you did find (which you found not to be a string literal)
256    /// which can make better errors. For example, if the literal was a byte string it will suggest
257    /// removing the `b` prefix.
258    pub(crate) fn expected_string_literal(
259        &self,
260        span: Span,
261        actual_literal: Option<&MetaItemLit>,
262    ) -> ErrorGuaranteed {
263        self.emit_err(AttributeParseError {
264            span,
265            attr_span: self.attr_span,
266            template: self.template.clone(),
267            attribute: self.attr_path.clone(),
268            reason: AttributeParseErrorReason::ExpectedStringLiteral {
269                byte_string: actual_literal.and_then(|i| {
270                    i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
271                }),
272            },
273        })
274    }
275
276    pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
277        self.emit_err(AttributeParseError {
278            span,
279            attr_span: self.attr_span,
280            template: self.template.clone(),
281            attribute: self.attr_path.clone(),
282            reason: AttributeParseErrorReason::ExpectedList,
283        })
284    }
285
286    pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
287        self.emit_err(AttributeParseError {
288            span: args_span,
289            attr_span: self.attr_span,
290            template: self.template.clone(),
291            attribute: self.attr_path.clone(),
292            reason: AttributeParseErrorReason::ExpectedNoArgs,
293        })
294    }
295
296    /// emit an error that a `name = value` pair was expected at this span. The symbol can be given for
297    /// a nicer error message talking about the specific name that was found lacking a value.
298    pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
299        self.emit_err(AttributeParseError {
300            span,
301            attr_span: self.attr_span,
302            template: self.template.clone(),
303            attribute: self.attr_path.clone(),
304            reason: AttributeParseErrorReason::ExpectedNameValue(name),
305        })
306    }
307
308    /// emit an error that a `name = value` pair was found where that name was already seen.
309    pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
310        self.emit_err(AttributeParseError {
311            span,
312            attr_span: self.attr_span,
313            template: self.template.clone(),
314            attribute: self.attr_path.clone(),
315            reason: AttributeParseErrorReason::DuplicateKey(key),
316        })
317    }
318
319    /// an error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
320    /// was expected *not* to be a literal, but instead a meta item.
321    pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
322        self.emit_err(AttributeParseError {
323            span,
324            attr_span: self.attr_span,
325            template: self.template.clone(),
326            attribute: self.attr_path.clone(),
327            reason: AttributeParseErrorReason::UnexpectedLiteral,
328        })
329    }
330
331    pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
332        self.emit_err(AttributeParseError {
333            span,
334            attr_span: self.attr_span,
335            template: self.template.clone(),
336            attribute: self.attr_path.clone(),
337            reason: AttributeParseErrorReason::ExpectedSingleArgument,
338        })
339    }
340
341    pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
342        self.emit_err(AttributeParseError {
343            span,
344            attr_span: self.attr_span,
345            template: self.template.clone(),
346            attribute: self.attr_path.clone(),
347            reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
348        })
349    }
350
351    pub(crate) fn expected_specific_argument(
352        &self,
353        span: Span,
354        possibilities: Vec<&'static str>,
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::ExpectedSpecificArgument {
362                possibilities,
363                strings: false,
364            },
365        })
366    }
367
368    pub(crate) fn expected_specific_argument_strings(
369        &self,
370        span: Span,
371        possibilities: Vec<&'static str>,
372    ) -> ErrorGuaranteed {
373        self.emit_err(AttributeParseError {
374            span,
375            attr_span: self.attr_span,
376            template: self.template.clone(),
377            attribute: self.attr_path.clone(),
378            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
379                possibilities,
380                strings: true,
381            },
382        })
383    }
384}
385
386impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
387    type Target = SharedContext<'f, 'sess, S>;
388
389    fn deref(&self) -> &Self::Target {
390        &self.shared
391    }
392}
393
394impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
395    fn deref_mut(&mut self) -> &mut Self::Target {
396        &mut self.shared
397    }
398}
399
400/// Context given to every attribute parser during finalization.
401///
402/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
403/// errors, for example.
404pub(crate) struct SharedContext<'p, 'sess, S: Stage> {
405    /// The parse context, gives access to the session and the
406    /// diagnostics context.
407    pub(crate) cx: &'p mut AttributeParser<'sess, S>,
408    /// The span of the syntactical component this attribute was applied to
409    pub(crate) target_span: Span,
410    /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
411    pub(crate) target_id: S::Id,
412
413    emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
414}
415
416/// Context given to every attribute parser during finalization.
417///
418/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
419/// errors, for example.
420pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
421    pub(crate) shared: SharedContext<'p, 'sess, S>,
422
423    /// A list of all attribute on this syntax node.
424    ///
425    /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
426    ///
427    /// Usually, you should use normal attribute parsing logic instead,
428    /// especially when making a *denylist* of other attributes.
429    pub(crate) all_attrs: &'p [PathParser<'p>],
430}
431
432impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
433    type Target = SharedContext<'p, 'sess, S>;
434
435    fn deref(&self) -> &Self::Target {
436        &self.shared
437    }
438}
439
440impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
441    fn deref_mut(&mut self) -> &mut Self::Target {
442        &mut self.shared
443    }
444}
445
446impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
447    type Target = AttributeParser<'sess, S>;
448
449    fn deref(&self) -> &Self::Target {
450        self.cx
451    }
452}
453
454impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
455    fn deref_mut(&mut self) -> &mut Self::Target {
456        self.cx
457    }
458}
459
460#[derive(PartialEq, Clone, Copy, Debug)]
461pub enum OmitDoc {
462    Lower,
463    Skip,
464}
465
466/// Context created once, for example as part of the ast lowering
467/// context, through which all attributes can be lowered.
468pub struct AttributeParser<'sess, S: Stage = Late> {
469    pub(crate) tools: Vec<Symbol>,
470    features: Option<&'sess Features>,
471    sess: &'sess Session,
472    stage: PhantomData<S>,
473
474    /// *Only* parse attributes with this symbol.
475    ///
476    /// Used in cases where we want the lowering infrastructure for parse just a single attribute.
477    parse_only: Option<Symbol>,
478}
479
480impl<'sess> AttributeParser<'sess, Early> {
481    /// This method allows you to parse attributes *before* you have access to features or tools.
482    /// One example where this is necessary, is to parse `feature` attributes themselves for
483    /// example.
484    ///
485    /// Try to use this as little as possible. Attributes *should* be lowered during
486    /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
487    /// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
488    ///
489    /// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
490    /// that symbol are picked out of the list of instructions and parsed. Those are returned.
491    ///
492    /// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
493    /// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
494    /// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
495    pub fn parse_limited(
496        sess: &'sess Session,
497        attrs: &[ast::Attribute],
498        sym: Symbol,
499        target_span: Span,
500        target_node_id: NodeId,
501    ) -> Option<Attribute> {
502        let mut p = Self {
503            features: None,
504            tools: Vec::new(),
505            parse_only: Some(sym),
506            sess,
507            stage: PhantomData,
508        };
509        let mut parsed = p.parse_attribute_list(
510            attrs,
511            target_span,
512            target_node_id,
513            OmitDoc::Skip,
514            std::convert::identity,
515            |_lint| {
516                panic!("can't emit lints here for now (nothing uses this atm)");
517            },
518        );
519        assert!(parsed.len() <= 1);
520
521        parsed.pop()
522    }
523}
524
525impl<'sess, S: Stage> AttributeParser<'sess, S> {
526    pub fn new(sess: &'sess Session, features: &'sess Features, tools: Vec<Symbol>) -> Self {
527        Self { features: Some(features), tools, parse_only: None, sess, stage: PhantomData }
528    }
529
530    pub(crate) fn sess(&self) -> &'sess Session {
531        &self.sess
532    }
533
534    pub(crate) fn features(&self) -> &'sess Features {
535        self.features.expect("features not available at this point in the compiler")
536    }
537
538    pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
539        self.sess().dcx()
540    }
541
542    /// Parse a list of attributes.
543    ///
544    /// `target_span` is the span of the thing this list of attributes is applied to,
545    /// and when `omit_doc` is set, doc attributes are filtered out.
546    pub fn parse_attribute_list(
547        &mut self,
548        attrs: &[ast::Attribute],
549        target_span: Span,
550        target_id: S::Id,
551        omit_doc: OmitDoc,
552
553        lower_span: impl Copy + Fn(Span) -> Span,
554        mut emit_lint: impl FnMut(AttributeLint<S::Id>),
555    ) -> Vec<Attribute> {
556        let mut attributes = Vec::new();
557        let mut attr_paths = Vec::new();
558
559        for attr in attrs {
560            // If we're only looking for a single attribute, skip all the ones we don't care about.
561            if let Some(expected) = self.parse_only {
562                if !attr.has_name(expected) {
563                    continue;
564                }
565            }
566
567            // Sometimes, for example for `#![doc = include_str!("readme.md")]`,
568            // doc still contains a non-literal. You might say, when we're lowering attributes
569            // that's expanded right? But no, sometimes, when parsing attributes on macros,
570            // we already use the lowering logic and these are still there. So, when `omit_doc`
571            // is set we *also* want to ignore these.
572            if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
573                continue;
574            }
575
576            match &attr.kind {
577                ast::AttrKind::DocComment(comment_kind, symbol) => {
578                    if omit_doc == OmitDoc::Skip {
579                        continue;
580                    }
581
582                    attributes.push(Attribute::Parsed(AttributeKind::DocComment {
583                        style: attr.style,
584                        kind: *comment_kind,
585                        span: lower_span(attr.span),
586                        comment: *symbol,
587                    }))
588                }
589                // // FIXME: make doc attributes go through a proper attribute parser
590                // ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
591                //     let p = GenericMetaItemParser::from_attr(&n, self.dcx());
592                //
593                //     attributes.push(Attribute::Parsed(AttributeKind::DocComment {
594                //         style: attr.style,
595                //         kind: CommentKind::Line,
596                //         span: attr.span,
597                //         comment: p.args().name_value(),
598                //     }))
599                // }
600                ast::AttrKind::Normal(n) => {
601                    attr_paths.push(PathParser::Ast(&n.item.path));
602
603                    let parser = MetaItemParser::from_attr(n, self.dcx());
604                    let path = parser.path();
605                    let args = parser.args();
606                    let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
607
608                    if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
609                        for (template, accept) in accepts {
610                            let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
611                                shared: SharedContext {
612                                    cx: self,
613                                    target_span,
614                                    target_id,
615                                    emit_lint: &mut emit_lint,
616                                },
617                                attr_span: lower_span(attr.span),
618                                template,
619                                attr_path: path.get_attribute_path(),
620                            };
621
622                            accept(&mut cx, args)
623                        }
624                    } else {
625                        // If we're here, we must be compiling a tool attribute... Or someone
626                        // forgot to parse their fancy new attribute. Let's warn them in any case.
627                        // If you are that person, and you really think your attribute should
628                        // remain unparsed, carefully read the documentation in this module and if
629                        // you still think so you can add an exception to this assertion.
630
631                        // FIXME(jdonszelmann): convert other attributes, and check with this that
632                        // we caught em all
633                        // const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
634                        // assert!(
635                        //     self.tools.contains(&parts[0]) || true,
636                        //     // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
637                        //     "attribute {path} wasn't parsed and isn't a know tool attribute",
638                        // );
639
640                        attributes.push(Attribute::Unparsed(Box::new(AttrItem {
641                            path: AttrPath::from_ast(&n.item.path),
642                            args: self.lower_attr_args(&n.item.args, lower_span),
643                            id: HashIgnoredAttrId { attr_id: attr.id },
644                            style: attr.style,
645                            span: lower_span(attr.span),
646                        })));
647                    }
648                }
649            }
650        }
651
652        let mut parsed_attributes = Vec::new();
653        for f in &S::parsers().1 {
654            if let Some(attr) = f(&mut FinalizeContext {
655                shared: SharedContext {
656                    cx: self,
657                    target_span,
658                    target_id,
659                    emit_lint: &mut emit_lint,
660                },
661                all_attrs: &attr_paths,
662            }) {
663                parsed_attributes.push(Attribute::Parsed(attr));
664            }
665        }
666
667        attributes.extend(parsed_attributes);
668
669        attributes
670    }
671
672    fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
673        match args {
674            ast::AttrArgs::Empty => AttrArgs::Empty,
675            ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
676            // This is an inert key-value attribute - it will never be visible to macros
677            // after it gets lowered to HIR. Therefore, we can extract literals to handle
678            // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
679            ast::AttrArgs::Eq { eq_span, expr } => {
680                // In valid code the value always ends up as a single literal. Otherwise, a dummy
681                // literal suffices because the error is handled elsewhere.
682                let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
683                    && let Ok(lit) =
684                        ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
685                {
686                    lit
687                } else {
688                    let guar = self.dcx().span_delayed_bug(
689                        args.span().unwrap_or(DUMMY_SP),
690                        "expr in place where literal is expected (builtin attr parsing)",
691                    );
692                    ast::MetaItemLit {
693                        symbol: sym::dummy,
694                        suffix: None,
695                        kind: ast::LitKind::Err(guar),
696                        span: DUMMY_SP,
697                    }
698                };
699                AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
700            }
701        }
702    }
703}