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, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
29    RecursionLimitParser, 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<NoCoreParser>>,
227        Single<WithoutArgs<NoImplicitPreludeParser>>,
228        Single<WithoutArgs<NoMangleParser>>,
229        Single<WithoutArgs<NoStdParser>>,
230        Single<WithoutArgs<NonExhaustiveParser>>,
231        Single<WithoutArgs<ParenSugarParser>>,
232        Single<WithoutArgs<PassByValueParser>>,
233        Single<WithoutArgs<PointeeParser>>,
234        Single<WithoutArgs<ProcMacroAttributeParser>>,
235        Single<WithoutArgs<ProcMacroParser>>,
236        Single<WithoutArgs<PubTransparentParser>>,
237        Single<WithoutArgs<SpecializationTraitParser>>,
238        Single<WithoutArgs<StdInternalSymbolParser>>,
239        Single<WithoutArgs<TrackCallerParser>>,
240        Single<WithoutArgs<TypeConstParser>>,
241        Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
242        // tidy-alphabetical-end
243    ];
244);
245
246mod private {
247    pub trait Sealed {}
248    impl Sealed for super::Early {}
249    impl Sealed for super::Late {}
250}
251
252// allow because it's a sealed trait
253#[allow(private_interfaces)]
254pub trait Stage: Sized + 'static + Sealed {
255    type Id: Copy;
256
257    fn parsers() -> &'static GroupType<Self>;
258
259    fn emit_err<'sess>(
260        &self,
261        sess: &'sess Session,
262        diag: impl for<'x> Diagnostic<'x>,
263    ) -> ErrorGuaranteed;
264
265    fn should_emit(&self) -> ShouldEmit;
266
267    fn id_is_crate_root(id: Self::Id) -> bool;
268}
269
270// allow because it's a sealed trait
271#[allow(private_interfaces)]
272impl Stage for Early {
273    type Id = NodeId;
274
275    fn parsers() -> &'static GroupType<Self> {
276        &early::ATTRIBUTE_PARSERS
277    }
278    fn emit_err<'sess>(
279        &self,
280        sess: &'sess Session,
281        diag: impl for<'x> Diagnostic<'x>,
282    ) -> ErrorGuaranteed {
283        self.should_emit().emit_err(sess.dcx().create_err(diag))
284    }
285
286    fn should_emit(&self) -> ShouldEmit {
287        self.emit_errors
288    }
289
290    fn id_is_crate_root(id: Self::Id) -> bool {
291        id == CRATE_NODE_ID
292    }
293}
294
295// allow because it's a sealed trait
296#[allow(private_interfaces)]
297impl Stage for Late {
298    type Id = HirId;
299
300    fn parsers() -> &'static GroupType<Self> {
301        &late::ATTRIBUTE_PARSERS
302    }
303    fn emit_err<'sess>(
304        &self,
305        tcx: &'sess Session,
306        diag: impl for<'x> Diagnostic<'x>,
307    ) -> ErrorGuaranteed {
308        tcx.dcx().emit_err(diag)
309    }
310
311    fn should_emit(&self) -> ShouldEmit {
312        ShouldEmit::ErrorsAndLints
313    }
314
315    fn id_is_crate_root(id: Self::Id) -> bool {
316        id == CRATE_HIR_ID
317    }
318}
319
320/// used when parsing attributes for miscellaneous things *before* ast lowering
321pub struct Early {
322    /// Whether to emit errors or delay them as a bug
323    /// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
324    /// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
325    pub emit_errors: ShouldEmit,
326}
327/// used when parsing attributes during ast lowering
328pub struct Late;
329
330/// Context given to every attribute parser when accepting
331///
332/// Gives [`AttributeParser`]s enough information to create errors, for example.
333pub struct AcceptContext<'f, 'sess, S: Stage> {
334    pub(crate) shared: SharedContext<'f, 'sess, S>,
335    /// The span of the attribute currently being parsed
336    pub(crate) attr_span: Span,
337
338    /// Whether it is an inner or outer attribute
339    pub(crate) attr_style: AttrStyle,
340
341    /// The expected structure of the attribute.
342    ///
343    /// Used in reporting errors to give a hint to users what the attribute *should* look like.
344    pub(crate) template: &'f AttributeTemplate,
345
346    /// The name of the attribute we're currently accepting.
347    pub(crate) attr_path: AttrPath,
348}
349
350impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
351    pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
352        self.stage.emit_err(&self.sess, diag)
353    }
354
355    /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
356    /// must be delayed until after HIR is built. This method will take care of the details of
357    /// that.
358    pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
359        if !matches!(
360            self.stage.should_emit(),
361            ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
362        ) {
363            return;
364        }
365        let id = self.target_id;
366        (self.emit_lint)(AttributeLint { id, span, kind: lint });
367    }
368
369    pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
370        self.emit_lint(
371            AttributeLintKind::UnusedDuplicate {
372                this: unused_span,
373                other: used_span,
374                warning: false,
375            },
376            unused_span,
377        )
378    }
379
380    pub(crate) fn warn_unused_duplicate_future_error(
381        &mut self,
382        used_span: Span,
383        unused_span: Span,
384    ) {
385        self.emit_lint(
386            AttributeLintKind::UnusedDuplicate {
387                this: unused_span,
388                other: used_span,
389                warning: true,
390            },
391            unused_span,
392        )
393    }
394}
395
396impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
397    pub(crate) fn unknown_key(
398        &self,
399        span: Span,
400        found: String,
401        options: &'static [&'static str],
402    ) -> ErrorGuaranteed {
403        self.emit_err(UnknownMetaItem { span, item: found, expected: options })
404    }
405
406    /// error that a string literal was expected.
407    /// You can optionally give the literal you did find (which you found not to be a string literal)
408    /// which can make better errors. For example, if the literal was a byte string it will suggest
409    /// removing the `b` prefix.
410    pub(crate) fn expected_string_literal(
411        &self,
412        span: Span,
413        actual_literal: Option<&MetaItemLit>,
414    ) -> ErrorGuaranteed {
415        self.emit_err(AttributeParseError {
416            span,
417            attr_span: self.attr_span,
418            template: self.template.clone(),
419            attribute: self.attr_path.clone(),
420            reason: AttributeParseErrorReason::ExpectedStringLiteral {
421                byte_string: actual_literal.and_then(|i| {
422                    i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
423                }),
424            },
425            attr_style: self.attr_style,
426        })
427    }
428
429    pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
430        self.emit_err(AttributeParseError {
431            span,
432            attr_span: self.attr_span,
433            template: self.template.clone(),
434            attribute: self.attr_path.clone(),
435            reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
436            attr_style: self.attr_style,
437        })
438    }
439
440    pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
441        self.emit_err(AttributeParseError {
442            span,
443            attr_span: self.attr_span,
444            template: self.template.clone(),
445            attribute: self.attr_path.clone(),
446            reason: AttributeParseErrorReason::ExpectedList,
447            attr_style: self.attr_style,
448        })
449    }
450
451    pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
452        self.emit_err(AttributeParseError {
453            span: args_span,
454            attr_span: self.attr_span,
455            template: self.template.clone(),
456            attribute: self.attr_path.clone(),
457            reason: AttributeParseErrorReason::ExpectedNoArgs,
458            attr_style: self.attr_style,
459        })
460    }
461
462    /// emit an error that a `name` was expected here
463    pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
464        self.emit_err(AttributeParseError {
465            span,
466            attr_span: self.attr_span,
467            template: self.template.clone(),
468            attribute: self.attr_path.clone(),
469            reason: AttributeParseErrorReason::ExpectedIdentifier,
470            attr_style: self.attr_style,
471        })
472    }
473
474    /// emit an error that a `name = value` pair was expected at this span. The symbol can be given for
475    /// a nicer error message talking about the specific name that was found lacking a value.
476    pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> 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::ExpectedNameValue(name),
483            attr_style: self.attr_style,
484        })
485    }
486
487    /// emit an error that a `name = value` pair was found where that name was already seen.
488    pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
489        self.emit_err(AttributeParseError {
490            span,
491            attr_span: self.attr_span,
492            template: self.template.clone(),
493            attribute: self.attr_path.clone(),
494            reason: AttributeParseErrorReason::DuplicateKey(key),
495            attr_style: self.attr_style,
496        })
497    }
498
499    /// an error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
500    /// was expected *not* to be a literal, but instead a meta item.
501    pub(crate) fn unexpected_literal(&self, span: Span) -> 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::UnexpectedLiteral,
508            attr_style: self.attr_style,
509        })
510    }
511
512    pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
513        self.emit_err(AttributeParseError {
514            span,
515            attr_span: self.attr_span,
516            template: self.template.clone(),
517            attribute: self.attr_path.clone(),
518            reason: AttributeParseErrorReason::ExpectedSingleArgument,
519            attr_style: self.attr_style,
520        })
521    }
522
523    pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
524        self.emit_err(AttributeParseError {
525            span,
526            attr_span: self.attr_span,
527            template: self.template.clone(),
528            attribute: self.attr_path.clone(),
529            reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
530            attr_style: self.attr_style,
531        })
532    }
533
534    /// produces an error along the lines of `expected one of [foo, meow]`
535    pub(crate) fn expected_specific_argument(
536        &self,
537        span: Span,
538        possibilities: &[Symbol],
539    ) -> ErrorGuaranteed {
540        self.emit_err(AttributeParseError {
541            span,
542            attr_span: self.attr_span,
543            template: self.template.clone(),
544            attribute: self.attr_path.clone(),
545            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
546                possibilities,
547                strings: false,
548                list: false,
549            },
550            attr_style: self.attr_style,
551        })
552    }
553
554    /// produces an error along the lines of `expected one of [foo, meow] as an argument`.
555    /// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument).
556    pub(crate) fn expected_specific_argument_and_list(
557        &self,
558        span: Span,
559        possibilities: &[Symbol],
560    ) -> ErrorGuaranteed {
561        self.emit_err(AttributeParseError {
562            span,
563            attr_span: self.attr_span,
564            template: self.template.clone(),
565            attribute: self.attr_path.clone(),
566            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
567                possibilities,
568                strings: false,
569                list: true,
570            },
571            attr_style: self.attr_style,
572        })
573    }
574
575    /// produces an error along the lines of `expected one of ["foo", "meow"]`
576    pub(crate) fn expected_specific_argument_strings(
577        &self,
578        span: Span,
579        possibilities: &[Symbol],
580    ) -> ErrorGuaranteed {
581        self.emit_err(AttributeParseError {
582            span,
583            attr_span: self.attr_span,
584            template: self.template.clone(),
585            attribute: self.attr_path.clone(),
586            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
587                possibilities,
588                strings: true,
589                list: false,
590            },
591            attr_style: self.attr_style,
592        })
593    }
594
595    pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
596        self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
597    }
598}
599
600impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
601    type Target = SharedContext<'f, 'sess, S>;
602
603    fn deref(&self) -> &Self::Target {
604        &self.shared
605    }
606}
607
608impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
609    fn deref_mut(&mut self) -> &mut Self::Target {
610        &mut self.shared
611    }
612}
613
614/// Context given to every attribute parser during finalization.
615///
616/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
617/// errors, for example.
618pub struct SharedContext<'p, 'sess, S: Stage> {
619    /// The parse context, gives access to the session and the
620    /// diagnostics context.
621    pub(crate) cx: &'p mut AttributeParser<'sess, S>,
622    /// The span of the syntactical component this attribute was applied to
623    pub(crate) target_span: Span,
624    /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
625    pub(crate) target_id: S::Id,
626
627    pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
628}
629
630/// Context given to every attribute parser during finalization.
631///
632/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
633/// errors, for example.
634pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
635    pub(crate) shared: SharedContext<'p, 'sess, S>,
636
637    /// A list of all attribute on this syntax node.
638    ///
639    /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
640    ///
641    /// Usually, you should use normal attribute parsing logic instead,
642    /// especially when making a *denylist* of other attributes.
643    pub(crate) all_attrs: &'p [PathParser<'p>],
644}
645
646impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
647    type Target = SharedContext<'p, 'sess, S>;
648
649    fn deref(&self) -> &Self::Target {
650        &self.shared
651    }
652}
653
654impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
655    fn deref_mut(&mut self) -> &mut Self::Target {
656        &mut self.shared
657    }
658}
659
660impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
661    type Target = AttributeParser<'sess, S>;
662
663    fn deref(&self) -> &Self::Target {
664        self.cx
665    }
666}
667
668impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
669    fn deref_mut(&mut self) -> &mut Self::Target {
670        self.cx
671    }
672}
673
674#[derive(PartialEq, Clone, Copy, Debug)]
675pub enum OmitDoc {
676    Lower,
677    Skip,
678}
679
680#[derive(Copy, Clone, Debug)]
681pub enum ShouldEmit {
682    /// The operations will emit errors, and lints, and errors are fatal.
683    ///
684    /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
685    /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
686    EarlyFatal { also_emit_lints: bool },
687    /// The operation will emit errors and lints.
688    /// This is usually what you need.
689    ErrorsAndLints,
690    /// The operation will emit *not* errors and lints.
691    /// Use this if you are *sure* that this operation will be called at a different time with `ShouldEmit::ErrorsAndLints`.
692    Nothing,
693}
694
695impl ShouldEmit {
696    pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
697        match self {
698            ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
699            ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
700            ShouldEmit::ErrorsAndLints => diag.emit(),
701            ShouldEmit::Nothing => diag.delay_as_bug(),
702        }
703    }
704}