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
@@ -180,7 +179,11 @@ pub trait Stage: Sized + 'static + Sealed {
180
179
181
180
fn parsers ( ) -> & ' static group_type ! ( Self ) ;
182
181
183
- fn emit_err < ' sess > ( sess : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed ;
182
+ fn emit_err < ' sess > (
183
+ & self ,
184
+ sess : & ' sess Session ,
185
+ diag : impl for < ' x > Diagnostic < ' x > ,
186
+ ) -> ErrorGuaranteed ;
184
187
}
185
188
186
189
// allow because it's a sealed trait
@@ -192,8 +195,16 @@ impl Stage for Early {
192
195
fn parsers ( ) -> & ' static group_type ! ( Self ) {
193
196
& early:: ATTRIBUTE_PARSERS
194
197
}
195
- fn emit_err < ' sess > ( sess : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
196
- sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
198
+ fn emit_err < ' sess > (
199
+ & self ,
200
+ sess : & ' sess Session ,
201
+ diag : impl for < ' x > Diagnostic < ' x > ,
202
+ ) -> ErrorGuaranteed {
203
+ if self . emit_errors {
204
+ sess. dcx ( ) . emit_err ( diag)
205
+ } else {
206
+ sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
207
+ }
197
208
}
198
209
}
199
210
@@ -206,20 +217,29 @@ impl Stage for Late {
206
217
fn parsers ( ) -> & ' static group_type ! ( Self ) {
207
218
& late:: ATTRIBUTE_PARSERS
208
219
}
209
- fn emit_err < ' sess > ( tcx : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
220
+ fn emit_err < ' sess > (
221
+ & self ,
222
+ tcx : & ' sess Session ,
223
+ diag : impl for < ' x > Diagnostic < ' x > ,
224
+ ) -> ErrorGuaranteed {
210
225
tcx. dcx ( ) . emit_err ( diag)
211
226
}
212
227
}
213
228
214
229
/// used when parsing attributes for miscellaneous things *before* ast lowering
215
- pub struct Early ;
230
+ pub struct Early {
231
+ /// Whether to emit errors or delay them as a bug
232
+ /// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
233
+ /// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
234
+ pub emit_errors : bool ,
235
+ }
216
236
/// used when parsing attributes during ast lowering
217
237
pub struct Late ;
218
238
219
239
/// Context given to every attribute parser when accepting
220
240
///
221
241
/// Gives [`AttributeParser`]s enough information to create errors, for example.
222
- pub ( crate ) struct AcceptContext < ' f , ' sess , S : Stage > {
242
+ pub struct AcceptContext < ' f , ' sess , S : Stage > {
223
243
pub ( crate ) shared : SharedContext < ' f , ' sess , S > ,
224
244
/// The span of the attribute currently being parsed
225
245
pub ( crate ) attr_span : Span ,
@@ -235,7 +255,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
235
255
236
256
impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
237
257
pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
238
- S :: emit_err ( & self . sess , diag)
258
+ self . stage . emit_err ( & self . sess , diag)
239
259
}
240
260
241
261
/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
@@ -450,7 +470,7 @@ impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> {
450
470
///
451
471
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
452
472
/// errors, for example.
453
- pub ( crate ) struct SharedContext < ' p , ' sess , S : Stage > {
473
+ pub struct SharedContext < ' p , ' sess , S : Stage > {
454
474
/// The parse context, gives access to the session and the
455
475
/// diagnostics context.
456
476
pub ( crate ) cx : & ' p mut AttributeParser < ' sess , S > ,
@@ -518,7 +538,7 @@ pub struct AttributeParser<'sess, S: Stage = Late> {
518
538
pub ( crate ) tools : Vec < Symbol > ,
519
539
features : Option < & ' sess Features > ,
520
540
sess : & ' sess Session ,
521
- stage : PhantomData < S > ,
541
+ stage : S ,
522
542
523
543
/// *Only* parse attributes with this symbol.
524
544
///
@@ -547,13 +567,14 @@ impl<'sess> AttributeParser<'sess, Early> {
547
567
sym : Symbol ,
548
568
target_span : Span ,
549
569
target_node_id : NodeId ,
570
+ features : Option < & ' sess Features > ,
550
571
) -> Option < Attribute > {
551
572
let mut p = Self {
552
- features : None ,
573
+ features,
553
574
tools : Vec :: new ( ) ,
554
575
parse_only : Some ( sym) ,
555
576
sess,
556
- stage : PhantomData ,
577
+ stage : Early { emit_errors : false } ,
557
578
} ;
558
579
let mut parsed = p. parse_attribute_list (
559
580
attrs,
@@ -569,11 +590,55 @@ impl<'sess> AttributeParser<'sess, Early> {
569
590
570
591
parsed. pop ( )
571
592
}
593
+
594
+ pub fn parse_single < T > (
595
+ sess : & ' sess Session ,
596
+ attr : & ast:: Attribute ,
597
+ target_span : Span ,
598
+ target_node_id : NodeId ,
599
+ features : Option < & ' sess Features > ,
600
+ emit_errors : bool ,
601
+ parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> T ,
602
+ template : & AttributeTemplate ,
603
+ ) -> T {
604
+ let mut parser = Self {
605
+ features,
606
+ tools : Vec :: new ( ) ,
607
+ parse_only : None ,
608
+ sess,
609
+ stage : Early { emit_errors } ,
610
+ } ;
611
+ let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
612
+ panic ! ( "parse_single called on a doc attr" )
613
+ } ;
614
+ let meta_parser = MetaItemParser :: from_attr ( normal_attr, parser. dcx ( ) ) ;
615
+ let path = meta_parser. path ( ) ;
616
+ let args = meta_parser. args ( ) ;
617
+ let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
618
+ shared : SharedContext {
619
+ cx : & mut parser,
620
+ target_span,
621
+ target_id : target_node_id,
622
+ emit_lint : & mut |_lint| {
623
+ panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
624
+ } ,
625
+ } ,
626
+ attr_span : attr. span ,
627
+ template,
628
+ attr_path : path. get_attribute_path ( ) ,
629
+ } ;
630
+ parse_fn ( & mut cx, args)
631
+ }
572
632
}
573
633
574
634
impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
575
- pub fn new ( sess : & ' sess Session , features : & ' sess Features , tools : Vec < Symbol > ) -> Self {
576
- Self { features : Some ( features) , tools, parse_only : None , sess, stage : PhantomData }
635
+ pub fn new (
636
+ sess : & ' sess Session ,
637
+ features : & ' sess Features ,
638
+ tools : Vec < Symbol > ,
639
+ stage : S ,
640
+ ) -> Self {
641
+ Self { features : Some ( features) , tools, parse_only : None , sess, stage }
577
642
}
578
643
579
644
pub ( crate ) fn sess ( & self ) -> & ' sess Session {
@@ -584,6 +649,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
584
649
self . features . expect ( "features not available at this point in the compiler" )
585
650
}
586
651
652
+ pub ( crate ) fn features_option ( & self ) -> Option < & ' sess Features > {
653
+ self . features
654
+ }
655
+
587
656
pub ( crate ) fn dcx ( & self ) -> DiagCtxtHandle < ' sess > {
588
657
self . sess ( ) . dcx ( )
589
658
}
0 commit comments