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