@@ -27,18 +27,22 @@ use crate::diagnostics::{self, MalformedLoopLabel};
2727use crate :: exp;
2828
2929impl < ' a > Parser < ' a > {
30- /// Parses a statement. This stops just before trailing semicolons on everything but items.
30+ /// Parses a statement nonterminal, which has a peculiar syntax preserved for backward
31+ /// compatibility. The parsing stops just before trailing semicolons on everything but items.
3132 /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
3233 ///
3334 /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
3435 /// whether or not we have attributes.
3536 // Public for rustfmt usage.
36- pub fn parse_stmt ( & mut self , force_collect : ForceCollect ) -> PResult < ' a , Option < Stmt > > {
37- Ok ( self . parse_stmt_without_recovery ( false , force_collect, false ) . unwrap_or_else ( |e| {
38- e. emit ( ) ;
39- self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Ignore ) ;
40- None
41- } ) )
37+ pub fn parse_stmt_nonterminal ( & mut self , force_collect : ForceCollect ) -> Option < Stmt > {
38+ match self . parse_stmt_without_recovery ( false , force_collect, false ) {
39+ Ok ( stmt) => Some ( stmt) ,
40+ Err ( e) => {
41+ e. emit ( ) ;
42+ self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Ignore ) ;
43+ None
44+ }
45+ }
4246 }
4347
4448 /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
@@ -49,19 +53,18 @@ impl<'a> Parser<'a> {
4953 capture_semi : bool ,
5054 force_collect : ForceCollect ,
5155 force_full_expr : bool ,
52- ) -> PResult < ' a , Option < Stmt > > {
56+ ) -> PResult < ' a , Stmt > {
5357 let pre_attr_pos = self . collect_pos ( ) ;
5458 let attrs = self . parse_outer_attributes ( ) ?;
5559 let lo = self . token . span ;
5660
57- if let Some ( stmt) = self . eat_metavar_seq ( MetaVarKind :: Stmt , |this| {
61+ if let Some ( mut stmt) = self . eat_metavar_seq ( MetaVarKind :: Stmt , |this| {
5862 this. parse_stmt_without_recovery ( false , ForceCollect :: Yes , false )
5963 } ) {
60- let mut stmt = stmt. expect ( "an actual statement" ) ;
6164 stmt. visit_attrs ( |stmt_attrs| {
6265 attrs. prepend_to_nt_inner ( stmt_attrs) ;
6366 } ) ;
64- return Ok ( Some ( stmt) ) ;
67+ return Ok ( stmt) ;
6568 }
6669
6770 if self . token . is_keyword ( kw:: Mut ) && self . is_keyword_ahead ( 1 , & [ kw:: Let ] ) {
@@ -161,9 +164,12 @@ impl<'a> Parser<'a> {
161164 self . mk_stmt ( lo. to ( item. span ) , StmtKind :: Item ( Box :: new ( item) ) )
162165 } else if self . eat ( exp ! ( Semi ) ) {
163166 // Do not attempt to parse an expression if we're done here.
164- self . error_outer_attrs ( attrs) ;
167+ self . error_outer_attrs ( attrs) ? ;
165168 self . mk_stmt ( lo, StmtKind :: Empty )
166- } else if self . token != token:: CloseBrace {
169+ } else if self . token == token:: CloseBrace {
170+ self . error_outer_attrs ( attrs) ?;
171+ self . dcx ( ) . span_bug ( self . token . span , "don't parse a statement if you see `}`" ) ;
172+ } else {
167173 // Remainder are line-expr stmts. This is similar to the `parse_stmt_path_start` case
168174 // above.
169175 let restrictions =
@@ -185,13 +191,10 @@ impl<'a> Parser<'a> {
185191 . emit_err ( diagnostics:: AssignmentElseNotAllowed { span : e. span . to ( bl. span ) } ) ;
186192 }
187193 self . mk_stmt ( lo. to ( e. span ) , StmtKind :: Expr ( e) )
188- } else {
189- self . error_outer_attrs ( attrs) ;
190- return Ok ( None ) ;
191194 } ;
192195
193196 self . maybe_augment_stashed_expr_in_pats_with_suggestions ( & stmt) ;
194- Ok ( Some ( stmt) )
197+ Ok ( stmt)
195198 }
196199
197200 fn parse_stmt_path_start ( & mut self , lo : Span , attrs : AttrWrapper ) -> PResult < ' a , Stmt > {
@@ -272,20 +275,21 @@ impl<'a> Parser<'a> {
272275
273276 /// Error on outer attributes in this context.
274277 /// Also error if the previous token was a doc comment.
275- fn error_outer_attrs ( & self , attrs : AttrWrapper ) {
276- if !attrs. is_empty ( )
277- && let attrs @ [ .., last] = & * attrs. take_for_recovery ( self . psess )
278- {
279- if last. is_doc_comment ( ) {
280- self . dcx ( ) . emit_err ( diagnostics:: DocCommentDoesNotDocumentAnything {
281- span : last. span ,
282- missing_comma : None ,
283- } ) ;
284- } else if attrs. iter ( ) . any ( |a| a. style == AttrStyle :: Outer ) {
285- self . dcx ( )
286- . emit_err ( diagnostics:: ExpectedStatementAfterOuterAttr { span : last. span } ) ;
287- }
278+ fn error_outer_attrs ( & self , attrs : AttrWrapper ) -> PResult < ' a , ( ) > {
279+ if attrs. is_empty ( ) {
280+ return Ok ( ( ) ) ;
288281 }
282+ let attrs = attrs. take_for_recovery ( self . psess ) ;
283+ let last = attrs. last ( ) . unwrap ( ) ;
284+ Err ( if last. is_doc_comment ( ) {
285+ self . dcx ( ) . create_err ( diagnostics:: DocCommentDoesNotDocumentAnything {
286+ span : last. span ,
287+ missing_comma : None ,
288+ } )
289+ } else {
290+ assert_eq ! ( last. style, AttrStyle :: Outer ) ;
291+ self . dcx ( ) . create_err ( diagnostics:: ExpectedStatementAfterOuterAttr { span : last. span } )
292+ } )
289293 }
290294
291295 fn recover_stmt_local_after_let (
@@ -521,6 +525,10 @@ impl<'a> Parser<'a> {
521525 let sp = self . token . span ;
522526 let mut err = self . dcx ( ) . struct_span_err ( sp, msg) ;
523527 self . label_expected_raw_ref ( & mut err) ;
528+ err. span_label ( sp, "expected `{`" ) ;
529+ if self . token == token:: CloseBrace {
530+ return err;
531+ }
524532
525533 let do_not_suggest_help = self . token . is_keyword ( kw:: In )
526534 || self . token == token:: Colon
@@ -547,13 +555,13 @@ impl<'a> Parser<'a> {
547555 // since we want to protect against:
548556 // `if 1 1 + 1 {` being suggested as `if { 1 } 1 + 1 {`
549557 // + +
550- Ok ( Some ( _ ) )
558+ Ok ( _ )
551559 if ( !self . token . is_keyword ( kw:: Else )
552560 && self . look_ahead ( 1 , |t| t == & token:: OpenBrace ) )
553561 || do_not_suggest_help => { }
554562 // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836).
555- Ok ( Some ( Stmt { kind : StmtKind :: Empty , .. } ) ) => { }
556- Ok ( Some ( stmt) ) => {
563+ Ok ( Stmt { kind : StmtKind :: Empty , .. } ) => { }
564+ Ok ( stmt) => {
557565 let stmt_own_line = self . psess . source_map ( ) . is_line_before_span_empty ( sp) ;
558566 let stmt_span = if stmt_own_line && self . eat ( exp ! ( Semi ) ) {
559567 // Expand the span to include the semicolon.
@@ -571,9 +579,7 @@ impl<'a> Parser<'a> {
571579 Err ( e) => {
572580 e. delay_as_bug ( ) ;
573581 }
574- _ => { }
575582 }
576- err. span_label ( sp, "expected `{`" ) ;
577583 err
578584 }
579585
@@ -773,17 +779,12 @@ impl<'a> Parser<'a> {
773779
774780 let guar = err. emit ( ) ;
775781 self . recover_stmt_ ( SemiColonMode :: Ignore , BlockMode :: Ignore ) ;
776- Some ( self . mk_stmt_err ( self . token . span , guar) )
782+ self . mk_stmt_err ( self . token . span , guar)
777783 }
778784 Ok ( stmt) => stmt,
779785 Err ( err) => return Err ( err) ,
780786 } ;
781- if let Some ( stmt) = stmt {
782- stmts. push ( stmt) ;
783- } else {
784- // Found only `;` or `}`.
785- continue ;
786- } ;
787+ stmts. push ( stmt) ;
787788 }
788789 Ok ( self . mk_block ( stmts, s, lo. to ( self . prev_token . span ) ) )
789790 }
@@ -943,10 +944,7 @@ impl<'a> Parser<'a> {
943944 }
944945
945946 /// Parses a statement, including the trailing semicolon.
946- pub fn parse_full_stmt (
947- & mut self ,
948- recover : AttemptLocalParseRecovery ,
949- ) -> PResult < ' a , Option < Stmt > > {
947+ pub fn parse_full_stmt ( & mut self , recover : AttemptLocalParseRecovery ) -> PResult < ' a , Stmt > {
950948 // Skip looking for a trailing semicolon when we have a metavar seq.
951949 if let Some ( stmt) = self . eat_metavar_seq ( MetaVarKind :: Stmt , |this| {
952950 // Why pass `true` for `force_full_expr`? Statement expressions are less expressive
@@ -959,14 +957,10 @@ impl<'a> Parser<'a> {
959957 // will reparse successfully.
960958 this. parse_stmt_without_recovery ( false , ForceCollect :: No , true )
961959 } ) {
962- let stmt = stmt. expect ( "an actual statement" ) ;
963- return Ok ( Some ( stmt) ) ;
960+ return Ok ( stmt) ;
964961 }
965962
966- let Some ( mut stmt) = self . parse_stmt_without_recovery ( true , ForceCollect :: No , false ) ?
967- else {
968- return Ok ( None ) ;
969- } ;
963+ let mut stmt = self . parse_stmt_without_recovery ( true , ForceCollect :: No , false ) ?;
970964
971965 let mut eat_semi = true ;
972966 let mut add_semi_to_stmt = false ;
@@ -1086,7 +1080,7 @@ impl<'a> Parser<'a> {
10861080 StmtKind :: Expr ( _) | StmtKind :: MacCall ( _) => { }
10871081 StmtKind :: Let ( local) => {
10881082 if self . try_recover_let_missing_semi ( local) . is_some ( ) {
1089- return Ok ( Some ( stmt) ) ;
1083+ return Ok ( stmt) ;
10901084 }
10911085 if let Err ( mut e) = self . expect_semi ( ) {
10921086 // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
@@ -1159,7 +1153,7 @@ impl<'a> Parser<'a> {
11591153 }
11601154
11611155 stmt. span = stmt. span . to ( self . prev_token . span ) ;
1162- Ok ( Some ( stmt) )
1156+ Ok ( stmt)
11631157 }
11641158
11651159 pub ( super ) fn mk_block (
0 commit comments