@@ -239,6 +239,7 @@ impl<'a> Parser<'a> {
239239 self . recover_const_impl ( const_span, attrs, def_ ( ) ) ?
240240 } else {
241241 self . recover_const_mut ( const_span) ;
242+ self . recover_missing_kw_before_item ( ) ?;
242243 let ( ident, generics, ty, expr) = self . parse_const_item ( ) ?;
243244 (
244245 ident,
@@ -311,6 +312,9 @@ impl<'a> Parser<'a> {
311312 Case :: Insensitive ,
312313 ) ;
313314 } else if macros_allowed && self . check_path ( ) {
315+ if self . isnt_macro_invocation ( ) {
316+ self . recover_missing_kw_before_item ( ) ?;
317+ }
314318 // MACRO INVOCATION ITEM
315319 ( Ident :: empty ( ) , ItemKind :: MacCall ( P ( self . parse_item_macro ( vis) ?) ) )
316320 } else {
@@ -374,25 +378,24 @@ impl<'a> Parser<'a> {
374378 self . check_ident ( ) && self . look_ahead ( 1 , |t| * t != token:: Not && * t != token:: PathSep )
375379 }
376380
377- /// Recover on encountering a struct or method definition where the user
378- /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`.
381+ /// Recover on encountering a struct, enum, or method definition where the user
382+ /// forgot to add the `struct`, `enum`, or `fn` keyword
379383 fn recover_missing_kw_before_item ( & mut self ) -> PResult < ' a , ( ) > {
380- // Space between `pub` keyword and the identifier
381- //
382- // pub S {}
383- // ^^^ `sp` points here
384- let sp = self . prev_token . span . between ( self . token . span ) ;
385- let full_sp = self . prev_token . span . to ( self . token . span ) ;
384+ let is_pub = self . prev_token . is_keyword ( kw:: Pub ) ;
385+ let is_const = self . prev_token . is_keyword ( kw:: Const ) ;
386+ let sp = self . token . span . shrink_to_lo ( ) ;
386387 let ident_sp = self . token . span ;
387388
388- let ident = if self . look_ahead ( 1 , |t| {
389- [
390- token:: Lt ,
391- token:: OpenDelim ( Delimiter :: Brace ) ,
392- token:: OpenDelim ( Delimiter :: Parenthesis ) ,
393- ]
394- . contains ( & t. kind )
395- } ) {
389+ let ident = if ( !is_const
390+ || self . look_ahead ( 1 , |t| * t == token:: OpenDelim ( Delimiter :: Parenthesis ) ) )
391+ && self . look_ahead ( 1 , |t| {
392+ [
393+ token:: Lt ,
394+ token:: OpenDelim ( Delimiter :: Brace ) ,
395+ token:: OpenDelim ( Delimiter :: Parenthesis ) ,
396+ ]
397+ . contains ( & t. kind )
398+ } ) {
396399 self . parse_ident ( ) . unwrap ( )
397400 } else {
398401 return Ok ( ( ) ) ;
@@ -406,11 +409,17 @@ impl<'a> Parser<'a> {
406409 }
407410
408411 let err = if self . check ( & token:: OpenDelim ( Delimiter :: Brace ) ) {
409- // possible public struct definition where `struct` was forgotten
410- Some ( errors:: MissingKeywordForItemDefinition :: Struct { span : sp, ident } )
412+ // possible struct or enum definition where `struct` or `enum` was forgotten
413+ if self . look_ahead ( 1 , |t| * t == token:: CloseDelim ( Delimiter :: Brace ) )
414+ || self . look_ahead ( 2 , |t| * t == token:: Colon )
415+ || self . look_ahead ( 3 , |t| * t == token:: Colon )
416+ {
417+ Some ( errors:: MissingKeywordForItemDefinition :: Struct { span : sp, ident } )
418+ } else {
419+ Some ( errors:: MissingKeywordForItemDefinition :: Enum { span : sp, ident } )
420+ }
411421 } else if self . check ( & token:: OpenDelim ( Delimiter :: Parenthesis ) ) {
412- // possible public function or tuple struct definition where `fn`/`struct` was
413- // forgotten
422+ // possible function or tuple struct definition where `fn` or `struct` was forgotten
414423 self . bump ( ) ; // `(`
415424 let is_method = self . recover_self_param ( ) ;
416425
@@ -426,7 +435,7 @@ impl<'a> Parser<'a> {
426435 } else {
427436 errors:: MissingKeywordForItemDefinition :: Function { span : sp, ident }
428437 }
429- } else if self . check ( & token:: Semi ) {
438+ } else if is_pub && self . check ( & token:: Semi ) {
430439 errors:: MissingKeywordForItemDefinition :: Struct { span : sp, ident }
431440 } else {
432441 errors:: MissingKeywordForItemDefinition :: Ambiguous {
@@ -435,7 +444,7 @@ impl<'a> Parser<'a> {
435444 None
436445 } else if let Ok ( snippet) = self . span_to_snippet ( ident_sp) {
437446 Some ( errors:: AmbiguousMissingKwForItemSub :: SuggestMacro {
438- span : full_sp ,
447+ span : ident_sp ,
439448 snippet,
440449 } )
441450 } else {
0 commit comments