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