@@ -35,61 +35,32 @@ impl<'a> Parser<'a> {
35
35
let attrs = self . parse_outer_attributes ( ) ?;
36
36
let lo = self . token . span ;
37
37
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 ) {
45
43
self . bump ( ) ; // `auto`
46
44
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) {
50
47
self . bump ( ) ; // `var`
51
48
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 ( )
60
53
{
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.
93
64
self . error_outer_attrs ( & attrs) ;
94
65
self . bump ( ) ;
95
66
let mut last_semi = lo;
@@ -104,27 +75,49 @@ impl<'a> Parser<'a> {
104
75
ExprKind :: Tup ( Vec :: new ( ) ) ,
105
76
AttrVec :: new ( ) ,
106
77
) ) ;
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 {
111
84
self . error_outer_attrs ( & attrs) ;
112
85
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) ;
113
102
}
114
103
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) ) )
118
116
}
119
117
120
118
/// Parses a statement macro `mac!(args)` provided a `path` representing `mac`.
121
119
/// 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 > {
128
121
let args = self . parse_mac_args ( ) ?;
129
122
let delim = args. delim ( ) ;
130
123
let hi = self . prev_span ;
@@ -145,7 +138,7 @@ impl<'a> Parser<'a> {
145
138
let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
146
139
StmtKind :: Expr ( e)
147
140
} ;
148
- Ok ( Some ( self . mk_stmt ( lo. to ( hi) , kind) ) )
141
+ Ok ( self . mk_stmt ( lo. to ( hi) , kind) )
149
142
}
150
143
151
144
/// Error on outer attributes in this context.
@@ -167,12 +160,12 @@ impl<'a> Parser<'a> {
167
160
attrs : AttrVec ,
168
161
msg : & str ,
169
162
sugg : & str ,
170
- ) -> PResult < ' a , Option < Stmt > > {
163
+ ) -> PResult < ' a , Stmt > {
171
164
let stmt = self . parse_local_mk ( lo, attrs) ?;
172
165
self . struct_span_err ( lo, "invalid variable declaration" )
173
166
. span_suggestion ( lo, msg, sugg. to_string ( ) , Applicability :: MachineApplicable )
174
167
. emit ( ) ;
175
- Ok ( Some ( stmt) )
168
+ Ok ( stmt)
176
169
}
177
170
178
171
fn parse_local_mk ( & mut self , lo : Span , attrs : AttrVec ) -> PResult < ' a , Stmt > {
@@ -372,36 +365,36 @@ impl<'a> Parser<'a> {
372
365
373
366
let mut eat_semi = true ;
374
367
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
+ ) ;
398
391
}
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) ) ;
404
392
}
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) ) ;
405
398
}
406
399
}
407
400
StmtKind :: Local ( ..) => {
0 commit comments