@@ -125,8 +125,13 @@ pub fn parse_cfgspecs(
125125/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`. 
126126pub  fn  parse_check_cfg ( handler :  & EarlyErrorHandler ,  specs :  Vec < String > )  -> CheckCfg  { 
127127    rustc_span:: create_default_session_if_not_set_then ( move  |_| { 
128-         let  mut  check_cfg = CheckCfg :: default ( ) ; 
128+         // If any --check-cfg is passed then exhaustive_values and exhaustive_names 
129+         // are enabled by default. 
130+         let  exhaustive_names = !specs. is_empty ( ) ; 
131+         let  exhaustive_values = !specs. is_empty ( ) ; 
132+         let  mut  check_cfg = CheckCfg  {  exhaustive_names,  exhaustive_values,  ..CheckCfg :: default ( )  } ; 
129133
134+         let  mut  old_syntax = None ; 
130135        for  s in  specs { 
131136            let  sess = ParseSess :: with_silent_emitter ( Some ( format ! ( 
132137                "this error occurred on the command line: `--check-cfg={s}`" 
@@ -142,18 +147,21 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
142147                } ; 
143148            } 
144149
145-             let  expected_error = || { 
146-                 error ! ( 
147-                     "expected `names(name1, name2, ... nameN)` or \  
148- \" value1\" , \" value2\" , ... \" valueN\" )`"
149-                 ) 
150-             } ; 
150+             let  expected_error =
151+                 || error ! ( "expected `cfg(name, values(\" value1\" , \" value2\" , ... \" valueN\" ))`" ) ; 
151152
152153            match  maybe_new_parser_from_source_str ( & sess,  filename,  s. to_string ( ) )  { 
153154                Ok ( mut  parser)  => match  parser. parse_meta_item ( )  { 
154155                    Ok ( meta_item)  if  parser. token  == token:: Eof  => { 
155156                        if  let  Some ( args)  = meta_item. meta_item_list ( )  { 
156157                            if  meta_item. has_name ( sym:: names)  { 
158+                                 // defaults are flipped for the old syntax 
159+                                 if  old_syntax == None  { 
160+                                     check_cfg. exhaustive_names  = false ; 
161+                                     check_cfg. exhaustive_values  = false ; 
162+                                 } 
163+                                 old_syntax = Some ( true ) ; 
164+ 
157165                                check_cfg. exhaustive_names  = true ; 
158166                                for  arg in  args { 
159167                                    if  arg. is_word ( )  && arg. ident ( ) . is_some ( )  { 
@@ -167,6 +175,13 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
167175                                    } 
168176                                } 
169177                            }  else  if  meta_item. has_name ( sym:: values)  { 
178+                                 // defaults are flipped for the old syntax 
179+                                 if  old_syntax == None  { 
180+                                     check_cfg. exhaustive_names  = false ; 
181+                                     check_cfg. exhaustive_values  = false ; 
182+                                 } 
183+                                 old_syntax = Some ( true ) ; 
184+ 
170185                                if  let  Some ( ( name,  values) )  = args. split_first ( )  { 
171186                                    if  name. is_word ( )  && name. ident ( ) . is_some ( )  { 
172187                                        let  ident = name. ident ( ) . expect ( "multi-segment cfg key" ) ; 
@@ -216,6 +231,116 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
216231                                }  else  { 
217232                                    expected_error ( ) ; 
218233                                } 
234+                             }  else  if  meta_item. has_name ( sym:: cfg)  { 
235+                                 old_syntax = Some ( false ) ; 
236+ 
237+                                 let  mut  names = Vec :: new ( ) ; 
238+                                 let  mut  values:  FxHashSet < _ >  = Default :: default ( ) ; 
239+ 
240+                                 let  mut  any_specified = false ; 
241+                                 let  mut  values_specified = false ; 
242+                                 let  mut  values_any_specified = false ; 
243+ 
244+                                 for  arg in  args { 
245+                                     if  arg. is_word ( )  && let  Some ( ident)  = arg. ident ( )  { 
246+                                         if  values_specified { 
247+                                             error ! ( "`cfg()` names cannot be after values" ) ; 
248+                                         } 
249+                                         names. push ( ident) ; 
250+                                     }  else  if  arg. has_name ( sym:: any) 
251+                                         && let  Some ( args)  = arg. meta_item_list ( ) 
252+                                     { 
253+                                         if  any_specified { 
254+                                             error ! ( "`any()` cannot be specified multiple times" ) ; 
255+                                         } 
256+                                         any_specified = true ; 
257+                                         if  !args. is_empty ( )  { 
258+                                             error ! ( "`any()` must be empty" ) ; 
259+                                         } 
260+                                     }  else  if  arg. has_name ( sym:: values) 
261+                                         && let  Some ( args)  = arg. meta_item_list ( ) 
262+                                     { 
263+                                         if  names. is_empty ( )  { 
264+                                             error ! ( 
265+                                                 "`values()` cannot be specified before the names" 
266+                                             ) ; 
267+                                         }  else  if  values_specified { 
268+                                             error ! ( 
269+                                                 "`values()` cannot be specified multiple times" 
270+                                             ) ; 
271+                                         } 
272+                                         values_specified = true ; 
273+ 
274+                                         for  arg in  args { 
275+                                             if  let  Some ( LitKind :: Str ( s,  _) )  =
276+                                                 arg. lit ( ) . map ( |lit| & lit. kind ) 
277+                                             { 
278+                                                 values. insert ( Some ( s. to_string ( ) ) ) ; 
279+                                             }  else  if  arg. has_name ( sym:: any) 
280+                                                 && let  Some ( args)  = arg. meta_item_list ( ) 
281+                                             { 
282+                                                 if  values_any_specified { 
283+                                                     error ! ( 
284+                                                         "`any()` in `values()` cannot be specified multiple times" 
285+                                                     ) ; 
286+                                                 } 
287+                                                 values_any_specified = true ; 
288+                                                 if  !args. is_empty ( )  { 
289+                                                     error ! ( "`any()` must be empty" ) ; 
290+                                                 } 
291+                                             }  else  { 
292+                                                 error ! ( 
293+                                                     "`values()` arguments must be string literals or `any()`" 
294+                                                 ) ; 
295+                                             } 
296+                                         } 
297+                                     }  else  { 
298+                                         error ! ( 
299+                                             "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`" 
300+                                         ) ; 
301+                                     } 
302+                                 } 
303+ 
304+                                 if  values. is_empty ( )  && !values_any_specified && !any_specified { 
305+                                     values. insert ( None ) ; 
306+                                 }  else  if  !values. is_empty ( )  && values_any_specified { 
307+                                     error ! ( 
308+                                         "`values()` arguments cannot specify string literals and `any()` at the same time" 
309+                                     ) ; 
310+                                 } 
311+ 
312+                                 if  any_specified { 
313+                                     if  !names. is_empty ( ) 
314+                                         || !values. is_empty ( ) 
315+                                         || values_any_specified
316+                                     { 
317+                                         error ! ( "`cfg(any())` can only be provided in isolation" ) ; 
318+                                     } 
319+ 
320+                                     check_cfg. exhaustive_names  = false ; 
321+                                 }  else  { 
322+                                     for  name in  names { 
323+                                         check_cfg
324+                                             . expecteds 
325+                                             . entry ( name. to_string ( ) ) 
326+                                             . and_modify ( |v| match  v { 
327+                                                 ExpectedValues :: Some ( v) 
328+                                                     if  !values_any_specified =>
329+                                                 { 
330+                                                     v. extend ( values. clone ( ) ) 
331+                                                 } 
332+                                                 ExpectedValues :: Some ( _)  => * v = ExpectedValues :: Any , 
333+                                                 ExpectedValues :: Any  => { } 
334+                                             } ) 
335+                                             . or_insert_with ( || { 
336+                                                 if  values_any_specified { 
337+                                                     ExpectedValues :: Any 
338+                                                 }  else  { 
339+                                                     ExpectedValues :: Some ( values. clone ( ) ) 
340+                                                 } 
341+                                             } ) ; 
342+                                     } 
343+                                 } 
219344                            }  else  { 
220345                                expected_error ( ) ; 
221346                            } 
0 commit comments