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