@@ -515,7 +515,7 @@ impl<'a> Parser<'a> {
515515
516516 generics. where_clause = self . parse_where_clause ( ) ?;
517517
518- let ( impl_items, attrs) = self . parse_impl_body ( ) ?;
518+ let ( impl_items, attrs) = self . parse_item_list ( |p , at_end| p . parse_impl_item ( at_end ) ) ?;
519519
520520 let item_kind = match ty_second {
521521 Some ( ty_second) => {
@@ -571,15 +571,21 @@ impl<'a> Parser<'a> {
571571 Ok ( ( Ident :: invalid ( ) , item_kind, Some ( attrs) ) )
572572 }
573573
574- fn parse_impl_body ( & mut self ) -> PResult < ' a , ( Vec < P < AssocItem > > , Vec < Attribute > ) > {
574+ fn parse_item_list < T > (
575+ & mut self ,
576+ mut parse_item : impl FnMut ( & mut Parser < ' a > , & mut bool ) -> PResult < ' a , T > ,
577+ ) -> PResult < ' a , ( Vec < T > , Vec < Attribute > ) > {
575578 self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
576579 let attrs = self . parse_inner_attributes ( ) ?;
577580
578- let mut impl_items = Vec :: new ( ) ;
581+ let mut items = Vec :: new ( ) ;
579582 while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
583+ if self . recover_doc_comment_before_brace ( ) {
584+ continue ;
585+ }
580586 let mut at_end = false ;
581- match self . parse_impl_item ( & mut at_end) {
582- Ok ( impl_item ) => impl_items . push ( impl_item ) ,
587+ match parse_item ( self , & mut at_end) {
588+ Ok ( item ) => items . push ( item ) ,
583589 Err ( mut err) => {
584590 err. emit ( ) ;
585591 if !at_end {
@@ -589,7 +595,30 @@ impl<'a> Parser<'a> {
589595 }
590596 }
591597 }
592- Ok ( ( impl_items, attrs) )
598+ Ok ( ( items, attrs) )
599+ }
600+
601+ /// Recover on a doc comment before `}`.
602+ fn recover_doc_comment_before_brace ( & mut self ) -> bool {
603+ if let token:: DocComment ( _) = self . token . kind {
604+ if self . look_ahead ( 1 , |tok| tok == & token:: CloseDelim ( token:: Brace ) ) {
605+ struct_span_err ! (
606+ self . diagnostic( ) ,
607+ self . token. span,
608+ E0584 ,
609+ "found a documentation comment that doesn't document anything" ,
610+ )
611+ . span_label ( self . token . span , "this doc comment doesn't document anything" )
612+ . help (
613+ "doc comments must come before what they document, maybe a \
614+ comment was intended with `//`?",
615+ )
616+ . emit ( ) ;
617+ self . bump ( ) ;
618+ return true ;
619+ }
620+ }
621+ false
593622 }
594623
595624 /// Parses defaultness (i.e., `default` or nothing).
@@ -660,39 +689,8 @@ impl<'a> Parser<'a> {
660689 } else {
661690 // It's a normal trait.
662691 tps. where_clause = self . parse_where_clause ( ) ?;
663- self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
664- let mut trait_items = vec ! [ ] ;
665- while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
666- if let token:: DocComment ( _) = self . token . kind {
667- if self . look_ahead ( 1 , |tok| tok == & token:: CloseDelim ( token:: Brace ) ) {
668- struct_span_err ! (
669- self . diagnostic( ) ,
670- self . token. span,
671- E0584 ,
672- "found a documentation comment that doesn't document anything" ,
673- )
674- . help (
675- "doc comments must come before what they document, maybe a \
676- comment was intended with `//`?",
677- )
678- . emit ( ) ;
679- self . bump ( ) ;
680- continue ;
681- }
682- }
683- let mut at_end = false ;
684- match self . parse_trait_item ( & mut at_end) {
685- Ok ( item) => trait_items. push ( item) ,
686- Err ( mut e) => {
687- e. emit ( ) ;
688- if !at_end {
689- self . consume_block ( token:: Brace , ConsumeClosingDelim :: Yes ) ;
690- break ;
691- }
692- }
693- }
694- }
695- Ok ( ( ident, ItemKind :: Trait ( is_auto, unsafety, tps, bounds, trait_items) , None ) )
692+ let ( items, attrs) = self . parse_item_list ( |p, at_end| p. parse_trait_item ( at_end) ) ?;
693+ Ok ( ( ident, ItemKind :: Trait ( is_auto, unsafety, tps, bounds, items) , Some ( attrs) ) )
696694 }
697695 }
698696
@@ -942,26 +940,18 @@ impl<'a> Parser<'a> {
942940 & mut self ,
943941 lo : Span ,
944942 abi : Option < StrLit > ,
945- visibility : Visibility ,
943+ vis : Visibility ,
946944 mut attrs : Vec < Attribute > ,
947945 ) -> PResult < ' a , P < Item > > {
948- self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
949-
950- attrs. extend ( self . parse_inner_attributes ( ) ?) ;
951-
952- let mut foreign_items = vec ! [ ] ;
953- while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
954- foreign_items. push ( self . parse_foreign_item ( ) ?) ;
955- }
956-
957- let prev_span = self . prev_span ;
958- let m = ast:: ForeignMod { abi, items : foreign_items } ;
959- let invalid = Ident :: invalid ( ) ;
960- Ok ( self . mk_item ( lo. to ( prev_span) , invalid, ItemKind :: ForeignMod ( m) , visibility, attrs) )
946+ let ( items, iattrs) = self . parse_item_list ( |p, at_end| p. parse_foreign_item ( at_end) ) ?;
947+ attrs. extend ( iattrs) ;
948+ let span = lo. to ( self . prev_span ) ;
949+ let m = ast:: ForeignMod { abi, items } ;
950+ Ok ( self . mk_item ( span, Ident :: invalid ( ) , ItemKind :: ForeignMod ( m) , vis, attrs) )
961951 }
962952
963953 /// Parses a foreign item (one in an `extern { ... }` block).
964- pub fn parse_foreign_item ( & mut self ) -> PResult < ' a , P < ForeignItem > > {
954+ pub fn parse_foreign_item ( & mut self , at_end : & mut bool ) -> PResult < ' a , P < ForeignItem > > {
965955 maybe_whole ! ( self , NtForeignItem , |ni| ni) ;
966956
967957 let mut attrs = self . parse_outer_attributes ( ) ?;
@@ -973,7 +963,7 @@ impl<'a> Parser<'a> {
973963 self . parse_item_foreign_type ( ) ?
974964 } else if self . check_fn_front_matter ( ) {
975965 // FOREIGN FUNCTION ITEM
976- let ( ident, sig, generics, body) = self . parse_fn ( & mut false , & mut attrs, |_| true ) ?;
966+ let ( ident, sig, generics, body) = self . parse_fn ( at_end , & mut attrs, |_| true ) ?;
977967 ( ident, ForeignItemKind :: Fn ( sig, generics, body) )
978968 } else if self . is_static_global ( ) {
979969 // FOREIGN STATIC ITEM
@@ -991,7 +981,7 @@ impl<'a> Parser<'a> {
991981 )
992982 . emit ( ) ;
993983 self . parse_item_foreign_static ( ) ?
994- } else if let Some ( mac) = self . parse_assoc_macro_invoc ( "extern" , Some ( & vis) , & mut false ) ? {
984+ } else if let Some ( mac) = self . parse_assoc_macro_invoc ( "extern" , Some ( & vis) , at_end ) ? {
995985 ( Ident :: invalid ( ) , ForeignItemKind :: Macro ( mac) )
996986 } else {
997987 if !attrs. is_empty ( ) {
0 commit comments