rustc_attr_parsing/
context.rs

1use std::cell::RefCell;
2use std::collections::BTreeMap;
3use std::ops::{Deref, DerefMut};
4use std::sync::LazyLock;
5
6use private::Sealed;
7use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
8use rustc_errors::{Diag, Diagnostic, Level};
9use rustc_feature::AttributeTemplate;
10use rustc_hir::attrs::AttributeKind;
11use rustc_hir::lints::{AttributeLint, AttributeLintKind};
12use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
13use rustc_session::Session;
14use rustc_span::{ErrorGuaranteed, Span, Symbol};
15
16use crate::AttributeParser;
17use crate::attributes::allow_unstable::{
18    AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
19};
20use crate::attributes::body::CoroutineParser;
21use crate::attributes::codegen_attrs::{
22    ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
23    NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, SanitizeParser,
24    TargetFeatureParser, TrackCallerParser, UsedParser,
25};
26use crate::attributes::confusables::ConfusablesParser;
27use crate::attributes::crate_level::{
28    CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
29    RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
30};
31use crate::attributes::debugger::DebuggerViualizerParser;
32use crate::attributes::deprecation::DeprecationParser;
33use crate::attributes::dummy::DummyParser;
34use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
35use crate::attributes::link_attrs::{
36    ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
37    LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
38};
39use crate::attributes::lint_helpers::{
40    AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
41};
42use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
43use crate::attributes::macro_attrs::{
44    AllowInternalUnsafeParser, MacroEscapeParser, MacroExportParser, MacroUseParser,
45};
46use crate::attributes::must_use::MustUseParser;
47use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
48use crate::attributes::non_exhaustive::NonExhaustiveParser;
49use crate::attributes::path::PathParser as PathAttributeParser;
50use crate::attributes::proc_macro_attrs::{
51    ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
52};
53use crate::attributes::prototype::CustomMirParser;
54use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
55use crate::attributes::rustc_internal::{
56    RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser,
57    RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser,
58};
59use crate::attributes::semantics::MayDangleParser;
60use crate::attributes::stability::{
61    BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
62};
63use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
64use crate::attributes::traits::{
65    AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser,
66    DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
67    PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
68    UnsafeSpecializationMarkerParser,
69};
70use crate::attributes::transparency::TransparencyParser;
71use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
72use crate::parser::{ArgParser, PathParser};
73use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
74use crate::target_checking::AllowedTargets;
75
76type GroupType<S> = LazyLock<GroupTypeInner<S>>;
77
78pub(super) struct GroupTypeInner<S: Stage> {
79    pub(super) accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
80    pub(super) finalizers: Vec<FinalizeFn<S>>,
81}
82
83pub(super) struct GroupTypeInnerAccept<S: Stage> {
84    pub(super) template: AttributeTemplate,
85    pub(super) accept_fn: AcceptFn<S>,
86    pub(super) allowed_targets: AllowedTargets,
87}
88
89type AcceptFn<S> =
90    Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
91type FinalizeFn<S> =
92    Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
93
94macro_rules! attribute_parsers {
95    (
96        pub(crate) static $name: ident = [$($names: ty),* $(,)?];
97    ) => {
98        mod early {
99            use super::*;
100            type Combine<T> = super::Combine<T, Early>;
101            type Single<T> = super::Single<T, Early>;
102            type WithoutArgs<T> = super::WithoutArgs<T, Early>;
103
104            attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
105        }
106        mod late {
107            use super::*;
108            type Combine<T> = super::Combine<T, Late>;
109            type Single<T> = super::Single<T, Late>;
110            type WithoutArgs<T> = super::WithoutArgs<T, Late>;
111
112            attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
113        }
114    };
115    (
116        @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
117    ) => {
118        pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
119            let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
120            let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
121            $(
122                {
123                    thread_local! {
124                        static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
125                    };
126
127                    for (path, template, accept_fn) in <$names>::ATTRIBUTES {
128                        accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
129                            template: *template,
130                            accept_fn: Box::new(|cx, args| {
131                                STATE_OBJECT.with_borrow_mut(|s| {
132                                    accept_fn(s, cx, args)
133                                })
134                            }),
135                            allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
136                        });
137                    }
138
139                    finalizes.push(Box::new(|cx| {
140                        let state = STATE_OBJECT.take();
141                        state.finalize(cx)
142                    }));
143                }
144            )*
145
146            GroupTypeInner { accepters:accepts, finalizers:finalizes }
147        });
148    };
149}
150attribute_parsers!(
151    pub(crate) static ATTRIBUTE_PARSERS = [
152        // tidy-alphabetical-start
153        AlignParser,
154        AlignStaticParser,
155        BodyStabilityParser,
156        ConfusablesParser,
157        ConstStabilityParser,
158        MacroUseParser,
159        NakedParser,
160        StabilityParser,
161        UsedParser,
162        // tidy-alphabetical-end
163
164        // tidy-alphabetical-start
165        Combine<AllowConstFnUnstableParser>,
166        Combine<AllowInternalUnstableParser>,
167        Combine<DebuggerViualizerParser>,
168        Combine<ForceTargetFeatureParser>,
169        Combine<LinkParser>,
170        Combine<ReprParser>,
171        Combine<TargetFeatureParser>,
172        Combine<UnstableFeatureBoundParser>,
173        // tidy-alphabetical-end
174
175        // tidy-alphabetical-start
176        Single<CoverageParser>,
177        Single<CrateNameParser>,
178        Single<CustomMirParser>,
179        Single<DeprecationParser>,
180        Single<DummyParser>,
181        Single<ExportNameParser>,
182        Single<IgnoreParser>,
183        Single<InlineParser>,
184        Single<LinkNameParser>,
185        Single<LinkOrdinalParser>,
186        Single<LinkSectionParser>,
187        Single<LinkageParser>,
188        Single<MacroExportParser>,
189        Single<MoveSizeLimitParser>,
190        Single<MustUseParser>,
191        Single<ObjcClassParser>,
192        Single<ObjcSelectorParser>,
193        Single<OptimizeParser>,
194        Single<PathAttributeParser>,
195        Single<PatternComplexityLimitParser>,
196        Single<ProcMacroDeriveParser>,
197        Single<RecursionLimitParser>,
198        Single<RustcBuiltinMacroParser>,
199        Single<RustcForceInlineParser>,
200        Single<RustcLayoutScalarValidRangeEndParser>,
201        Single<RustcLayoutScalarValidRangeStartParser>,
202        Single<RustcObjectLifetimeDefaultParser>,
203        Single<RustcSimdMonomorphizeLaneLimitParser>,
204        Single<SanitizeParser>,
205        Single<ShouldPanicParser>,
206        Single<SkipDuringMethodDispatchParser>,
207        Single<TransparencyParser>,
208        Single<TypeLengthLimitParser>,
209        Single<WithoutArgs<AllowIncoherentImplParser>>,
210        Single<WithoutArgs<AllowInternalUnsafeParser>>,
211        Single<WithoutArgs<AsPtrParser>>,
212        Single<WithoutArgs<AutomaticallyDerivedParser>>,
213        Single<WithoutArgs<CoinductiveParser>>,
214        Single<WithoutArgs<ColdParser>>,
215        Single<WithoutArgs<ConstContinueParser>>,
216        Single<WithoutArgs<ConstStabilityIndirectParser>>,
217        Single<WithoutArgs<ConstTraitParser>>,
218        Single<WithoutArgs<CoroutineParser>>,
219        Single<WithoutArgs<DenyExplicitImplParser>>,
220        Single<WithoutArgs<DoNotImplementViaObjectParser>>,
221        Single<WithoutArgs<ExportStableParser>>,
222        Single<WithoutArgs<FfiConstParser>>,
223        Single<WithoutArgs<FfiPureParser>>,
224        Single<WithoutArgs<FundamentalParser>>,
225        Single<WithoutArgs<LoopMatchParser>>,
226        Single<WithoutArgs<MacroEscapeParser>>,
227        Single<WithoutArgs<MarkerParser>>,
228        Single<WithoutArgs<MayDangleParser>>,
229        Single<WithoutArgs<NoCoreParser>>,
230        Single<WithoutArgs<NoImplicitPreludeParser>>,
231        Single<WithoutArgs<NoMangleParser>>,
232        Single<WithoutArgs<NoStdParser>>,
233        Single<WithoutArgs<NonExhaustiveParser>>,
234        Single<WithoutArgs<ParenSugarParser>>,
235        Single<WithoutArgs<PassByValueParser>>,
236        Single<WithoutArgs<PointeeParser>>,
237        Single<WithoutArgs<ProcMacroAttributeParser>>,
238        Single<WithoutArgs<ProcMacroParser>>,
239        Single<WithoutArgs<PubTransparentParser>>,
240        Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
241        Single<WithoutArgs<RustcMainParser>>,
242        Single<WithoutArgs<SpecializationTraitParser>>,
243        Single<WithoutArgs<StdInternalSymbolParser>>,
244        Single<WithoutArgs<TrackCallerParser>>,
245        Single<WithoutArgs<TypeConstParser>>,
246        Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
247        // tidy-alphabetical-end
248    ];
249);
250
251mod private {
252    pub trait Sealed {}
253    impl Sealed for super::Early {}
254    impl Sealed for super::Late {}
255}
256
257// allow because it's a sealed trait
258#[allow(private_interfaces)]
259pub trait Stage: Sized + 'static + Sealed {
260    type Id: Copy;
261
262    fn parsers() -> &'static GroupType<Self>;
263
264    fn emit_err<'sess>(
265        &self,
266        sess: &'sess Session,
267        diag: impl for<'x> Diagnostic<'x>,
268    ) -> ErrorGuaranteed;
269
270    fn should_emit(&self) -> ShouldEmit;
271
272    fn id_is_crate_root(id: Self::Id) -> bool;
273}
274
275// allow because it's a sealed trait
276#[allow(private_interfaces)]
277impl Stage for Early {
278    type Id = NodeId;
279
280    fn parsers() -> &'static GroupType<Self> {
281        &early::ATTRIBUTE_PARSERS
282    }
283    fn emit_err<'sess>(
284        &self,
285        sess: &'sess Session,
286        diag: impl for<'x> Diagnostic<'x>,
287    ) -> ErrorGuaranteed {
288        self.should_emit().emit_err(sess.dcx().create_err(diag))
289    }
290
291    fn should_emit(&self) -> ShouldEmit {
292        self.emit_errors
293    }
294
295    fn id_is_crate_root(id: Self::Id) -> bool {
296        id == CRATE_NODE_ID
297    }
298}
299
300// allow because it's a sealed trait
301#[allow(private_interfaces)]
302impl Stage for Late {
303    type Id = HirId;
304
305    fn parsers() -> &'static GroupType<Self> {
306        &late::ATTRIBUTE_PARSERS
307    }
308    fn emit_err<'sess>(
309        &self,
310        tcx: &'sess Session,
311        diag: impl for<'x> Diagnostic<'x>,
312    ) -> ErrorGuaranteed {
313        tcx.dcx().emit_err(diag)
314    }
315
316    fn should_emit(&self) -> ShouldEmit {
317        ShouldEmit::ErrorsAndLints
318    }
319
320    fn id_is_crate_root(id: Self::Id) -> bool {
321        id == CRATE_HIR_ID
322    }
323}
324
325/// used when parsing attributes for miscellaneous things *before* ast lowering
326pub struct Early {
327    /// Whether to emit errors or delay them as a bug
328    /// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
329    /// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
330    pub emit_errors: ShouldEmit,
331}
332/// used when parsing attributes during ast lowering
333pub struct Late;
334
335/// Context given to every attribute parser when accepting
336///
337/// Gives [`AttributeParser`]s enough information to create errors, for example.
338pub struct AcceptContext<'f, 'sess, S: Stage> {
339    pub(crate) shared: SharedContext<'f, 'sess, S>,
340
341    /// The outer span of the attribute currently being parsed
342    /// #[attribute(...)]
343    /// ^^^^^^^^^^^^^^^^^ outer span
344    /// For attributes in `cfg_attr`, the outer span and inner spans are equal.
345    pub(crate) attr_span: Span,
346    /// The inner span of the attribute currently being parsed
347    /// #[attribute(...)]
348    ///   ^^^^^^^^^^^^^^  inner span
349    pub(crate) inner_span: Span,
350
351    /// Whether it is an inner or outer attribute
352    pub(crate) attr_style: AttrStyle,
353
354    /// The expected structure of the attribute.
355    ///
356    /// Used in reporting errors to give a hint to users what the attribute *should* look like.
357    pub(crate) template: &'f AttributeTemplate,
358
359    /// The name of the attribute we're currently accepting.
360    pub(crate) attr_path: AttrPath,
361}
362
363impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
364    pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
365        self.stage.emit_err(&self.sess, diag)
366    }
367
368    /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
369    /// must be delayed until after HIR is built. This method will take care of the details of
370    /// that.
371    pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
372        if !matches!(
373            self.stage.should_emit(),
374            ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
375        ) {
376            return;
377        }
378        let id = self.target_id;
379        (self.emit_lint)(AttributeLint { id, span, kind: lint });
380    }
381
382    pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
383        self.emit_lint(
384            AttributeLintKind::UnusedDuplicate {
385                this: unused_span,
386                other: used_span,
387                warning: false,
388            },
389            unused_span,
390        )
391    }
392
393    pub(crate) fn warn_unused_duplicate_future_error(
394        &mut self,
395        used_span: Span,
396        unused_span: Span,
397    ) {
398        self.emit_lint(
399            AttributeLintKind::UnusedDuplicate {
400                this: unused_span,
401                other: used_span,
402                warning: true,
403            },
404            unused_span,
405        )
406    }
407}
408
409impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
410    pub(crate) fn unknown_key(
411        &self,
412        span: Span,
413        found: String,
414        options: &'static [&'static str],
415    ) -> ErrorGuaranteed {
416        self.emit_err(UnknownMetaItem { span, item: found, expected: options })
417    }
418
419    /// error that a string literal was expected.
420    /// You can optionally give the literal you did find (which you found not to be a string literal)
421    /// which can make better errors. For example, if the literal was a byte string it will suggest
422    /// removing the `b` prefix.
423    pub(crate) fn expected_string_literal(
424        &self,
425        span: Span,
426        actual_literal: Option<&MetaItemLit>,
427    ) -> ErrorGuaranteed {
428        self.emit_err(AttributeParseError {
429            span,
430            attr_span: self.attr_span,
431            template: self.template.clone(),
432            attribute: self.attr_path.clone(),
433            reason: AttributeParseErrorReason::ExpectedStringLiteral {
434                byte_string: actual_literal.and_then(|i| {
435                    i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
436                }),
437            },
438            suggestions: self.suggestions(),
439        })
440    }
441
442    pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
443        self.emit_err(AttributeParseError {
444            span,
445            attr_span: self.attr_span,
446            template: self.template.clone(),
447            attribute: self.attr_path.clone(),
448            reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
449            suggestions: self.suggestions(),
450        })
451    }
452
453    pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
454        self.emit_err(AttributeParseError {
455            span,
456            attr_span: self.attr_span,
457            template: self.template.clone(),
458            attribute: self.attr_path.clone(),
459            reason: AttributeParseErrorReason::ExpectedList,
460            suggestions: self.suggestions(),
461        })
462    }
463
464    pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
465        self.emit_err(AttributeParseError {
466            span: args_span,
467            attr_span: self.attr_span,
468            template: self.template.clone(),
469            attribute: self.attr_path.clone(),
470            reason: AttributeParseErrorReason::ExpectedNoArgs,
471            suggestions: self.suggestions(),
472        })
473    }
474
475    /// emit an error that a `name` was expected here
476    pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
477        self.emit_err(AttributeParseError {
478            span,
479            attr_span: self.attr_span,
480            template: self.template.clone(),
481            attribute: self.attr_path.clone(),
482            reason: AttributeParseErrorReason::ExpectedIdentifier,
483            suggestions: self.suggestions(),
484        })
485    }
486
487    /// emit an error that a `name = value` pair was expected at this span. The symbol can be given for
488    /// a nicer error message talking about the specific name that was found lacking a value.
489    pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
490        self.emit_err(AttributeParseError {
491            span,
492            attr_span: self.attr_span,
493            template: self.template.clone(),
494            attribute: self.attr_path.clone(),
495            reason: AttributeParseErrorReason::ExpectedNameValue(name),
496            suggestions: self.suggestions(),
497        })
498    }
499
500    /// emit an error that a `name = value` pair was found where that name was already seen.
501    pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
502        self.emit_err(AttributeParseError {
503            span,
504            attr_span: self.attr_span,
505            template: self.template.clone(),
506            attribute: self.attr_path.clone(),
507            reason: AttributeParseErrorReason::DuplicateKey(key),
508            suggestions: self.suggestions(),
509        })
510    }
511
512    /// an error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
513    /// was expected *not* to be a literal, but instead a meta item.
514    pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
515        self.emit_err(AttributeParseError {
516            span,
517            attr_span: self.attr_span,
518            template: self.template.clone(),
519            attribute: self.attr_path.clone(),
520            reason: AttributeParseErrorReason::UnexpectedLiteral,
521            suggestions: self.suggestions(),
522        })
523    }
524
525    pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
526        self.emit_err(AttributeParseError {
527            span,
528            attr_span: self.attr_span,
529            template: self.template.clone(),
530            attribute: self.attr_path.clone(),
531            reason: AttributeParseErrorReason::ExpectedSingleArgument,
532            suggestions: self.suggestions(),
533        })
534    }
535
536    pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
537        self.emit_err(AttributeParseError {
538            span,
539            attr_span: self.attr_span,
540            template: self.template.clone(),
541            attribute: self.attr_path.clone(),
542            reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
543            suggestions: self.suggestions(),
544        })
545    }
546
547    /// produces an error along the lines of `expected one of [foo, meow]`
548    pub(crate) fn expected_specific_argument(
549        &self,
550        span: Span,
551        possibilities: &[Symbol],
552    ) -> ErrorGuaranteed {
553        self.emit_err(AttributeParseError {
554            span,
555            attr_span: self.attr_span,
556            template: self.template.clone(),
557            attribute: self.attr_path.clone(),
558            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
559                possibilities,
560                strings: false,
561                list: false,
562            },
563            suggestions: self.suggestions(),
564        })
565    }
566
567    /// produces an error along the lines of `expected one of [foo, meow] as an argument`.
568    /// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument).
569    pub(crate) fn expected_specific_argument_and_list(
570        &self,
571        span: Span,
572        possibilities: &[Symbol],
573    ) -> ErrorGuaranteed {
574        self.emit_err(AttributeParseError {
575            span,
576            attr_span: self.attr_span,
577            template: self.template.clone(),
578            attribute: self.attr_path.clone(),
579            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
580                possibilities,
581                strings: false,
582                list: true,
583            },
584            suggestions: self.suggestions(),
585        })
586    }
587
588    /// produces an error along the lines of `expected one of ["foo", "meow"]`
589    pub(crate) fn expected_specific_argument_strings(
590        &self,
591        span: Span,
592        possibilities: &[Symbol],
593    ) -> ErrorGuaranteed {
594        self.emit_err(AttributeParseError {
595            span,
596            attr_span: self.attr_span,
597            template: self.template.clone(),
598            attribute: self.attr_path.clone(),
599            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
600                possibilities,
601                strings: true,
602                list: false,
603            },
604            suggestions: self.suggestions(),
605        })
606    }
607
608    pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
609        let attr_path = self.attr_path.clone();
610        let valid_without_list = self.template.word;
611        self.emit_lint(
612            AttributeLintKind::EmptyAttribute { first_span: span, attr_path, valid_without_list },
613            span,
614        );
615    }
616
617    pub(crate) fn suggestions(&self) -> Vec<String> {
618        // If the outer and inner spans are equal, we are parsing an attribute from `cfg_attr`,
619        // So don't display an attribute style in the suggestions
620        let style = (self.attr_span != self.inner_span).then_some(self.attr_style);
621        self.template.suggestions(style, &self.attr_path)
622    }
623}
624
625impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
626    type Target = SharedContext<'f, 'sess, S>;
627
628    fn deref(&self) -> &Self::Target {
629        &self.shared
630    }
631}
632
633impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
634    fn deref_mut(&mut self) -> &mut Self::Target {
635        &mut self.shared
636    }
637}
638
639/// Context given to every attribute parser during finalization.
640///
641/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
642/// errors, for example.
643pub struct SharedContext<'p, 'sess, S: Stage> {
644    /// The parse context, gives access to the session and the
645    /// diagnostics context.
646    pub(crate) cx: &'p mut AttributeParser<'sess, S>,
647    /// The span of the syntactical component this attribute was applied to
648    pub(crate) target_span: Span,
649    /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
650    pub(crate) target_id: S::Id,
651
652    pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
653}
654
655/// Context given to every attribute parser during finalization.
656///
657/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
658/// errors, for example.
659pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
660    pub(crate) shared: SharedContext<'p, 'sess, S>,
661
662    /// A list of all attribute on this syntax node.
663    ///
664    /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
665    ///
666    /// Usually, you should use normal attribute parsing logic instead,
667    /// especially when making a *denylist* of other attributes.
668    pub(crate) all_attrs: &'p [PathParser<'p>],
669}
670
671impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
672    type Target = SharedContext<'p, 'sess, S>;
673
674    fn deref(&self) -> &Self::Target {
675        &self.shared
676    }
677}
678
679impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
680    fn deref_mut(&mut self) -> &mut Self::Target {
681        &mut self.shared
682    }
683}
684
685impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
686    type Target = AttributeParser<'sess, S>;
687
688    fn deref(&self) -> &Self::Target {
689        self.cx
690    }
691}
692
693impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
694    fn deref_mut(&mut self) -> &mut Self::Target {
695        self.cx
696    }
697}
698
699#[derive(PartialEq, Clone, Copy, Debug)]
700pub enum OmitDoc {
701    Lower,
702    Skip,
703}
704
705#[derive(Copy, Clone, Debug)]
706pub enum ShouldEmit {
707    /// The operations will emit errors, and lints, and errors are fatal.
708    ///
709    /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
710    /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
711    EarlyFatal { also_emit_lints: bool },
712    /// The operation will emit errors and lints.
713    /// This is usually what you need.
714    ErrorsAndLints,
715    /// The operation will emit *not* errors and lints.
716    /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`.
717    Nothing,
718}
719
720impl ShouldEmit {
721    pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
722        match self {
723            ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
724            ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
725            ShouldEmit::ErrorsAndLints => diag.emit(),
726            ShouldEmit::Nothing => diag.delay_as_bug(),
727        }
728    }
729}