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