@@ -63,8 +63,8 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
6363 #[ allow( rustc:: untranslatable_diagnostic) ]
6464 #[ allow( rustc:: diagnostic_outside_of_impl) ]
6565 dcx. fatal( format!(
66- concat!( "invalid `--cfg` argument: `{}` (" , $reason , " )") ,
67- s
66+ concat!( "invalid `--cfg` argument: `{}` ({} )" ) ,
67+ s, $reason ,
6868 ) ) ;
6969 } ;
7070 }
@@ -83,6 +83,19 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
8383 }
8484 MetaItemKind :: NameValue ( ..) | MetaItemKind :: Word => {
8585 let ident = meta_item. ident ( ) . expect ( "multi-segment cfg key" ) ;
86+
87+ if ident. is_reserved ( ) {
88+ if !ident. name . can_be_raw ( ) {
89+ if s. trim ( ) . starts_with ( & format ! ( "r#{}" , ident. as_str( ) ) ) {
90+ error ! ( format!( "argument key must be an identifier, but `{}` cannot be a raw identifier" , ident. name) ) ;
91+ } else {
92+ error ! ( format!( "argument key must be an identifier but found keyword `{}`" , ident. name) ) ;
93+ }
94+ } else if !s. trim ( ) . starts_with ( & ident. to_string ( ) ) {
95+ error ! ( format!( "argument key must be an identifier but found keyword `{}`, escape it using `{}`" , ident. as_str( ) , ident) ) ;
96+ }
97+ }
98+
8699 return ( ident. name , meta_item. value_str ( ) ) ;
87100 }
88101 }
@@ -91,7 +104,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
91104 Err ( err) => err. cancel ( ) ,
92105 } ,
93106 Err ( errs) => errs. into_iter ( ) . for_each ( |err| err. cancel ( ) ) ,
94- }
107+ } ;
95108
96109 // If the user tried to use a key="value" flag, but is missing the quotes, provide
97110 // a hint about how to resolve this.
@@ -202,18 +215,54 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
202215 let mut values_specified = false ;
203216 let mut values_any_specified = false ;
204217
218+ let arg_strs = s
219+ . trim ( )
220+ . trim_start_matches ( "cfg(" )
221+ . trim_end_matches ( ')' )
222+ . split ( ',' )
223+ . collect :: < Vec < _ > > ( ) ;
224+
205225 for arg in args {
206226 if arg. is_word ( )
207227 && let Some ( ident) = arg. ident ( )
208228 {
209229 if values_specified {
210230 error ! ( "`cfg()` names cannot be after values" ) ;
211231 }
232+
233+ if ident. is_reserved ( ) {
234+ if !ident. name . can_be_raw ( ) {
235+ if arg_strs[ names. len ( ) ] . starts_with ( & format ! ( "r#{}" , ident. as_str( ) ) ) {
236+ error ! ( format!(
237+ "argument key must be an identifier, but `{}` cannot be a raw identifier" ,
238+ ident. name
239+ ) ) ;
240+ } else {
241+ error ! ( format!(
242+ "argument key must be an identifier but found keyword `{}`" ,
243+ ident. name
244+ ) ) ;
245+ }
246+ } else if !arg_strs[ names. len ( ) ] . starts_with ( & ident. to_string ( ) ) {
247+ error ! ( format!(
248+ "argument key must be an identifier but found keyword `{}`, escape it using `{}`" ,
249+ ident. as_str( ) ,
250+ ident
251+ ) ) ;
252+ }
253+ }
254+
212255 names. push ( ident) ;
213256 } else if let Some ( boolean) = arg. boolean_literal ( ) {
214257 if values_specified {
215258 error ! ( "`cfg()` names cannot be after values" ) ;
216259 }
260+
261+ let lit_str = arg_strs[ names. len ( ) ] ;
262+ if !lit_str. starts_with ( "r#" ) {
263+ error ! ( in arg, format!( "`cfg()` names must be identifiers but found keyword `{lit_str}`, escape it using `r#{lit_str}`" ) ) ;
264+ }
265+
217266 names. push ( rustc_span:: Ident :: new (
218267 if boolean { rustc_span:: kw:: True } else { rustc_span:: kw:: False } ,
219268 arg. span ( ) ,
0 commit comments