@@ -27,7 +27,7 @@ use crate::attributes::stability::{
2727} ;
2828use crate :: attributes:: transparency:: TransparencyParser ;
2929use crate :: attributes:: { AttributeParser as _, Combine , Single } ;
30- use crate :: parser:: { ArgParser , MetaItemParser } ;
30+ use crate :: parser:: { ArgParser , MetaItemParser , PathParser } ;
3131use crate :: session_diagnostics:: { AttributeParseError , AttributeParseErrorReason , UnknownMetaItem } ;
3232
3333macro_rules! group_type {
@@ -96,6 +96,7 @@ attribute_parsers!(
9696 BodyStabilityParser ,
9797 ConfusablesParser ,
9898 ConstStabilityParser ,
99+ NakedParser ,
99100 StabilityParser ,
100101 // tidy-alphabetical-end
101102
@@ -112,7 +113,6 @@ attribute_parsers!(
112113 Single <DeprecationParser >,
113114 Single <InlineParser >,
114115 Single <MayDangleParser >,
115- Single <NakedParser >,
116116 Single <OptimizeParser >,
117117 Single <RustcForceInlineParser >,
118118 Single <TransparencyParser >,
@@ -171,7 +171,7 @@ pub struct Late;
171171///
172172/// Gives [`AttributeParser`]s enough information to create errors, for example.
173173pub ( crate ) struct AcceptContext < ' f , ' sess , S : Stage > {
174- pub ( crate ) finalize_cx : FinalizeContext < ' f , ' sess , S > ,
174+ pub ( crate ) shared : SharedContext < ' f , ' sess , S > ,
175175 /// The span of the attribute currently being parsed
176176 pub ( crate ) attr_span : Span ,
177177
@@ -184,7 +184,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
184184 pub ( crate ) attr_path : AttrPath ,
185185}
186186
187- impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
187+ impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
188188 pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
189189 S :: emit_err ( & self . sess , diag)
190190 }
@@ -222,7 +222,9 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
222222 unused_span,
223223 )
224224 }
225+ }
225226
227+ impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
226228 pub ( crate ) fn unknown_key (
227229 & self ,
228230 span : Span ,
@@ -355,24 +357,24 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
355357}
356358
357359impl < ' f , ' sess , S : Stage > Deref for AcceptContext < ' f , ' sess , S > {
358- type Target = FinalizeContext < ' f , ' sess , S > ;
360+ type Target = SharedContext < ' f , ' sess , S > ;
359361
360362 fn deref ( & self ) -> & Self :: Target {
361- & self . finalize_cx
363+ & self . shared
362364 }
363365}
364366
365367impl < ' f , ' sess , S : Stage > DerefMut for AcceptContext < ' f , ' sess , S > {
366368 fn deref_mut ( & mut self ) -> & mut Self :: Target {
367- & mut self . finalize_cx
369+ & mut self . shared
368370 }
369371}
370372
371373/// Context given to every attribute parser during finalization.
372374///
373375/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
374376/// errors, for example.
375- pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
377+ pub ( crate ) struct SharedContext < ' p , ' sess , S : Stage > {
376378 /// The parse context, gives access to the session and the
377379 /// diagnostics context.
378380 pub ( crate ) cx : & ' p mut AttributeParser < ' sess , S > ,
@@ -381,18 +383,48 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
381383 /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
382384 pub ( crate ) target_id : S :: Id ,
383385
384- pub ( crate ) emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
386+ emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
387+ }
388+
389+ /// Context given to every attribute parser during finalization.
390+ ///
391+ /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
392+ /// errors, for example.
393+ pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
394+ pub ( crate ) shared : SharedContext < ' p , ' sess , S > ,
395+
396+ /// A list of all attribute on this syntax node.
397+ ///
398+ /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
399+ ///
400+ /// Usually, you should use normal attribute parsing logic instead,
401+ /// especially when making a *denylist* of other attributes.
402+ pub ( crate ) all_attrs : & ' p [ PathParser < ' p > ] ,
385403}
386404
387405impl < ' p , ' sess : ' p , S : Stage > Deref for FinalizeContext < ' p , ' sess , S > {
406+ type Target = SharedContext < ' p , ' sess , S > ;
407+
408+ fn deref ( & self ) -> & Self :: Target {
409+ & self . shared
410+ }
411+ }
412+
413+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
414+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
415+ & mut self . shared
416+ }
417+ }
418+
419+ impl < ' p , ' sess : ' p , S : Stage > Deref for SharedContext < ' p , ' sess , S > {
388420 type Target = AttributeParser < ' sess , S > ;
389421
390422 fn deref ( & self ) -> & Self :: Target {
391423 self . cx
392424 }
393425}
394426
395- impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
427+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for SharedContext < ' p , ' sess , S > {
396428 fn deref_mut ( & mut self ) -> & mut Self :: Target {
397429 self . cx
398430 }
@@ -407,8 +439,7 @@ pub enum OmitDoc {
407439/// Context created once, for example as part of the ast lowering
408440/// context, through which all attributes can be lowered.
409441pub struct AttributeParser < ' sess , S : Stage = Late > {
410- #[ expect( dead_code) ] // FIXME(jdonszelmann): needed later to verify we parsed all attributes
411- tools : Vec < Symbol > ,
442+ pub ( crate ) tools : Vec < Symbol > ,
412443 features : Option < & ' sess Features > ,
413444 sess : & ' sess Session ,
414445 stage : PhantomData < S > ,
@@ -496,6 +527,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
496527 mut emit_lint : impl FnMut ( AttributeLint < S :: Id > ) ,
497528 ) -> Vec < Attribute > {
498529 let mut attributes = Vec :: new ( ) ;
530+ let mut attr_paths = Vec :: new ( ) ;
499531
500532 for attr in attrs {
501533 // If we're only looking for a single attribute, skip all the ones we don't care about.
@@ -539,6 +571,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
539571 // }))
540572 // }
541573 ast:: AttrKind :: Normal ( n) => {
574+ attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
575+
542576 let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
543577 let path = parser. path ( ) ;
544578 let args = parser. args ( ) ;
@@ -547,7 +581,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
547581 if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
548582 for ( template, accept) in accepts {
549583 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
550- finalize_cx : FinalizeContext {
584+ shared : SharedContext {
551585 cx : self ,
552586 target_span,
553587 target_id,
@@ -591,10 +625,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
591625 let mut parsed_attributes = Vec :: new ( ) ;
592626 for f in & S :: parsers ( ) . 1 {
593627 if let Some ( attr) = f ( & mut FinalizeContext {
594- cx : self ,
595- target_span,
596- target_id,
597- emit_lint : & mut emit_lint,
628+ shared : SharedContext {
629+ cx : self ,
630+ target_span,
631+ target_id,
632+ emit_lint : & mut emit_lint,
633+ } ,
634+ all_attrs : & attr_paths,
598635 } ) {
599636 parsed_attributes. push ( Attribute :: Parsed ( attr) ) ;
600637 }
0 commit comments