@@ -28,7 +28,7 @@ use crate::attributes::stability::{
2828} ;
2929use crate :: attributes:: transparency:: TransparencyParser ;
3030use crate :: attributes:: { AttributeParser as _, Combine , Single } ;
31- use crate :: parser:: { ArgParser , MetaItemParser } ;
31+ use crate :: parser:: { ArgParser , MetaItemParser , PathParser } ;
3232use crate :: session_diagnostics:: { AttributeParseError , AttributeParseErrorReason , UnknownMetaItem } ;
3333
3434macro_rules! group_type {
@@ -97,6 +97,7 @@ attribute_parsers!(
9797 BodyStabilityParser ,
9898 ConfusablesParser ,
9999 ConstStabilityParser ,
100+ NakedParser ,
100101 StabilityParser ,
101102 // tidy-alphabetical-end
102103
@@ -114,7 +115,6 @@ attribute_parsers!(
114115 Single <InlineParser >,
115116 Single <MayDangleParser >,
116117 Single <MustUseParser >,
117- Single <NakedParser >,
118118 Single <NoMangleParser >,
119119 Single <OptimizeParser >,
120120 Single <PubTransparentParser >,
@@ -175,7 +175,7 @@ pub struct Late;
175175///
176176/// Gives [`AttributeParser`]s enough information to create errors, for example.
177177pub ( crate ) struct AcceptContext < ' f , ' sess , S : Stage > {
178- pub ( crate ) finalize_cx : FinalizeContext < ' f , ' sess , S > ,
178+ pub ( crate ) shared : SharedContext < ' f , ' sess , S > ,
179179 /// The span of the attribute currently being parsed
180180 pub ( crate ) attr_span : Span ,
181181
@@ -188,7 +188,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
188188 pub ( crate ) attr_path : AttrPath ,
189189}
190190
191- impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
191+ impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
192192 pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
193193 S :: emit_err ( & self . sess , diag)
194194 }
@@ -226,7 +226,9 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
226226 unused_span,
227227 )
228228 }
229+ }
229230
231+ impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
230232 pub ( crate ) fn unknown_key (
231233 & self ,
232234 span : Span ,
@@ -359,24 +361,24 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
359361}
360362
361363impl < ' f , ' sess , S : Stage > Deref for AcceptContext < ' f , ' sess , S > {
362- type Target = FinalizeContext < ' f , ' sess , S > ;
364+ type Target = SharedContext < ' f , ' sess , S > ;
363365
364366 fn deref ( & self ) -> & Self :: Target {
365- & self . finalize_cx
367+ & self . shared
366368 }
367369}
368370
369371impl < ' f , ' sess , S : Stage > DerefMut for AcceptContext < ' f , ' sess , S > {
370372 fn deref_mut ( & mut self ) -> & mut Self :: Target {
371- & mut self . finalize_cx
373+ & mut self . shared
372374 }
373375}
374376
375377/// Context given to every attribute parser during finalization.
376378///
377379/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
378380/// errors, for example.
379- pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
381+ pub ( crate ) struct SharedContext < ' p , ' sess , S : Stage > {
380382 /// The parse context, gives access to the session and the
381383 /// diagnostics context.
382384 pub ( crate ) cx : & ' p mut AttributeParser < ' sess , S > ,
@@ -385,18 +387,48 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
385387 /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
386388 pub ( crate ) target_id : S :: Id ,
387389
388- pub ( crate ) emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
390+ emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
391+ }
392+
393+ /// Context given to every attribute parser during finalization.
394+ ///
395+ /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
396+ /// errors, for example.
397+ pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
398+ pub ( crate ) shared : SharedContext < ' p , ' sess , S > ,
399+
400+ /// A list of all attribute on this syntax node.
401+ ///
402+ /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
403+ ///
404+ /// Usually, you should use normal attribute parsing logic instead,
405+ /// especially when making a *denylist* of other attributes.
406+ pub ( crate ) all_attrs : & ' p [ PathParser < ' p > ] ,
389407}
390408
391409impl < ' p , ' sess : ' p , S : Stage > Deref for FinalizeContext < ' p , ' sess , S > {
410+ type Target = SharedContext < ' p , ' sess , S > ;
411+
412+ fn deref ( & self ) -> & Self :: Target {
413+ & self . shared
414+ }
415+ }
416+
417+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
418+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
419+ & mut self . shared
420+ }
421+ }
422+
423+ impl < ' p , ' sess : ' p , S : Stage > Deref for SharedContext < ' p , ' sess , S > {
392424 type Target = AttributeParser < ' sess , S > ;
393425
394426 fn deref ( & self ) -> & Self :: Target {
395427 self . cx
396428 }
397429}
398430
399- impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
431+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for SharedContext < ' p , ' sess , S > {
400432 fn deref_mut ( & mut self ) -> & mut Self :: Target {
401433 self . cx
402434 }
@@ -411,8 +443,7 @@ pub enum OmitDoc {
411443/// Context created once, for example as part of the ast lowering
412444/// context, through which all attributes can be lowered.
413445pub struct AttributeParser < ' sess , S : Stage = Late > {
414- #[ expect( dead_code) ] // FIXME(jdonszelmann): needed later to verify we parsed all attributes
415- tools : Vec < Symbol > ,
446+ pub ( crate ) tools : Vec < Symbol > ,
416447 features : Option < & ' sess Features > ,
417448 sess : & ' sess Session ,
418449 stage : PhantomData < S > ,
@@ -500,6 +531,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
500531 mut emit_lint : impl FnMut ( AttributeLint < S :: Id > ) ,
501532 ) -> Vec < Attribute > {
502533 let mut attributes = Vec :: new ( ) ;
534+ let mut attr_paths = Vec :: new ( ) ;
503535
504536 for attr in attrs {
505537 // If we're only looking for a single attribute, skip all the ones we don't care about.
@@ -543,6 +575,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
543575 // }))
544576 // }
545577 ast:: AttrKind :: Normal ( n) => {
578+ attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
579+
546580 let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
547581 let path = parser. path ( ) ;
548582 let args = parser. args ( ) ;
@@ -551,7 +585,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
551585 if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
552586 for ( template, accept) in accepts {
553587 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
554- finalize_cx : FinalizeContext {
588+ shared : SharedContext {
555589 cx : self ,
556590 target_span,
557591 target_id,
@@ -595,10 +629,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
595629 let mut parsed_attributes = Vec :: new ( ) ;
596630 for f in & S :: parsers ( ) . 1 {
597631 if let Some ( attr) = f ( & mut FinalizeContext {
598- cx : self ,
599- target_span,
600- target_id,
601- emit_lint : & mut emit_lint,
632+ shared : SharedContext {
633+ cx : self ,
634+ target_span,
635+ target_id,
636+ emit_lint : & mut emit_lint,
637+ } ,
638+ all_attrs : & attr_paths,
602639 } ) {
603640 parsed_attributes. push ( Attribute :: Parsed ( attr) ) ;
604641 }
0 commit comments