11use std:: cell:: RefCell ;
22use std:: collections:: BTreeMap ;
3- use std:: marker:: PhantomData ;
43use std:: ops:: { Deref , DerefMut } ;
54use std:: sync:: LazyLock ;
65
@@ -15,6 +14,7 @@ use rustc_session::Session;
1514use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym} ;
1615
1716use crate :: attributes:: allow_unstable:: { AllowConstFnUnstableParser , AllowInternalUnstableParser } ;
17+ use crate :: attributes:: cfg:: CfgParser ;
1818use crate :: attributes:: codegen_attrs:: {
1919 ColdParser , ExportNameParser , NakedParser , NoMangleParser , OptimizeParser , TargetFeatureParser ,
2020 TrackCallerParser , UsedParser ,
@@ -121,6 +121,7 @@ attribute_parsers!(
121121 // tidy-alphabetical-start
122122 Combine <AllowConstFnUnstableParser >,
123123 Combine <AllowInternalUnstableParser >,
124+ Combine <CfgParser >,
124125 Combine <ReprParser >,
125126 Combine <TargetFeatureParser >,
126127 // tidy-alphabetical-end
@@ -171,7 +172,11 @@ pub trait Stage: Sized + 'static + Sealed {
171172
172173 fn parsers ( ) -> & ' static group_type ! ( Self ) ;
173174
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 ;
175180}
176181
177182// allow because it's a sealed trait
@@ -183,8 +188,16 @@ impl Stage for Early {
183188 fn parsers ( ) -> & ' static group_type ! ( Self ) {
184189 & early:: ATTRIBUTE_PARSERS
185190 }
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+ }
188201 }
189202}
190203
@@ -197,13 +210,22 @@ impl Stage for Late {
197210 fn parsers ( ) -> & ' static group_type ! ( Self ) {
198211 & late:: ATTRIBUTE_PARSERS
199212 }
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 {
201218 tcx. dcx ( ) . emit_err ( diag)
202219 }
203220}
204221
205222/// 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+ }
207229/// used when parsing attributes during ast lowering
208230pub struct Late ;
209231
@@ -226,7 +248,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> {
226248
227249impl < ' f , ' sess : ' f , S : Stage > SharedContext < ' f , ' sess , S > {
228250 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)
230252 }
231253
232254 /// 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> {
509531 pub ( crate ) tools : Vec < Symbol > ,
510532 features : Option < & ' sess Features > ,
511533 sess : & ' sess Session ,
512- stage : PhantomData < S > ,
534+ stage : S ,
513535
514536 /// *Only* parse attributes with this symbol.
515537 ///
@@ -538,13 +560,15 @@ impl<'sess> AttributeParser<'sess, Early> {
538560 sym : Symbol ,
539561 target_span : Span ,
540562 target_node_id : NodeId ,
563+ features : Option < & ' sess Features > ,
564+ emit_errors : bool ,
541565 ) -> Option < Attribute > {
542566 let mut p = Self {
543- features : None ,
567+ features,
544568 tools : Vec :: new ( ) ,
545569 parse_only : Some ( sym) ,
546570 sess,
547- stage : PhantomData ,
571+ stage : Early { emit_errors } ,
548572 } ;
549573 let mut parsed = p. parse_attribute_list (
550574 attrs,
@@ -563,8 +587,13 @@ impl<'sess> AttributeParser<'sess, Early> {
563587}
564588
565589impl < ' 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 }
568597 }
569598
570599 pub ( crate ) fn sess ( & self ) -> & ' sess Session {
@@ -575,6 +604,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
575604 self . features . expect ( "features not available at this point in the compiler" )
576605 }
577606
607+ pub ( crate ) fn features_option ( & self ) -> Option < & ' sess Features > {
608+ self . features
609+ }
610+
578611 pub ( crate ) fn dcx ( & self ) -> DiagCtxtHandle < ' sess > {
579612 self . sess ( ) . dcx ( )
580613 }
0 commit comments