@@ -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 <OptimizeParser >,
119119 Single <PubTransparentParser >,
120120 Single <RustcForceInlineParser >,
@@ -174,7 +174,7 @@ pub struct Late;
174174///
175175/// Gives [`AttributeParser`]s enough information to create errors, for example.
176176pub ( crate ) struct AcceptContext < ' f , ' sess , S : Stage > {
177- pub ( crate ) finalize_cx : FinalizeContext < ' f , ' sess , S > ,
177+ pub ( crate ) shared : SharedContext < ' f , ' sess , S > ,
178178 /// The span of the attribute currently being parsed
179179 pub ( crate ) attr_span : Span ,
180180
@@ -187,7 +187,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
187187 pub ( crate ) attr_path : AttrPath ,
188188}
189189
190- impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
190+ impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
191191 pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
192192 S :: emit_err ( & self . sess , diag)
193193 }
@@ -225,7 +225,9 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
225225 unused_span,
226226 )
227227 }
228+ }
228229
230+ impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
229231 pub ( crate ) fn unknown_key (
230232 & self ,
231233 span : Span ,
@@ -358,24 +360,24 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
358360}
359361
360362impl < ' f , ' sess , S : Stage > Deref for AcceptContext < ' f , ' sess , S > {
361- type Target = FinalizeContext < ' f , ' sess , S > ;
363+ type Target = SharedContext < ' f , ' sess , S > ;
362364
363365 fn deref ( & self ) -> & Self :: Target {
364- & self . finalize_cx
366+ & self . shared
365367 }
366368}
367369
368370impl < ' f , ' sess , S : Stage > DerefMut for AcceptContext < ' f , ' sess , S > {
369371 fn deref_mut ( & mut self ) -> & mut Self :: Target {
370- & mut self . finalize_cx
372+ & mut self . shared
371373 }
372374}
373375
374376/// Context given to every attribute parser during finalization.
375377///
376378/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
377379/// errors, for example.
378- pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
380+ pub ( crate ) struct SharedContext < ' p , ' sess , S : Stage > {
379381 /// The parse context, gives access to the session and the
380382 /// diagnostics context.
381383 pub ( crate ) cx : & ' p mut AttributeParser < ' sess , S > ,
@@ -384,18 +386,48 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
384386 /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
385387 pub ( crate ) target_id : S :: Id ,
386388
387- pub ( crate ) emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
389+ emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
390+ }
391+
392+ /// Context given to every attribute parser during finalization.
393+ ///
394+ /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
395+ /// errors, for example.
396+ pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
397+ pub ( crate ) shared : SharedContext < ' p , ' sess , S > ,
398+
399+ /// A list of all attribute on this syntax node.
400+ ///
401+ /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
402+ ///
403+ /// Usually, you should use normal attribute parsing logic instead,
404+ /// especially when making a *denylist* of other attributes.
405+ pub ( crate ) all_attrs : & ' p [ PathParser < ' p > ] ,
388406}
389407
390408impl < ' p , ' sess : ' p , S : Stage > Deref for FinalizeContext < ' p , ' sess , S > {
409+ type Target = SharedContext < ' p , ' sess , S > ;
410+
411+ fn deref ( & self ) -> & Self :: Target {
412+ & self . shared
413+ }
414+ }
415+
416+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
417+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
418+ & mut self . shared
419+ }
420+ }
421+
422+ impl < ' p , ' sess : ' p , S : Stage > Deref for SharedContext < ' p , ' sess , S > {
391423 type Target = AttributeParser < ' sess , S > ;
392424
393425 fn deref ( & self ) -> & Self :: Target {
394426 self . cx
395427 }
396428}
397429
398- impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
430+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for SharedContext < ' p , ' sess , S > {
399431 fn deref_mut ( & mut self ) -> & mut Self :: Target {
400432 self . cx
401433 }
@@ -410,8 +442,7 @@ pub enum OmitDoc {
410442/// Context created once, for example as part of the ast lowering
411443/// context, through which all attributes can be lowered.
412444pub struct AttributeParser < ' sess , S : Stage = Late > {
413- #[ expect( dead_code) ] // FIXME(jdonszelmann): needed later to verify we parsed all attributes
414- tools : Vec < Symbol > ,
445+ pub ( crate ) tools : Vec < Symbol > ,
415446 features : Option < & ' sess Features > ,
416447 sess : & ' sess Session ,
417448 stage : PhantomData < S > ,
@@ -499,6 +530,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
499530 mut emit_lint : impl FnMut ( AttributeLint < S :: Id > ) ,
500531 ) -> Vec < Attribute > {
501532 let mut attributes = Vec :: new ( ) ;
533+ let mut attr_paths = Vec :: new ( ) ;
502534
503535 for attr in attrs {
504536 // If we're only looking for a single attribute, skip all the ones we don't care about.
@@ -542,6 +574,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
542574 // }))
543575 // }
544576 ast:: AttrKind :: Normal ( n) => {
577+ attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
578+
545579 let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
546580 let path = parser. path ( ) ;
547581 let args = parser. args ( ) ;
@@ -550,7 +584,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
550584 if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
551585 for ( template, accept) in accepts {
552586 let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
553- finalize_cx : FinalizeContext {
587+ shared : SharedContext {
554588 cx : self ,
555589 target_span,
556590 target_id,
@@ -594,10 +628,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
594628 let mut parsed_attributes = Vec :: new ( ) ;
595629 for f in & S :: parsers ( ) . 1 {
596630 if let Some ( attr) = f ( & mut FinalizeContext {
597- cx : self ,
598- target_span,
599- target_id,
600- emit_lint : & mut emit_lint,
631+ shared : SharedContext {
632+ cx : self ,
633+ target_span,
634+ target_id,
635+ emit_lint : & mut emit_lint,
636+ } ,
637+ all_attrs : & attr_paths,
601638 } ) {
602639 parsed_attributes. push ( Attribute :: Parsed ( attr) ) ;
603640 }
0 commit comments