@@ -515,7 +515,7 @@ impl<'a> Parser<'a> {
515
515
516
516
generics. where_clause = self . parse_where_clause ( ) ?;
517
517
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 ) ) ?;
519
519
520
520
let item_kind = match ty_second {
521
521
Some ( ty_second) => {
@@ -571,15 +571,21 @@ impl<'a> Parser<'a> {
571
571
Ok ( ( Ident :: invalid ( ) , item_kind, Some ( attrs) ) )
572
572
}
573
573
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 > ) > {
575
578
self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
576
579
let attrs = self . parse_inner_attributes ( ) ?;
577
580
578
- let mut impl_items = Vec :: new ( ) ;
581
+ let mut items = Vec :: new ( ) ;
579
582
while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
583
+ if self . recover_doc_comment_before_brace ( ) {
584
+ continue ;
585
+ }
580
586
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 ) ,
583
589
Err ( mut err) => {
584
590
err. emit ( ) ;
585
591
if !at_end {
@@ -589,7 +595,30 @@ impl<'a> Parser<'a> {
589
595
}
590
596
}
591
597
}
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
593
622
}
594
623
595
624
/// Parses defaultness (i.e., `default` or nothing).
@@ -660,39 +689,8 @@ impl<'a> Parser<'a> {
660
689
} else {
661
690
// It's a normal trait.
662
691
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) ) )
696
694
}
697
695
}
698
696
@@ -942,26 +940,18 @@ impl<'a> Parser<'a> {
942
940
& mut self ,
943
941
lo : Span ,
944
942
abi : Option < StrLit > ,
945
- visibility : Visibility ,
943
+ vis : Visibility ,
946
944
mut attrs : Vec < Attribute > ,
947
945
) -> 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) )
961
951
}
962
952
963
953
/// 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 > > {
965
955
maybe_whole ! ( self , NtForeignItem , |ni| ni) ;
966
956
967
957
let mut attrs = self . parse_outer_attributes ( ) ?;
@@ -973,7 +963,7 @@ impl<'a> Parser<'a> {
973
963
self . parse_item_foreign_type ( ) ?
974
964
} else if self . check_fn_front_matter ( ) {
975
965
// 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 ) ?;
977
967
( ident, ForeignItemKind :: Fn ( sig, generics, body) )
978
968
} else if self . is_static_global ( ) {
979
969
// FOREIGN STATIC ITEM
@@ -991,7 +981,7 @@ impl<'a> Parser<'a> {
991
981
)
992
982
. emit ( ) ;
993
983
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 ) ? {
995
985
( Ident :: invalid ( ) , ForeignItemKind :: Macro ( mac) )
996
986
} else {
997
987
if !attrs. is_empty ( ) {
0 commit comments