@@ -203,101 +203,107 @@ impl<'a> Parser<'a> {
203203 return Ok ( Some ( macro_def) ) ;
204204 }
205205
206- // Verify whether we have encountered a struct or method definition where the user forgot to
207- // add the `struct` or `fn` keyword after writing `pub`: `pub S {}`
208206 if vis. node . is_pub ( ) && self . check_ident ( ) && self . look_ahead ( 1 , |t| * t != token:: Not ) {
209- // Space between `pub` keyword and the identifier
210- //
211- // pub S {}
212- // ^^^ `sp` points here
213- let sp = self . prev_span . between ( self . token . span ) ;
214- let full_sp = self . prev_span . to ( self . token . span ) ;
215- let ident_sp = self . token . span ;
216- if self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Brace ) ) {
217- // possible public struct definition where `struct` was forgotten
218- let ident = self . parse_ident ( ) . unwrap ( ) ;
219- let msg = format ! ( "add `struct` here to parse `{}` as a public struct" , ident) ;
220- let mut err = self . struct_span_err ( sp, "missing `struct` for struct definition" ) ;
207+ self . recover_missing_kw_before_item ( ) ?;
208+ }
209+ self . parse_macro_use_or_failure ( attrs, macros_allowed, attributes_allowed, lo, vis)
210+ }
211+
212+ /// Recover on encountering a struct or method definition where the user
213+ /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`.
214+ fn recover_missing_kw_before_item ( & mut self ) -> PResult < ' a , ( ) > {
215+ // Space between `pub` keyword and the identifier
216+ //
217+ // pub S {}
218+ // ^^^ `sp` points here
219+ let sp = self . prev_span . between ( self . token . span ) ;
220+ let full_sp = self . prev_span . to ( self . token . span ) ;
221+ let ident_sp = self . token . span ;
222+ if self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Brace ) ) {
223+ // possible public struct definition where `struct` was forgotten
224+ let ident = self . parse_ident ( ) . unwrap ( ) ;
225+ let msg = format ! ( "add `struct` here to parse `{}` as a public struct" , ident) ;
226+ let mut err = self . struct_span_err ( sp, "missing `struct` for struct definition" ) ;
227+ err. span_suggestion_short (
228+ sp,
229+ & msg,
230+ " struct " . into ( ) ,
231+ Applicability :: MaybeIncorrect , // speculative
232+ ) ;
233+ return Err ( err) ;
234+ } else if self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Paren ) ) {
235+ let ident = self . parse_ident ( ) . unwrap ( ) ;
236+ self . bump ( ) ; // `(`
237+ let kw_name = self . recover_first_param ( ) ;
238+ self . consume_block ( token:: Paren , ConsumeClosingDelim :: Yes ) ;
239+ let ( kw, kw_name, ambiguous) = if self . check ( & token:: RArrow ) {
240+ self . eat_to_tokens ( & [ & token:: OpenDelim ( token:: Brace ) ] ) ;
241+ self . bump ( ) ; // `{`
242+ ( "fn" , kw_name, false )
243+ } else if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
244+ self . bump ( ) ; // `{`
245+ ( "fn" , kw_name, false )
246+ } else if self . check ( & token:: Colon ) {
247+ let kw = "struct" ;
248+ ( kw, kw, false )
249+ } else {
250+ ( "fn` or `struct" , "function or struct" , true )
251+ } ;
252+
253+ let msg = format ! ( "missing `{}` for {} definition" , kw, kw_name) ;
254+ let mut err = self . struct_span_err ( sp, & msg) ;
255+ if !ambiguous {
256+ self . consume_block ( token:: Brace , ConsumeClosingDelim :: Yes ) ;
257+ let suggestion =
258+ format ! ( "add `{}` here to parse `{}` as a public {}" , kw, ident, kw_name) ;
221259 err. span_suggestion_short (
222260 sp,
223- & msg ,
224- " struct " . into ( ) ,
225- Applicability :: MaybeIncorrect , // speculative
261+ & suggestion ,
262+ format ! ( " {} " , kw ) ,
263+ Applicability :: MachineApplicable ,
226264 ) ;
227- return Err ( err) ;
228- } else if self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( token:: Paren ) ) {
229- let ident = self . parse_ident ( ) . unwrap ( ) ;
230- self . bump ( ) ; // `(`
231- let kw_name = self . recover_first_param ( ) ;
232- self . consume_block ( token:: Paren , ConsumeClosingDelim :: Yes ) ;
233- let ( kw, kw_name, ambiguous) = if self . check ( & token:: RArrow ) {
234- self . eat_to_tokens ( & [ & token:: OpenDelim ( token:: Brace ) ] ) ;
235- self . bump ( ) ; // `{`
236- ( "fn" , kw_name, false )
237- } else if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
238- self . bump ( ) ; // `{`
239- ( "fn" , kw_name, false )
240- } else if self . check ( & token:: Colon ) {
241- let kw = "struct" ;
242- ( kw, kw, false )
243- } else {
244- ( "fn` or `struct" , "function or struct" , true )
245- } ;
246-
247- let msg = format ! ( "missing `{}` for {} definition" , kw, kw_name) ;
248- let mut err = self . struct_span_err ( sp, & msg) ;
249- if !ambiguous {
250- self . consume_block ( token:: Brace , ConsumeClosingDelim :: Yes ) ;
251- let suggestion =
252- format ! ( "add `{}` here to parse `{}` as a public {}" , kw, ident, kw_name) ;
253- err. span_suggestion_short (
254- sp,
255- & suggestion,
256- format ! ( " {} " , kw) ,
257- Applicability :: MachineApplicable ,
265+ } else {
266+ if let Ok ( snippet) = self . span_to_snippet ( ident_sp) {
267+ err. span_suggestion (
268+ full_sp,
269+ "if you meant to call a macro, try" ,
270+ format ! ( "{}!" , snippet) ,
271+ // this is the `ambiguous` conditional branch
272+ Applicability :: MaybeIncorrect ,
258273 ) ;
259274 } else {
260- if let Ok ( snippet) = self . span_to_snippet ( ident_sp) {
261- err. span_suggestion (
262- full_sp,
263- "if you meant to call a macro, try" ,
264- format ! ( "{}!" , snippet) ,
265- // this is the `ambiguous` conditional branch
266- Applicability :: MaybeIncorrect ,
267- ) ;
268- } else {
269- err. help (
270- "if you meant to call a macro, remove the `pub` \
275+ err. help (
276+ "if you meant to call a macro, remove the `pub` \
271277 and add a trailing `!` after the identifier",
272- ) ;
273- }
274- }
275- return Err ( err) ;
276- } else if self . look_ahead ( 1 , |t| * t == token:: Lt ) {
277- let ident = self . parse_ident ( ) . unwrap ( ) ;
278- self . eat_to_tokens ( & [ & token:: Gt ] ) ;
279- self . bump ( ) ; // `>`
280- let ( kw, kw_name, ambiguous) = if self . eat ( & token:: OpenDelim ( token:: Paren ) ) {
281- ( "fn" , self . recover_first_param ( ) , false )
282- } else if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
283- ( "struct" , "struct" , false )
284- } else {
285- ( "fn` or `struct" , "function or struct" , true )
286- } ;
287- let msg = format ! ( "missing `{}` for {} definition" , kw, kw_name) ;
288- let mut err = self . struct_span_err ( sp, & msg) ;
289- if !ambiguous {
290- err. span_suggestion_short (
291- sp,
292- & format ! ( "add `{}` here to parse `{}` as a public {}" , kw, ident, kw_name) ,
293- format ! ( " {} " , kw) ,
294- Applicability :: MachineApplicable ,
295278 ) ;
296279 }
297- return Err ( err) ;
298280 }
281+ return Err ( err) ;
282+ } else if self . look_ahead ( 1 , |t| * t == token:: Lt ) {
283+ let ident = self . parse_ident ( ) . unwrap ( ) ;
284+ self . eat_to_tokens ( & [ & token:: Gt ] ) ;
285+ self . bump ( ) ; // `>`
286+ let ( kw, kw_name, ambiguous) = if self . eat ( & token:: OpenDelim ( token:: Paren ) ) {
287+ ( "fn" , self . recover_first_param ( ) , false )
288+ } else if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
289+ ( "struct" , "struct" , false )
290+ } else {
291+ ( "fn` or `struct" , "function or struct" , true )
292+ } ;
293+ let msg = format ! ( "missing `{}` for {} definition" , kw, kw_name) ;
294+ let mut err = self . struct_span_err ( sp, & msg) ;
295+ if !ambiguous {
296+ err. span_suggestion_short (
297+ sp,
298+ & format ! ( "add `{}` here to parse `{}` as a public {}" , kw, ident, kw_name) ,
299+ format ! ( " {} " , kw) ,
300+ Applicability :: MachineApplicable ,
301+ ) ;
302+ }
303+ return Err ( err) ;
304+ } else {
305+ Ok ( ( ) )
299306 }
300- self . parse_macro_use_or_failure ( attrs, macros_allowed, attributes_allowed, lo, vis)
301307 }
302308
303309 pub ( super ) fn mk_item_with_info (
0 commit comments