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