1
1
use std:: cell:: RefCell ;
2
2
use std:: collections:: BTreeMap ;
3
- use std:: marker:: PhantomData ;
4
3
use std:: ops:: { Deref , DerefMut } ;
5
4
use std:: sync:: LazyLock ;
6
5
@@ -202,7 +201,11 @@ pub trait Stage: Sized + 'static + Sealed {
202
201
203
202
fn parsers ( ) -> & ' static group_type ! ( Self ) ;
204
203
205
- fn emit_err < ' sess > ( sess : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed ;
204
+ fn emit_err < ' sess > (
205
+ & self ,
206
+ sess : & ' sess Session ,
207
+ diag : impl for < ' x > Diagnostic < ' x > ,
208
+ ) -> ErrorGuaranteed ;
206
209
}
207
210
208
211
// allow because it's a sealed trait
@@ -214,8 +217,16 @@ impl Stage for Early {
214
217
fn parsers ( ) -> & ' static group_type ! ( Self ) {
215
218
& early:: ATTRIBUTE_PARSERS
216
219
}
217
- fn emit_err < ' sess > ( sess : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
218
- sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
220
+ fn emit_err < ' sess > (
221
+ & self ,
222
+ sess : & ' sess Session ,
223
+ diag : impl for < ' x > Diagnostic < ' x > ,
224
+ ) -> ErrorGuaranteed {
225
+ if self . emit_errors {
226
+ sess. dcx ( ) . emit_err ( diag)
227
+ } else {
228
+ sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
229
+ }
219
230
}
220
231
}
221
232
@@ -228,20 +239,29 @@ impl Stage for Late {
228
239
fn parsers ( ) -> & ' static group_type ! ( Self ) {
229
240
& late:: ATTRIBUTE_PARSERS
230
241
}
231
- fn emit_err < ' sess > ( tcx : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
242
+ fn emit_err < ' sess > (
243
+ & self ,
244
+ tcx : & ' sess Session ,
245
+ diag : impl for < ' x > Diagnostic < ' x > ,
246
+ ) -> ErrorGuaranteed {
232
247
tcx. dcx ( ) . emit_err ( diag)
233
248
}
234
249
}
235
250
236
251
/// used when parsing attributes for miscellaneous things *before* ast lowering
237
- pub struct Early ;
252
+ pub struct Early {
253
+ /// Whether to emit errors or delay them as a bug
254
+ /// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
255
+ /// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
256
+ pub emit_errors : bool ,
257
+ }
238
258
/// used when parsing attributes during ast lowering
239
259
pub struct Late ;
240
260
241
261
/// Context given to every attribute parser when accepting
242
262
///
243
263
/// Gives [`AttributeParser`]s enough information to create errors, for example.
244
- pub ( crate ) struct AcceptContext < ' f , ' sess , S : Stage > {
264
+ pub struct AcceptContext < ' f , ' sess , S : Stage > {
245
265
pub ( crate ) shared : SharedContext < ' f , ' sess , S > ,
246
266
/// The span of the attribute currently being parsed
247
267
pub ( crate ) attr_span : Span ,
@@ -257,7 +277,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
257
277
258
278
impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
259
279
pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
260
- S :: emit_err ( & self . sess , diag)
280
+ self . stage . emit_err ( & self . sess , diag)
261
281
}
262
282
263
283
/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
@@ -472,7 +492,7 @@ impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
472
492
///
473
493
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
474
494
/// errors, for example.
475
- pub ( crate ) struct SharedContext < ' p , ' sess , S : Stage > {
495
+ pub struct SharedContext < ' p , ' sess , S : Stage > {
476
496
/// The parse context, gives access to the session and the
477
497
/// diagnostics context.
478
498
pub ( crate ) cx : & ' p mut AttributeParser < ' sess , S > ,
@@ -540,7 +560,7 @@ pub struct AttributeParser<'sess, S: Stage = Late> {
540
560
pub ( crate ) tools : Vec < Symbol > ,
541
561
features : Option < & ' sess Features > ,
542
562
sess : & ' sess Session ,
543
- stage : PhantomData < S > ,
563
+ stage : S ,
544
564
545
565
/// *Only* parse attributes with this symbol.
546
566
///
@@ -569,13 +589,14 @@ impl<'sess> AttributeParser<'sess, Early> {
569
589
sym : Symbol ,
570
590
target_span : Span ,
571
591
target_node_id : NodeId ,
592
+ features : Option < & ' sess Features > ,
572
593
) -> Option < Attribute > {
573
594
let mut p = Self {
574
- features : None ,
595
+ features,
575
596
tools : Vec :: new ( ) ,
576
597
parse_only : Some ( sym) ,
577
598
sess,
578
- stage : PhantomData ,
599
+ stage : Early { emit_errors : false } ,
579
600
} ;
580
601
let mut parsed = p. parse_attribute_list (
581
602
attrs,
@@ -591,11 +612,55 @@ impl<'sess> AttributeParser<'sess, Early> {
591
612
592
613
parsed. pop ( )
593
614
}
615
+
616
+ pub fn parse_single < T > (
617
+ sess : & ' sess Session ,
618
+ attr : & ast:: Attribute ,
619
+ target_span : Span ,
620
+ target_node_id : NodeId ,
621
+ features : Option < & ' sess Features > ,
622
+ emit_errors : bool ,
623
+ parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> T ,
624
+ template : & AttributeTemplate ,
625
+ ) -> T {
626
+ let mut parser = Self {
627
+ features,
628
+ tools : Vec :: new ( ) ,
629
+ parse_only : None ,
630
+ sess,
631
+ stage : Early { emit_errors } ,
632
+ } ;
633
+ let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
634
+ panic ! ( "parse_single called on a doc attr" )
635
+ } ;
636
+ let meta_parser = MetaItemParser :: from_attr ( normal_attr, parser. dcx ( ) ) ;
637
+ let path = meta_parser. path ( ) ;
638
+ let args = meta_parser. args ( ) ;
639
+ let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
640
+ shared : SharedContext {
641
+ cx : & mut parser,
642
+ target_span,
643
+ target_id : target_node_id,
644
+ emit_lint : & mut |_lint| {
645
+ panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
646
+ } ,
647
+ } ,
648
+ attr_span : attr. span ,
649
+ template,
650
+ attr_path : path. get_attribute_path ( ) ,
651
+ } ;
652
+ parse_fn ( & mut cx, args)
653
+ }
594
654
}
595
655
596
656
impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
597
- pub fn new ( sess : & ' sess Session , features : & ' sess Features , tools : Vec < Symbol > ) -> Self {
598
- Self { features : Some ( features) , tools, parse_only : None , sess, stage : PhantomData }
657
+ pub fn new (
658
+ sess : & ' sess Session ,
659
+ features : & ' sess Features ,
660
+ tools : Vec < Symbol > ,
661
+ stage : S ,
662
+ ) -> Self {
663
+ Self { features : Some ( features) , tools, parse_only : None , sess, stage }
599
664
}
600
665
601
666
pub ( crate ) fn sess ( & self ) -> & ' sess Session {
@@ -606,6 +671,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
606
671
self . features . expect ( "features not available at this point in the compiler" )
607
672
}
608
673
674
+ pub ( crate ) fn features_option ( & self ) -> Option < & ' sess Features > {
675
+ self . features
676
+ }
677
+
609
678
pub ( crate ) fn dcx ( & self ) -> DiagCtxtHandle < ' sess > {
610
679
self . sess ( ) . dcx ( )
611
680
}
0 commit comments