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