@@ -35,61 +35,32 @@ impl<'a> Parser<'a> {
3535        let  attrs = self . parse_outer_attributes ( ) ?; 
3636        let  lo = self . token . span ; 
3737
38-         if  self . eat_keyword ( kw:: Let )  { 
39-             return  self . parse_local_mk ( lo,  attrs. into ( ) ) . map ( Some ) ; 
40-         } 
41-         if  self . is_kw_followed_by_ident ( kw:: Mut )  { 
42-             return  self . recover_stmt_local ( lo,  attrs. into ( ) ,  "missing keyword" ,  "let mut" ) ; 
43-         } 
44-         if  self . is_kw_followed_by_ident ( kw:: Auto )  { 
38+         let  stmt = if  self . eat_keyword ( kw:: Let )  { 
39+             self . parse_local_mk ( lo,  attrs. into ( ) ) ?
40+         }  else  if  self . is_kw_followed_by_ident ( kw:: Mut )  { 
41+             self . recover_stmt_local ( lo,  attrs. into ( ) ,  "missing keyword" ,  "let mut" ) ?
42+         }  else  if  self . is_kw_followed_by_ident ( kw:: Auto )  { 
4543            self . bump ( ) ;  // `auto` 
4644            let  msg = "write `let` instead of `auto` to introduce a new variable" ; 
47-             return  self . recover_stmt_local ( lo,  attrs. into ( ) ,  msg,  "let" ) ; 
48-         } 
49-         if  self . is_kw_followed_by_ident ( sym:: var)  { 
45+             self . recover_stmt_local ( lo,  attrs. into ( ) ,  msg,  "let" ) ?
46+         }  else  if  self . is_kw_followed_by_ident ( sym:: var)  { 
5047            self . bump ( ) ;  // `var` 
5148            let  msg = "write `let` instead of `var` to introduce a new variable" ; 
52-             return  self . recover_stmt_local ( lo,  attrs. into ( ) ,  msg,  "let" ) ; 
53-         } 
54- 
55-         // Starts like a simple path, being careful to avoid contextual keywords, 
56-         // e.g., `union`, items with `crate` visibility, or `auto trait` items. 
57-         // We aim to parse an arbitrary path `a::b` but not something that starts like a path 
58-         // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`. 
59-         if  self . token . is_path_start ( )  && !self . token . is_qpath_start ( )  && !self . is_path_start_item ( ) 
49+             self . recover_stmt_local ( lo,  attrs. into ( ) ,  msg,  "let" ) ?
50+         }  else  if  self . token . is_path_start ( ) 
51+             && !self . token . is_qpath_start ( ) 
52+             && !self . is_path_start_item ( ) 
6053        { 
61-             let  path = self . parse_path ( PathStyle :: Expr ) ?; 
62- 
63-             if  self . eat ( & token:: Not )  { 
64-                 return  self . parse_stmt_mac ( lo,  attrs. into ( ) ,  path) ; 
65-             } 
66- 
67-             let  expr = if  self . check ( & token:: OpenDelim ( token:: Brace ) )  { 
68-                 self . parse_struct_expr ( lo,  path,  AttrVec :: new ( ) ) ?
69-             }  else  { 
70-                 let  hi = self . prev_span ; 
71-                 self . mk_expr ( lo. to ( hi) ,  ExprKind :: Path ( None ,  path) ,  AttrVec :: new ( ) ) 
72-             } ; 
73- 
74-             let  expr = self . with_res ( Restrictions :: STMT_EXPR ,  |this| { 
75-                 let  expr = this. parse_dot_or_call_expr_with ( expr,  lo,  attrs. into ( ) ) ?; 
76-                 this. parse_assoc_expr_with ( 0 ,  LhsExpr :: AlreadyParsed ( expr) ) 
77-             } ) ?; 
78-             return  Ok ( Some ( self . mk_stmt ( lo. to ( self . prev_span ) ,  StmtKind :: Expr ( expr) ) ) ) ; 
79-         } 
80- 
81-         // FIXME: Bad copy of attrs 
82-         let  old_directory_ownership =
83-             mem:: replace ( & mut  self . directory . ownership ,  DirectoryOwnership :: UnownedViaBlock ) ; 
84-         let  item = self . parse_item_common ( attrs. clone ( ) ,  false ,  true ,  |_| true ) ?; 
85-         self . directory . ownership  = old_directory_ownership; 
86- 
87-         if  let  Some ( item)  = item { 
88-             return  Ok ( Some ( self . mk_stmt ( lo. to ( item. span ) ,  StmtKind :: Item ( P ( item) ) ) ) ) ; 
89-         } 
90- 
91-         // Do not attempt to parse an expression if we're done here. 
92-         if  self . token  == token:: Semi  { 
54+             // We have avoided contextual keywords like `union`, items with `crate` visibility, 
55+             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something 
56+             // that starts like a path (1 token), but it fact not a path. 
57+             // Also, we avoid stealing syntax from `parse_item_`. 
58+             self . parse_stmt_path_start ( lo,  attrs) ?
59+         }  else  if  let  Some ( item)  = self . parse_stmt_item ( attrs. clone ( ) ) ? { 
60+             // FIXME: Bad copy of attrs 
61+             self . mk_stmt ( lo. to ( item. span ) ,  StmtKind :: Item ( P ( item) ) ) 
62+         }  else  if  self . token  == token:: Semi  { 
63+             // Do not attempt to parse an expression if we're done here. 
9364            self . error_outer_attrs ( & attrs) ; 
9465            self . bump ( ) ; 
9566            let  mut  last_semi = lo; 
@@ -104,27 +75,49 @@ impl<'a> Parser<'a> {
10475                ExprKind :: Tup ( Vec :: new ( ) ) , 
10576                AttrVec :: new ( ) , 
10677            ) ) ; 
107-             return  Ok ( Some ( self . mk_stmt ( lo. to ( last_semi) ,  kind) ) ) ; 
108-         } 
109- 
110-         if  self . token  == token:: CloseDelim ( token:: Brace )  { 
78+             self . mk_stmt ( lo. to ( last_semi) ,  kind) 
79+         }  else  if  self . token  != token:: CloseDelim ( token:: Brace )  { 
80+             // Remainder are line-expr stmts. 
81+             let  e = self . parse_expr_res ( Restrictions :: STMT_EXPR ,  Some ( attrs. into ( ) ) ) ?; 
82+             self . mk_stmt ( lo. to ( e. span ) ,  StmtKind :: Expr ( e) ) 
83+         }  else  { 
11184            self . error_outer_attrs ( & attrs) ; 
11285            return  Ok ( None ) ; 
86+         } ; 
87+         Ok ( Some ( stmt) ) 
88+     } 
89+ 
90+     fn  parse_stmt_item ( & mut  self ,  attrs :  Vec < Attribute > )  -> PResult < ' a ,  Option < ast:: Item > >  { 
91+         let  old = mem:: replace ( & mut  self . directory . ownership ,  DirectoryOwnership :: UnownedViaBlock ) ; 
92+         let  item = self . parse_item_common ( attrs. clone ( ) ,  false ,  true ,  |_| true ) ?; 
93+         self . directory . ownership  = old; 
94+         Ok ( item) 
95+     } 
96+ 
97+     fn  parse_stmt_path_start ( & mut  self ,  lo :  Span ,  attrs :  Vec < Attribute > )  -> PResult < ' a ,  Stmt >  { 
98+         let  path = self . parse_path ( PathStyle :: Expr ) ?; 
99+ 
100+         if  self . eat ( & token:: Not )  { 
101+             return  self . parse_stmt_mac ( lo,  attrs. into ( ) ,  path) ; 
113102        } 
114103
115-         // Remainder are line-expr stmts. 
116-         let  e = self . parse_expr_res ( Restrictions :: STMT_EXPR ,  Some ( attrs. into ( ) ) ) ?; 
117-         Ok ( Some ( self . mk_stmt ( lo. to ( e. span ) ,  StmtKind :: Expr ( e) ) ) ) 
104+         let  expr = if  self . check ( & token:: OpenDelim ( token:: Brace ) )  { 
105+             self . parse_struct_expr ( lo,  path,  AttrVec :: new ( ) ) ?
106+         }  else  { 
107+             let  hi = self . prev_span ; 
108+             self . mk_expr ( lo. to ( hi) ,  ExprKind :: Path ( None ,  path) ,  AttrVec :: new ( ) ) 
109+         } ; 
110+ 
111+         let  expr = self . with_res ( Restrictions :: STMT_EXPR ,  |this| { 
112+             let  expr = this. parse_dot_or_call_expr_with ( expr,  lo,  attrs. into ( ) ) ?; 
113+             this. parse_assoc_expr_with ( 0 ,  LhsExpr :: AlreadyParsed ( expr) ) 
114+         } ) ?; 
115+         Ok ( self . mk_stmt ( lo. to ( self . prev_span ) ,  StmtKind :: Expr ( expr) ) ) 
118116    } 
119117
120118    /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`. 
121119     /// At this point, the `!` token after the path has already been eaten. 
122-      fn  parse_stmt_mac ( 
123-         & mut  self , 
124-         lo :  Span , 
125-         attrs :  AttrVec , 
126-         path :  ast:: Path , 
127-     )  -> PResult < ' a ,  Option < Stmt > >  { 
120+      fn  parse_stmt_mac ( & mut  self ,  lo :  Span ,  attrs :  AttrVec ,  path :  ast:: Path )  -> PResult < ' a ,  Stmt >  { 
128121        let  args = self . parse_mac_args ( ) ?; 
129122        let  delim = args. delim ( ) ; 
130123        let  hi = self . prev_span ; 
@@ -145,7 +138,7 @@ impl<'a> Parser<'a> {
145138            let  e = self . parse_assoc_expr_with ( 0 ,  LhsExpr :: AlreadyParsed ( e) ) ?; 
146139            StmtKind :: Expr ( e) 
147140        } ; 
148-         Ok ( Some ( self . mk_stmt ( lo. to ( hi) ,  kind) ) ) 
141+         Ok ( self . mk_stmt ( lo. to ( hi) ,  kind) ) 
149142    } 
150143
151144    /// Error on outer attributes in this context. 
@@ -167,12 +160,12 @@ impl<'a> Parser<'a> {
167160        attrs :  AttrVec , 
168161        msg :  & str , 
169162        sugg :  & str , 
170-     )  -> PResult < ' a ,  Option < Stmt > >  { 
163+     )  -> PResult < ' a ,  Stmt >  { 
171164        let  stmt = self . parse_local_mk ( lo,  attrs) ?; 
172165        self . struct_span_err ( lo,  "invalid variable declaration" ) 
173166            . span_suggestion ( lo,  msg,  sugg. to_string ( ) ,  Applicability :: MachineApplicable ) 
174167            . emit ( ) ; 
175-         Ok ( Some ( stmt) ) 
168+         Ok ( stmt) 
176169    } 
177170
178171    fn  parse_local_mk ( & mut  self ,  lo :  Span ,  attrs :  AttrVec )  -> PResult < ' a ,  Stmt >  { 
@@ -372,36 +365,36 @@ impl<'a> Parser<'a> {
372365
373366        let  mut  eat_semi = true ; 
374367        match  stmt. kind  { 
375-             StmtKind :: Expr ( ref  expr )   if   self . token  != token :: Eof  =>  { 
376-                  // expression without semicolon 
377-                 if  classify:: expr_requires_semi_to_be_stmt ( expr)  { 
378-                      // Just check for errors and recover; do not eat semicolon yet. 
379-                      if   let   Err ( mut  e )  = 
380-                          self . expect_one_of ( & [ ] ,   & [ token :: Semi ,  token :: CloseDelim ( token :: Brace ) ] ) 
381-                     { 
382-                          if   let   TokenKind :: DocComment ( .. )  =  self . token . kind   { 
383-                              if  let  Ok ( snippet )  = self . span_to_snippet ( self . token . span )  { 
384-                                  let  sp  = self . token . span ; 
385-                                  let  marker  = & snippet [ .. 3 ] ; 
386-                                  let  ( comment_marker ,  doc_comment_marker )  = marker . split_at ( 2 ) ; 
387- 
388-                                 e . span_suggestion ( 
389-                                     sp . with_hi ( sp . lo ( )  +  BytePos ( marker . len ( )   as   u32 ) ) , 
390-                                      & format ! ( 
391-                                          "add a space before `{}` to use a regular comment" , 
392-                                         doc_comment_marker , 
393-                                     ) , 
394-                                      format ! ( "{} {}" ,  comment_marker ,  doc_comment_marker ) , 
395-                                      Applicability :: MaybeIncorrect , 
396-                                 ) ; 
397-                             } 
368+             // Expression without semicolon. 
369+             StmtKind :: Expr ( ref  expr ) 
370+                 if  self . token  != token :: Eof  &&  classify:: expr_requires_semi_to_be_stmt ( expr)  => 
371+             { 
372+                 // Just check for errors and recover; do not eat semicolon yet. 
373+                 if   let   Err ( mut  e )  = 
374+                     self . expect_one_of ( & [ ] ,   & [ token :: Semi ,  token :: CloseDelim ( token :: Brace ) ] ) 
375+                 { 
376+                     if  let  TokenKind :: DocComment ( .. )  = self . token . kind  { 
377+                         if   let  Ok ( snippet )  = self . span_to_snippet ( self . token . span )   { 
378+                             let  sp  = self . token . span ; 
379+                             let  marker =  & snippet [ .. 3 ] ; 
380+                              let   ( comment_marker ,  doc_comment_marker )  = marker . split_at ( 2 ) ; 
381+ 
382+                             e . span_suggestion ( 
383+                                 sp . with_hi ( sp . lo ( )  +  BytePos ( marker . len ( )   as   u32 ) ) , 
384+                                 & format ! ( 
385+                                     "add a space before `{}` to use a regular comment" , 
386+                                     doc_comment_marker , 
387+                                 ) , 
388+                                 format ! ( "{} {}" ,  comment_marker ,  doc_comment_marker ) , 
389+                                 Applicability :: MaybeIncorrect , 
390+                             ) ; 
398391                        } 
399-                         e. emit ( ) ; 
400-                         self . recover_stmt ( ) ; 
401-                         // Don't complain about type errors in body tail after parse error (#57383). 
402-                         let  sp = expr. span . to ( self . prev_span ) ; 
403-                         stmt. kind  = StmtKind :: Expr ( self . mk_expr_err ( sp) ) ; 
404392                    } 
393+                     e. emit ( ) ; 
394+                     self . recover_stmt ( ) ; 
395+                     // Don't complain about type errors in body tail after parse error (#57383). 
396+                     let  sp = expr. span . to ( self . prev_span ) ; 
397+                     stmt. kind  = StmtKind :: Expr ( self . mk_expr_err ( sp) ) ; 
405398                } 
406399            } 
407400            StmtKind :: Local ( ..)  => { 
0 commit comments