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