@@ -26,7 +26,7 @@ use crate::attributes::stability::{
26
26
} ;
27
27
use crate :: attributes:: transparency:: TransparencyParser ;
28
28
use crate :: attributes:: { AttributeParser as _, Combine , Single } ;
29
- use crate :: parser:: { ArgParser , MetaItemParser } ;
29
+ use crate :: parser:: { ArgParser , MetaItemParser , PathParser } ;
30
30
use crate :: session_diagnostics:: { AttributeParseError , AttributeParseErrorReason , UnknownMetaItem } ;
31
31
32
32
macro_rules! group_type {
@@ -95,6 +95,7 @@ attribute_parsers!(
95
95
BodyStabilityParser ,
96
96
ConfusablesParser ,
97
97
ConstStabilityParser ,
98
+ NakedParser ,
98
99
StabilityParser ,
99
100
// tidy-alphabetical-end
100
101
@@ -110,7 +111,6 @@ attribute_parsers!(
110
111
Single <ConstStabilityIndirectParser >,
111
112
Single <DeprecationParser >,
112
113
Single <InlineParser >,
113
- Single <NakedParser >,
114
114
Single <OptimizeParser >,
115
115
Single <RustcForceInlineParser >,
116
116
Single <TransparencyParser >,
@@ -169,7 +169,7 @@ pub struct Late;
169
169
///
170
170
/// Gives [`AttributeParser`]s enough information to create errors, for example.
171
171
pub ( crate ) struct AcceptContext < ' f , ' sess , S : Stage > {
172
- pub ( crate ) finalize_cx : FinalizeContext < ' f , ' sess , S > ,
172
+ pub ( crate ) shared : SharedContext < ' f , ' sess , S > ,
173
173
/// The span of the attribute currently being parsed
174
174
pub ( crate ) attr_span : Span ,
175
175
@@ -182,7 +182,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
182
182
pub ( crate ) attr_path : AttrPath ,
183
183
}
184
184
185
- impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
185
+ impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
186
186
pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
187
187
S :: emit_err ( & self . sess , diag)
188
188
}
@@ -220,7 +220,9 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
220
220
unused_span,
221
221
)
222
222
}
223
+ }
223
224
225
+ impl < ' f , ' sess : ' f , S : Stage > AcceptContext < ' f , ' sess , S > {
224
226
pub ( crate ) fn unknown_key (
225
227
& self ,
226
228
span : Span ,
@@ -353,24 +355,24 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
353
355
}
354
356
355
357
impl < ' f , ' sess , S : Stage > Deref for AcceptContext < ' f , ' sess , S > {
356
- type Target = FinalizeContext < ' f , ' sess , S > ;
358
+ type Target = SharedContext < ' f , ' sess , S > ;
357
359
358
360
fn deref ( & self ) -> & Self :: Target {
359
- & self . finalize_cx
361
+ & self . shared
360
362
}
361
363
}
362
364
363
365
impl < ' f , ' sess , S : Stage > DerefMut for AcceptContext < ' f , ' sess , S > {
364
366
fn deref_mut ( & mut self ) -> & mut Self :: Target {
365
- & mut self . finalize_cx
367
+ & mut self . shared
366
368
}
367
369
}
368
370
369
371
/// Context given to every attribute parser during finalization.
370
372
///
371
373
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
372
374
/// errors, for example.
373
- pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
375
+ pub ( crate ) struct SharedContext < ' p , ' sess , S : Stage > {
374
376
/// The parse context, gives access to the session and the
375
377
/// diagnostics context.
376
378
pub ( crate ) cx : & ' p mut AttributeParser < ' sess , S > ,
@@ -379,18 +381,48 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> {
379
381
/// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
380
382
pub ( crate ) target_id : S :: Id ,
381
383
382
- pub ( crate ) emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
384
+ emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
385
+ }
386
+
387
+ /// Context given to every attribute parser during finalization.
388
+ ///
389
+ /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
390
+ /// errors, for example.
391
+ pub ( crate ) struct FinalizeContext < ' p , ' sess , S : Stage > {
392
+ pub ( crate ) shared : SharedContext < ' p , ' sess , S > ,
393
+
394
+ /// A list of all attribute on this syntax node.
395
+ ///
396
+ /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
397
+ ///
398
+ /// Usually, you should use normal attribute parsing logic instead,
399
+ /// especially when making a *denylist* of other attributes.
400
+ pub ( crate ) all_attrs : & ' p [ PathParser < ' p > ] ,
383
401
}
384
402
385
403
impl < ' p , ' sess : ' p , S : Stage > Deref for FinalizeContext < ' p , ' sess , S > {
404
+ type Target = SharedContext < ' p , ' sess , S > ;
405
+
406
+ fn deref ( & self ) -> & Self :: Target {
407
+ & self . shared
408
+ }
409
+ }
410
+
411
+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
412
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
413
+ & mut self . shared
414
+ }
415
+ }
416
+
417
+ impl < ' p , ' sess : ' p , S : Stage > Deref for SharedContext < ' p , ' sess , S > {
386
418
type Target = AttributeParser < ' sess , S > ;
387
419
388
420
fn deref ( & self ) -> & Self :: Target {
389
421
self . cx
390
422
}
391
423
}
392
424
393
- impl < ' p , ' sess : ' p , S : Stage > DerefMut for FinalizeContext < ' p , ' sess , S > {
425
+ impl < ' p , ' sess : ' p , S : Stage > DerefMut for SharedContext < ' p , ' sess , S > {
394
426
fn deref_mut ( & mut self ) -> & mut Self :: Target {
395
427
self . cx
396
428
}
@@ -405,8 +437,7 @@ pub enum OmitDoc {
405
437
/// Context created once, for example as part of the ast lowering
406
438
/// context, through which all attributes can be lowered.
407
439
pub struct AttributeParser < ' sess , S : Stage = Late > {
408
- #[ expect( dead_code) ] // FIXME(jdonszelmann): needed later to verify we parsed all attributes
409
- tools : Vec < Symbol > ,
440
+ pub ( crate ) tools : Vec < Symbol > ,
410
441
features : Option < & ' sess Features > ,
411
442
sess : & ' sess Session ,
412
443
stage : PhantomData < S > ,
@@ -494,6 +525,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
494
525
mut emit_lint : impl FnMut ( AttributeLint < S :: Id > ) ,
495
526
) -> Vec < Attribute > {
496
527
let mut attributes = Vec :: new ( ) ;
528
+ let mut attr_paths = Vec :: new ( ) ;
497
529
498
530
for attr in attrs {
499
531
// If we're only looking for a single attribute, skip all the ones we don't care about.
@@ -537,6 +569,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
537
569
// }))
538
570
// }
539
571
ast:: AttrKind :: Normal ( n) => {
572
+ attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
573
+
540
574
let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
541
575
let path = parser. path ( ) ;
542
576
let args = parser. args ( ) ;
@@ -545,7 +579,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
545
579
if let Some ( accepts) = S :: parsers ( ) . 0 . get ( parts. as_slice ( ) ) {
546
580
for ( template, accept) in accepts {
547
581
let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
548
- finalize_cx : FinalizeContext {
582
+ shared : SharedContext {
549
583
cx : self ,
550
584
target_span,
551
585
target_id,
@@ -589,10 +623,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
589
623
let mut parsed_attributes = Vec :: new ( ) ;
590
624
for f in & S :: parsers ( ) . 1 {
591
625
if let Some ( attr) = f ( & mut FinalizeContext {
592
- cx : self ,
593
- target_span,
594
- target_id,
595
- emit_lint : & mut emit_lint,
626
+ shared : SharedContext {
627
+ cx : self ,
628
+ target_span,
629
+ target_id,
630
+ emit_lint : & mut emit_lint,
631
+ } ,
632
+ all_attrs : & attr_paths,
596
633
} ) {
597
634
parsed_attributes. push ( Attribute :: Parsed ( attr) ) ;
598
635
}
0 commit comments