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