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;
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, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
24 RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser,
25 TrackCallerParser, UsedParser,
26};
27use crate::attributes::confusables::ConfusablesParser;
28use crate::attributes::crate_level::{
29 CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
30 RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
31};
32use crate::attributes::debugger::DebuggerViualizerParser;
33use crate::attributes::deprecation::DeprecationParser;
34use crate::attributes::dummy::DummyParser;
35use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
36use crate::attributes::link_attrs::{
37 ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
38 LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
39};
40use crate::attributes::lint_helpers::{
41 AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
42};
43use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
44use crate::attributes::macro_attrs::{
45 AllowInternalUnsafeParser, MacroEscapeParser, MacroExportParser, MacroUseParser,
46};
47use crate::attributes::must_use::MustUseParser;
48use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
49use crate::attributes::non_exhaustive::NonExhaustiveParser;
50use crate::attributes::path::PathParser as PathAttributeParser;
51use crate::attributes::pin_v2::PinV2Parser;
52use crate::attributes::proc_macro_attrs::{
53 ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
54};
55use crate::attributes::prototype::CustomMirParser;
56use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
57use crate::attributes::rustc_internal::{
58 RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser,
59 RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser,
60};
61use crate::attributes::semantics::MayDangleParser;
62use crate::attributes::stability::{
63 BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
64};
65use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
66use crate::attributes::traits::{
67 AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser,
68 DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
69 PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
70 UnsafeSpecializationMarkerParser,
71};
72use crate::attributes::transparency::TransparencyParser;
73use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
74use crate::parser::{ArgParser, PathParser};
75use crate::session_diagnostics::{
76 AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem,
77};
78use crate::target_checking::AllowedTargets;
79
80type GroupType<S> = LazyLock<GroupTypeInner<S>>;
81
82pub(super) struct GroupTypeInner<S: Stage> {
83 pub(super) accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
84 pub(super) finalizers: Vec<FinalizeFn<S>>,
85}
86
87pub(super) struct GroupTypeInnerAccept<S: Stage> {
88 pub(super) template: AttributeTemplate,
89 pub(super) accept_fn: AcceptFn<S>,
90 pub(super) allowed_targets: AllowedTargets,
91}
92
93type AcceptFn<S> =
94 Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess, S>, &ArgParser<'a>) + Send + Sync>;
95type FinalizeFn<S> =
96 Box<dyn Send + Sync + Fn(&mut FinalizeContext<'_, '_, S>) -> Option<AttributeKind>>;
97
98macro_rules! attribute_parsers {
99 (
100 pub(crate) static $name: ident = [$($names: ty),* $(,)?];
101 ) => {
102 mod early {
103 use super::*;
104 type Combine<T> = super::Combine<T, Early>;
105 type Single<T> = super::Single<T, Early>;
106 type WithoutArgs<T> = super::WithoutArgs<T, Early>;
107
108 attribute_parsers!(@[Early] pub(crate) static $name = [$($names),*];);
109 }
110 mod late {
111 use super::*;
112 type Combine<T> = super::Combine<T, Late>;
113 type Single<T> = super::Single<T, Late>;
114 type WithoutArgs<T> = super::WithoutArgs<T, Late>;
115
116 attribute_parsers!(@[Late] pub(crate) static $name = [$($names),*];);
117 }
118 };
119 (
120 @[$stage: ty] pub(crate) static $name: ident = [$($names: ty),* $(,)?];
121 ) => {
122 pub(crate) static $name: GroupType<$stage> = LazyLock::new(|| {
123 let mut accepts = BTreeMap::<_, Vec<GroupTypeInnerAccept<$stage>>>::new();
124 let mut finalizes = Vec::<FinalizeFn<$stage>>::new();
125 $(
126 {
127 thread_local! {
128 static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());
129 };
130
131 for (path, template, accept_fn) in <$names>::ATTRIBUTES {
132 accepts.entry(*path).or_default().push(GroupTypeInnerAccept {
133 template: *template,
134 accept_fn: Box::new(|cx, args| {
135 STATE_OBJECT.with_borrow_mut(|s| {
136 accept_fn(s, cx, args)
137 })
138 }),
139 allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
140 });
141 }
142
143 finalizes.push(Box::new(|cx| {
144 let state = STATE_OBJECT.take();
145 state.finalize(cx)
146 }));
147 }
148 )*
149
150 GroupTypeInner { accepters:accepts, finalizers:finalizes }
151 });
152 };
153}
154attribute_parsers!(
155 pub(crate) static ATTRIBUTE_PARSERS = [
156 AlignParser,
158 AlignStaticParser,
159 BodyStabilityParser,
160 ConfusablesParser,
161 ConstStabilityParser,
162 MacroUseParser,
163 NakedParser,
164 StabilityParser,
165 UsedParser,
166 Combine<AllowConstFnUnstableParser>,
170 Combine<AllowInternalUnstableParser>,
171 Combine<DebuggerViualizerParser>,
172 Combine<ForceTargetFeatureParser>,
173 Combine<LinkParser>,
174 Combine<ReprParser>,
175 Combine<TargetFeatureParser>,
176 Combine<UnstableFeatureBoundParser>,
177 Single<CoverageParser>,
181 Single<CrateNameParser>,
182 Single<CustomMirParser>,
183 Single<DeprecationParser>,
184 Single<DummyParser>,
185 Single<ExportNameParser>,
186 Single<IgnoreParser>,
187 Single<InlineParser>,
188 Single<LinkNameParser>,
189 Single<LinkOrdinalParser>,
190 Single<LinkSectionParser>,
191 Single<LinkageParser>,
192 Single<MacroExportParser>,
193 Single<MoveSizeLimitParser>,
194 Single<MustUseParser>,
195 Single<ObjcClassParser>,
196 Single<ObjcSelectorParser>,
197 Single<OptimizeParser>,
198 Single<PathAttributeParser>,
199 Single<PatternComplexityLimitParser>,
200 Single<ProcMacroDeriveParser>,
201 Single<RecursionLimitParser>,
202 Single<RustcBuiltinMacroParser>,
203 Single<RustcForceInlineParser>,
204 Single<RustcLayoutScalarValidRangeEndParser>,
205 Single<RustcLayoutScalarValidRangeStartParser>,
206 Single<RustcObjectLifetimeDefaultParser>,
207 Single<RustcSimdMonomorphizeLaneLimitParser>,
208 Single<SanitizeParser>,
209 Single<ShouldPanicParser>,
210 Single<SkipDuringMethodDispatchParser>,
211 Single<TransparencyParser>,
212 Single<TypeLengthLimitParser>,
213 Single<WithoutArgs<AllowIncoherentImplParser>>,
214 Single<WithoutArgs<AllowInternalUnsafeParser>>,
215 Single<WithoutArgs<AsPtrParser>>,
216 Single<WithoutArgs<AutomaticallyDerivedParser>>,
217 Single<WithoutArgs<CoinductiveParser>>,
218 Single<WithoutArgs<ColdParser>>,
219 Single<WithoutArgs<ConstContinueParser>>,
220 Single<WithoutArgs<ConstStabilityIndirectParser>>,
221 Single<WithoutArgs<CoroutineParser>>,
222 Single<WithoutArgs<DenyExplicitImplParser>>,
223 Single<WithoutArgs<DoNotImplementViaObjectParser>>,
224 Single<WithoutArgs<ExportStableParser>>,
225 Single<WithoutArgs<FfiConstParser>>,
226 Single<WithoutArgs<FfiPureParser>>,
227 Single<WithoutArgs<FundamentalParser>>,
228 Single<WithoutArgs<LoopMatchParser>>,
229 Single<WithoutArgs<MacroEscapeParser>>,
230 Single<WithoutArgs<MarkerParser>>,
231 Single<WithoutArgs<MayDangleParser>>,
232 Single<WithoutArgs<NoCoreParser>>,
233 Single<WithoutArgs<NoImplicitPreludeParser>>,
234 Single<WithoutArgs<NoMangleParser>>,
235 Single<WithoutArgs<NoStdParser>>,
236 Single<WithoutArgs<NonExhaustiveParser>>,
237 Single<WithoutArgs<ParenSugarParser>>,
238 Single<WithoutArgs<PassByValueParser>>,
239 Single<WithoutArgs<PinV2Parser>>,
240 Single<WithoutArgs<PointeeParser>>,
241 Single<WithoutArgs<ProcMacroAttributeParser>>,
242 Single<WithoutArgs<ProcMacroParser>>,
243 Single<WithoutArgs<PubTransparentParser>>,
244 Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
245 Single<WithoutArgs<RustcMainParser>>,
246 Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
247 Single<WithoutArgs<SpecializationTraitParser>>,
248 Single<WithoutArgs<StdInternalSymbolParser>>,
249 Single<WithoutArgs<TrackCallerParser>>,
250 Single<WithoutArgs<TypeConstParser>>,
251 Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
252 ];
254);
255
256mod private {
257 pub trait Sealed {}
258 impl Sealed for super::Early {}
259 impl Sealed for super::Late {}
260}
261
262#[allow(private_interfaces)]
264pub trait Stage: Sized + 'static + Sealed {
265 type Id: Copy;
266
267 fn parsers() -> &'static GroupType<Self>;
268
269 fn emit_err<'sess>(
270 &self,
271 sess: &'sess Session,
272 diag: impl for<'x> Diagnostic<'x>,
273 ) -> ErrorGuaranteed;
274
275 fn should_emit(&self) -> ShouldEmit;
276
277 fn id_is_crate_root(id: Self::Id) -> bool;
278}
279
280#[allow(private_interfaces)]
282impl Stage for Early {
283 type Id = NodeId;
284
285 fn parsers() -> &'static GroupType<Self> {
286 &early::ATTRIBUTE_PARSERS
287 }
288 fn emit_err<'sess>(
289 &self,
290 sess: &'sess Session,
291 diag: impl for<'x> Diagnostic<'x>,
292 ) -> ErrorGuaranteed {
293 self.should_emit().emit_err(sess.dcx().create_err(diag))
294 }
295
296 fn should_emit(&self) -> ShouldEmit {
297 self.emit_errors
298 }
299
300 fn id_is_crate_root(id: Self::Id) -> bool {
301 id == CRATE_NODE_ID
302 }
303}
304
305#[allow(private_interfaces)]
307impl Stage for Late {
308 type Id = HirId;
309
310 fn parsers() -> &'static GroupType<Self> {
311 &late::ATTRIBUTE_PARSERS
312 }
313 fn emit_err<'sess>(
314 &self,
315 tcx: &'sess Session,
316 diag: impl for<'x> Diagnostic<'x>,
317 ) -> ErrorGuaranteed {
318 tcx.dcx().emit_err(diag)
319 }
320
321 fn should_emit(&self) -> ShouldEmit {
322 ShouldEmit::ErrorsAndLints
323 }
324
325 fn id_is_crate_root(id: Self::Id) -> bool {
326 id == CRATE_HIR_ID
327 }
328}
329
330pub struct Early {
332 pub emit_errors: ShouldEmit,
336}
337pub struct Late;
339
340pub struct AcceptContext<'f, 'sess, S: Stage> {
344 pub(crate) shared: SharedContext<'f, 'sess, S>,
345
346 pub(crate) attr_span: Span,
351 pub(crate) inner_span: Span,
355
356 pub(crate) attr_style: AttrStyle,
358
359 pub(crate) parsed_description: ParsedDescription,
362
363 pub(crate) template: &'f AttributeTemplate,
367
368 pub(crate) attr_path: AttrPath,
370}
371
372impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
373 pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
374 self.stage.emit_err(&self.sess, diag)
375 }
376
377 pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
381 if !matches!(
382 self.stage.should_emit(),
383 ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
384 ) {
385 return;
386 }
387 let id = self.target_id;
388 (self.emit_lint)(AttributeLint { id, span, kind: lint });
389 }
390
391 pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
392 self.emit_lint(
393 AttributeLintKind::UnusedDuplicate {
394 this: unused_span,
395 other: used_span,
396 warning: false,
397 },
398 unused_span,
399 )
400 }
401
402 pub(crate) fn warn_unused_duplicate_future_error(
403 &mut self,
404 used_span: Span,
405 unused_span: Span,
406 ) {
407 self.emit_lint(
408 AttributeLintKind::UnusedDuplicate {
409 this: unused_span,
410 other: used_span,
411 warning: true,
412 },
413 unused_span,
414 )
415 }
416}
417
418impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
419 pub(crate) fn unknown_key(
420 &self,
421 span: Span,
422 found: String,
423 options: &'static [&'static str],
424 ) -> ErrorGuaranteed {
425 self.emit_err(UnknownMetaItem { span, item: found, expected: options })
426 }
427
428 pub(crate) fn expected_string_literal(
433 &self,
434 span: Span,
435 actual_literal: Option<&MetaItemLit>,
436 ) -> ErrorGuaranteed {
437 self.emit_err(AttributeParseError {
438 span,
439 attr_span: self.attr_span,
440 template: self.template.clone(),
441 path: self.attr_path.clone(),
442 description: self.parsed_description,
443 reason: AttributeParseErrorReason::ExpectedStringLiteral {
444 byte_string: actual_literal.and_then(|i| {
445 i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
446 }),
447 },
448 suggestions: self.suggestions(),
449 })
450 }
451
452 pub(crate) fn expected_integer_literal(&self, span: Span) -> ErrorGuaranteed {
453 self.emit_err(AttributeParseError {
454 span,
455 attr_span: self.attr_span,
456 template: self.template.clone(),
457 path: self.attr_path.clone(),
458 description: self.parsed_description,
459 reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
460 suggestions: self.suggestions(),
461 })
462 }
463
464 pub(crate) fn expected_list(&self, span: Span) -> ErrorGuaranteed {
465 self.emit_err(AttributeParseError {
466 span,
467 attr_span: self.attr_span,
468 template: self.template.clone(),
469 path: self.attr_path.clone(),
470 description: self.parsed_description,
471 reason: AttributeParseErrorReason::ExpectedList,
472 suggestions: self.suggestions(),
473 })
474 }
475
476 pub(crate) fn expected_no_args(&self, args_span: Span) -> ErrorGuaranteed {
477 self.emit_err(AttributeParseError {
478 span: args_span,
479 attr_span: self.attr_span,
480 template: self.template.clone(),
481 path: self.attr_path.clone(),
482 description: self.parsed_description,
483 reason: AttributeParseErrorReason::ExpectedNoArgs,
484 suggestions: self.suggestions(),
485 })
486 }
487
488 pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
490 self.emit_err(AttributeParseError {
491 span,
492 attr_span: self.attr_span,
493 template: self.template.clone(),
494 path: self.attr_path.clone(),
495 description: self.parsed_description,
496 reason: AttributeParseErrorReason::ExpectedIdentifier,
497 suggestions: self.suggestions(),
498 })
499 }
500
501 pub(crate) fn expected_name_value(&self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {
504 self.emit_err(AttributeParseError {
505 span,
506 attr_span: self.attr_span,
507 template: self.template.clone(),
508 path: self.attr_path.clone(),
509 description: self.parsed_description,
510 reason: AttributeParseErrorReason::ExpectedNameValue(name),
511 suggestions: self.suggestions(),
512 })
513 }
514
515 pub(crate) fn duplicate_key(&self, span: Span, key: Symbol) -> ErrorGuaranteed {
517 self.emit_err(AttributeParseError {
518 span,
519 attr_span: self.attr_span,
520 template: self.template.clone(),
521 path: self.attr_path.clone(),
522 description: self.parsed_description,
523 reason: AttributeParseErrorReason::DuplicateKey(key),
524 suggestions: self.suggestions(),
525 })
526 }
527
528 pub(crate) fn unexpected_literal(&self, span: Span) -> ErrorGuaranteed {
531 self.emit_err(AttributeParseError {
532 span,
533 attr_span: self.attr_span,
534 template: self.template.clone(),
535 path: self.attr_path.clone(),
536 description: self.parsed_description,
537 reason: AttributeParseErrorReason::UnexpectedLiteral,
538 suggestions: self.suggestions(),
539 })
540 }
541
542 pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
543 self.emit_err(AttributeParseError {
544 span,
545 attr_span: self.attr_span,
546 template: self.template.clone(),
547 path: self.attr_path.clone(),
548 description: self.parsed_description,
549 reason: AttributeParseErrorReason::ExpectedSingleArgument,
550 suggestions: self.suggestions(),
551 })
552 }
553
554 pub(crate) fn expected_at_least_one_argument(&self, span: Span) -> ErrorGuaranteed {
555 self.emit_err(AttributeParseError {
556 span,
557 attr_span: self.attr_span,
558 template: self.template.clone(),
559 path: self.attr_path.clone(),
560 description: self.parsed_description,
561 reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
562 suggestions: self.suggestions(),
563 })
564 }
565
566 pub(crate) fn expected_specific_argument(
568 &self,
569 span: Span,
570 possibilities: &[Symbol],
571 ) -> ErrorGuaranteed {
572 self.emit_err(AttributeParseError {
573 span,
574 attr_span: self.attr_span,
575 template: self.template.clone(),
576 path: self.attr_path.clone(),
577 description: self.parsed_description,
578 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
579 possibilities,
580 strings: false,
581 list: false,
582 },
583 suggestions: self.suggestions(),
584 })
585 }
586
587 pub(crate) fn expected_specific_argument_and_list(
590 &self,
591 span: Span,
592 possibilities: &[Symbol],
593 ) -> ErrorGuaranteed {
594 self.emit_err(AttributeParseError {
595 span,
596 attr_span: self.attr_span,
597 template: self.template.clone(),
598 path: self.attr_path.clone(),
599 description: self.parsed_description,
600 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
601 possibilities,
602 strings: false,
603 list: true,
604 },
605 suggestions: self.suggestions(),
606 })
607 }
608
609 pub(crate) fn expected_specific_argument_strings(
611 &self,
612 span: Span,
613 possibilities: &[Symbol],
614 ) -> ErrorGuaranteed {
615 self.emit_err(AttributeParseError {
616 span,
617 attr_span: self.attr_span,
618 template: self.template.clone(),
619 path: self.attr_path.clone(),
620 description: self.parsed_description,
621 reason: AttributeParseErrorReason::ExpectedSpecificArgument {
622 possibilities,
623 strings: true,
624 list: false,
625 },
626 suggestions: self.suggestions(),
627 })
628 }
629
630 pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
631 let attr_path = self.attr_path.clone();
632 let valid_without_list = self.template.word;
633 self.emit_lint(
634 AttributeLintKind::EmptyAttribute { first_span: span, attr_path, valid_without_list },
635 span,
636 );
637 }
638
639 pub(crate) fn suggestions(&self) -> Vec<String> {
640 let style = (self.attr_span != self.inner_span).then_some(self.attr_style);
643 self.template.suggestions(style, &self.attr_path)
644 }
645}
646
647impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
648 type Target = SharedContext<'f, 'sess, S>;
649
650 fn deref(&self) -> &Self::Target {
651 &self.shared
652 }
653}
654
655impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
656 fn deref_mut(&mut self) -> &mut Self::Target {
657 &mut self.shared
658 }
659}
660
661pub struct SharedContext<'p, 'sess, S: Stage> {
666 pub(crate) cx: &'p mut AttributeParser<'sess, S>,
669 pub(crate) target_span: Span,
671 pub(crate) target_id: S::Id,
673
674 pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
675}
676
677pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
682 pub(crate) shared: SharedContext<'p, 'sess, S>,
683
684 pub(crate) all_attrs: &'p [PathParser<'p>],
691}
692
693impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> {
694 type Target = SharedContext<'p, 'sess, S>;
695
696 fn deref(&self) -> &Self::Target {
697 &self.shared
698 }
699}
700
701impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> {
702 fn deref_mut(&mut self) -> &mut Self::Target {
703 &mut self.shared
704 }
705}
706
707impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> {
708 type Target = AttributeParser<'sess, S>;
709
710 fn deref(&self) -> &Self::Target {
711 self.cx
712 }
713}
714
715impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> {
716 fn deref_mut(&mut self) -> &mut Self::Target {
717 self.cx
718 }
719}
720
721#[derive(PartialEq, Clone, Copy, Debug)]
722pub enum OmitDoc {
723 Lower,
724 Skip,
725}
726
727#[derive(Copy, Clone, Debug)]
728pub enum ShouldEmit {
729 EarlyFatal { also_emit_lints: bool },
734 ErrorsAndLints,
737 Nothing,
740}
741
742impl ShouldEmit {
743 pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
744 match self {
745 ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),
746 ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),
747 ShouldEmit::ErrorsAndLints => diag.emit(),
748 ShouldEmit::Nothing => diag.delay_as_bug(),
749 }
750 }
751}