@@ -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