@@ -15,6 +15,7 @@ use rustc_middle::ty::CurrentGcx;
1515use rustc_middle:: util:: Providers ;
1616use rustc_parse:: lexer:: StripTokens ;
1717use rustc_parse:: new_parser_from_source_str;
18+ use rustc_parse:: parser:: Recovery ;
1819use rustc_parse:: parser:: attr:: AllowLeadingUnsafe ;
1920use rustc_query_impl:: QueryCtxt ;
2021use rustc_query_system:: query:: print_query_stack;
@@ -52,7 +53,7 @@ pub struct Compiler {
5253pub ( crate ) fn parse_cfg ( dcx : DiagCtxtHandle < ' _ > , cfgs : Vec < String > ) -> Cfg {
5354 cfgs. into_iter ( )
5455 . map ( |s| {
55- let psess = ParseSess :: with_fatal_emitter (
56+ let psess = ParseSess :: with_error_emitter (
5657 vec ! [ crate :: DEFAULT_LOCALE_RESOURCE , rustc_parse:: DEFAULT_LOCALE_RESOURCE ] ,
5758 format ! ( "this error occurred on the command line: `--cfg={s}`" ) ,
5859 ) ;
@@ -63,47 +64,46 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
6364 #[ allow( rustc:: untranslatable_diagnostic) ]
6465 #[ allow( rustc:: diagnostic_outside_of_impl) ]
6566 dcx. fatal( format!(
66- concat! ( "invalid `--cfg` argument: `{}` ({})" ) ,
67+ "invalid `--cfg` argument: `{}` ({})" ,
6768 s, $reason,
6869 ) ) ;
6970 } ;
7071 }
7172
7273 match new_parser_from_source_str ( & psess, filename, s. to_string ( ) , StripTokens :: Nothing )
7374 {
74- Ok ( mut parser) => match parser. parse_meta_item ( AllowLeadingUnsafe :: No ) {
75- Ok ( meta_item) if parser. token == token:: Eof => {
76- if meta_item. path . segments . len ( ) != 1 {
77- error ! ( "argument key must be an identifier" ) ;
78- }
79- match & meta_item. kind {
80- MetaItemKind :: List ( ..) => { }
81- MetaItemKind :: NameValue ( lit) if !lit. kind . is_str ( ) => {
82- error ! ( "argument value must be a string" ) ;
75+ Ok ( mut parser) => {
76+ parser = parser. recovery ( Recovery :: Forbidden ) ;
77+ match parser. parse_meta_item ( AllowLeadingUnsafe :: No ) {
78+ Ok ( meta_item) if parser. token == token:: Eof => {
79+ if meta_item. path . segments . len ( ) != 1 {
80+ error ! ( "argument key must be an identifier" ) ;
8381 }
84- MetaItemKind :: NameValue ( ..) | MetaItemKind :: Word => {
85- let ident = meta_item. ident ( ) . expect ( "multi-segment cfg key" ) ;
82+ match & meta_item. kind {
83+ MetaItemKind :: List ( ..) => { }
84+ MetaItemKind :: NameValue ( lit) if !lit. kind . is_str ( ) => {
85+ error ! ( "argument value must be a string" ) ;
86+ }
87+ MetaItemKind :: NameValue ( ..) | MetaItemKind :: Word => {
88+ let ident = meta_item. ident ( ) . expect ( "multi-segment cfg key" ) ;
8689
87- if ident. is_reserved ( ) {
8890 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) ) ;
91+ error ! ( format!( "argument key must be an identifier, but `{}` cannot be a raw identifier" , ident. name) ) ;
9692 }
97- }
9893
99- return ( ident. name , meta_item. value_str ( ) ) ;
94+ return ( ident. name , meta_item. value_str ( ) ) ;
95+ }
10096 }
10197 }
98+ Ok ( ..) => { }
99+ Err ( err) => {
100+ err. emit ( ) ;
101+ } ,
102102 }
103- Ok ( ..) => { }
104- Err ( err) => err. cancel ( ) ,
105103 } ,
106- Err ( errs) => errs. into_iter ( ) . for_each ( |err| err. cancel ( ) ) ,
104+ Err ( errs) => errs. into_iter ( ) . for_each ( |err| {
105+ err. emit ( ) ;
106+ } ) ,
107107 } ;
108108
109109 // If the user tried to use a key="value" flag, but is missing the quotes, provide
@@ -129,7 +129,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
129129 let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg :: default ( ) } ;
130130
131131 for s in specs {
132- let psess = ParseSess :: with_fatal_emitter (
132+ let psess = ParseSess :: with_error_emitter (
133133 vec ! [ crate :: DEFAULT_LOCALE_RESOURCE , rustc_parse:: DEFAULT_LOCALE_RESOURCE ] ,
134134 format ! ( "this error occurred on the command line: `--check-cfg={s}`" ) ,
135135 ) ;
@@ -186,16 +186,19 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
186186 {
187187 Ok ( parser) => parser,
188188 Err ( errs) => {
189- errs. into_iter ( ) . for_each ( |err| err. cancel ( ) ) ;
189+ errs. into_iter ( ) . for_each ( |err| {
190+ err. emit ( ) ;
191+ } ) ;
190192 expected_error ( ) ;
191193 }
192194 } ;
195+ parser = parser. recovery ( Recovery :: Forbidden ) ;
193196
194197 let meta_item = match parser. parse_meta_item ( AllowLeadingUnsafe :: No ) {
195198 Ok ( meta_item) if parser. token == token:: Eof => meta_item,
196199 Ok ( ..) => expected_error ( ) ,
197200 Err ( err) => {
198- err. cancel ( ) ;
201+ err. emit ( ) ;
199202 expected_error ( ) ;
200203 }
201204 } ;
@@ -215,13 +218,6 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
215218 let mut values_specified = false ;
216219 let mut values_any_specified = false ;
217220
218- let arg_strs = s
219- . trim ( )
220- . trim_start_matches ( "cfg(" )
221- . trim_end_matches ( ')' )
222- . split ( ',' )
223- . collect :: < Vec < _ > > ( ) ;
224-
225221 for arg in args {
226222 if arg. is_word ( )
227223 && let Some ( ident) = arg. ident ( )
@@ -230,26 +226,11 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
230226 error ! ( "`cfg()` names cannot be after values" ) ;
231227 }
232228
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- }
229+ if !ident. name . can_be_raw ( ) {
230+ error ! ( format!(
231+ "argument key must be an identifier, but `{}` cannot be a raw identifier" ,
232+ ident. name
233+ ) ) ;
253234 }
254235
255236 names. push ( ident) ;
@@ -258,11 +239,6 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
258239 error ! ( "`cfg()` names cannot be after values" ) ;
259240 }
260241
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-
266242 names. push ( rustc_span:: Ident :: new (
267243 if boolean { rustc_span:: kw:: True } else { rustc_span:: kw:: False } ,
268244 arg. span ( ) ,
0 commit comments