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
@@ -15,6 +14,7 @@ use rustc_session::Session;
15
14
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym} ;
16
15
17
16
use crate :: attributes:: allow_unstable:: { AllowConstFnUnstableParser , AllowInternalUnstableParser } ;
17
+ use crate :: attributes:: cfg:: CfgParser ;
18
18
use crate :: attributes:: codegen_attrs:: {
19
19
ColdParser , ExportNameParser , NakedParser , NoMangleParser , OptimizeParser , TargetFeatureParser ,
20
20
TrackCallerParser , UsedParser ,
@@ -121,6 +121,7 @@ attribute_parsers!(
121
121
// tidy-alphabetical-start
122
122
Combine <AllowConstFnUnstableParser >,
123
123
Combine <AllowInternalUnstableParser >,
124
+ Combine <CfgParser >,
124
125
Combine <ReprParser >,
125
126
Combine <TargetFeatureParser >,
126
127
// tidy-alphabetical-end
@@ -171,7 +172,11 @@ pub trait Stage: Sized + 'static + Sealed {
171
172
172
173
fn parsers ( ) -> & ' static group_type ! ( Self ) ;
173
174
174
- fn emit_err < ' sess > ( sess : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed ;
175
+ fn emit_err < ' sess > (
176
+ & self ,
177
+ sess : & ' sess Session ,
178
+ diag : impl for < ' x > Diagnostic < ' x > ,
179
+ ) -> ErrorGuaranteed ;
175
180
}
176
181
177
182
// allow because it's a sealed trait
@@ -183,8 +188,16 @@ impl Stage for Early {
183
188
fn parsers ( ) -> & ' static group_type ! ( Self ) {
184
189
& early:: ATTRIBUTE_PARSERS
185
190
}
186
- fn emit_err < ' sess > ( sess : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
187
- sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
191
+ fn emit_err < ' sess > (
192
+ & self ,
193
+ sess : & ' sess Session ,
194
+ diag : impl for < ' x > Diagnostic < ' x > ,
195
+ ) -> ErrorGuaranteed {
196
+ if self . emit_errors {
197
+ sess. dcx ( ) . emit_err ( diag)
198
+ } else {
199
+ sess. dcx ( ) . create_err ( diag) . delay_as_bug ( )
200
+ }
188
201
}
189
202
}
190
203
@@ -197,13 +210,22 @@ impl Stage for Late {
197
210
fn parsers ( ) -> & ' static group_type ! ( Self ) {
198
211
& late:: ATTRIBUTE_PARSERS
199
212
}
200
- fn emit_err < ' sess > ( tcx : & ' sess Session , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
213
+ fn emit_err < ' sess > (
214
+ & self ,
215
+ tcx : & ' sess Session ,
216
+ diag : impl for < ' x > Diagnostic < ' x > ,
217
+ ) -> ErrorGuaranteed {
201
218
tcx. dcx ( ) . emit_err ( diag)
202
219
}
203
220
}
204
221
205
222
/// used when parsing attributes for miscellaneous things *before* ast lowering
206
- pub struct Early ;
223
+ pub struct Early {
224
+ /// Whether to emit errors or delay them as a bug
225
+ /// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
226
+ /// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
227
+ pub emit_errors : bool ,
228
+ }
207
229
/// used when parsing attributes during ast lowering
208
230
pub struct Late ;
209
231
@@ -226,7 +248,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
226
248
227
249
impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
228
250
pub ( crate ) fn emit_err ( & self , diag : impl for < ' x > Diagnostic < ' x > ) -> ErrorGuaranteed {
229
- S :: emit_err ( & self . sess , diag)
251
+ self . stage . emit_err ( & self . sess , diag)
230
252
}
231
253
232
254
/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
@@ -509,7 +531,7 @@ pub struct AttributeParser<'sess, S: Stage = Late> {
509
531
pub ( crate ) tools : Vec < Symbol > ,
510
532
features : Option < & ' sess Features > ,
511
533
sess : & ' sess Session ,
512
- stage : PhantomData < S > ,
534
+ stage : S ,
513
535
514
536
/// *Only* parse attributes with this symbol.
515
537
///
@@ -538,13 +560,15 @@ impl<'sess> AttributeParser<'sess, Early> {
538
560
sym : Symbol ,
539
561
target_span : Span ,
540
562
target_node_id : NodeId ,
563
+ features : Option < & ' sess Features > ,
564
+ emit_errors : bool ,
541
565
) -> Option < Attribute > {
542
566
let mut p = Self {
543
- features : None ,
567
+ features,
544
568
tools : Vec :: new ( ) ,
545
569
parse_only : Some ( sym) ,
546
570
sess,
547
- stage : PhantomData ,
571
+ stage : Early { emit_errors } ,
548
572
} ;
549
573
let mut parsed = p. parse_attribute_list (
550
574
attrs,
@@ -563,8 +587,13 @@ impl<'sess> AttributeParser<'sess, Early> {
563
587
}
564
588
565
589
impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
566
- pub fn new ( sess : & ' sess Session , features : & ' sess Features , tools : Vec < Symbol > ) -> Self {
567
- Self { features : Some ( features) , tools, parse_only : None , sess, stage : PhantomData }
590
+ pub fn new (
591
+ sess : & ' sess Session ,
592
+ features : & ' sess Features ,
593
+ tools : Vec < Symbol > ,
594
+ stage : S ,
595
+ ) -> Self {
596
+ Self { features : Some ( features) , tools, parse_only : None , sess, stage }
568
597
}
569
598
570
599
pub ( crate ) fn sess ( & self ) -> & ' sess Session {
@@ -575,6 +604,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
575
604
self . features . expect ( "features not available at this point in the compiler" )
576
605
}
577
606
607
+ pub ( crate ) fn features_option ( & self ) -> Option < & ' sess Features > {
608
+ self . features
609
+ }
610
+
578
611
pub ( crate ) fn dcx ( & self ) -> DiagCtxtHandle < ' sess > {
579
612
self . sess ( ) . dcx ( )
580
613
}
0 commit comments