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