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