@@ -44,8 +44,8 @@ impl<'a> Parser<'a> {
44
44
let lo = self . token . span ;
45
45
46
46
Ok ( Some ( if self . eat_keyword ( kw:: Let ) {
47
- let stmt = self . parse_local ( attrs. into ( ) ) ?;
48
- self . mk_stmt ( lo. to ( self . prev_span ) , StmtKind :: Local ( stmt ) )
47
+ let local = self . parse_local ( attrs. into ( ) ) ?;
48
+ self . mk_stmt ( lo. to ( self . prev_span ) , StmtKind :: Local ( local ) )
49
49
} else if let Some ( macro_def) = self . eat_macro_def (
50
50
& attrs,
51
51
& respan ( lo, VisibilityKind :: Inherited ) ,
@@ -56,79 +56,31 @@ impl<'a> Parser<'a> {
56
56
// such as a union items, item with `crate` visibility or auto trait items.
57
57
// Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
58
58
// like a path (1 token), but it fact not a path.
59
- // `union::b::c` - path, `union U { ... }` - not a path.
60
- // `crate::b::c` - path, `crate struct S;` - not a path.
61
59
} else if self . token . is_path_start ( )
62
60
&& !self . token . is_qpath_start ( )
63
- && !self . is_union_item ( )
64
- && !self . is_crate_vis ( )
61
+ && !self . is_union_item ( ) // `union::b::c` - path, `union U { ... }` - not a path.
62
+ && !self . is_crate_vis ( ) // `crate::b::c` - path, `crate struct S;` - not a path.
65
63
&& !self . is_auto_trait_item ( )
66
64
&& !self . is_async_fn ( )
67
65
{
68
66
let path = self . parse_path ( PathStyle :: Expr ) ?;
69
67
70
- if !self . eat ( & token:: Not ) {
71
- let expr = if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
72
- self . parse_struct_expr ( lo, path, ThinVec :: new ( ) ) ?
73
- } else {
74
- let hi = self . prev_span ;
75
- self . mk_expr ( lo. to ( hi) , ExprKind :: Path ( None , path) , ThinVec :: new ( ) )
76
- } ;
77
-
78
- let expr = self . with_res ( Restrictions :: STMT_EXPR , |this| {
79
- let expr = this. parse_dot_or_call_expr_with ( expr, lo, attrs. into ( ) ) ?;
80
- this. parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( expr) )
81
- } ) ?;
82
- return Ok ( Some ( self . mk_stmt ( lo. to ( self . prev_span ) , StmtKind :: Expr ( expr) ) ) ) ;
68
+ if self . eat ( & token:: Not ) {
69
+ return self . parse_stmt_mac ( lo, attrs. into ( ) , path, macro_legacy_warnings) ;
83
70
}
84
71
85
- let args = self . parse_mac_args ( ) ?;
86
- let delim = args. delim ( ) ;
87
- let hi = self . prev_span ;
88
-
89
- let style = if delim == token:: Brace {
90
- MacStmtStyle :: Braces
72
+ let expr = if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
73
+ self . parse_struct_expr ( lo, path, ThinVec :: new ( ) ) ?
91
74
} else {
92
- MacStmtStyle :: NoBraces
93
- } ;
94
-
95
- let mac = Mac {
96
- path,
97
- args,
98
- prior_type_ascription : self . last_type_ascription ,
75
+ let hi = self . prev_span ;
76
+ self . mk_expr ( lo. to ( hi) , ExprKind :: Path ( None , path) , ThinVec :: new ( ) )
99
77
} ;
100
78
101
- let kind = if delim == token:: Brace
102
- || self . token == token:: Semi
103
- || self . token == token:: Eof
104
- {
105
- StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) )
106
- }
107
- // We used to incorrectly stop parsing macro-expanded statements here.
108
- // If the next token will be an error anyway but could have parsed with the
109
- // earlier behavior, stop parsing here and emit a warning to avoid breakage.
110
- else if macro_legacy_warnings
111
- && self . token . can_begin_expr ( )
112
- && match self . token . kind {
113
- // These can continue an expression, so we can't stop parsing and warn.
114
- token:: OpenDelim ( token:: Paren ) | token:: OpenDelim ( token:: Bracket ) |
115
- token:: BinOp ( token:: Minus ) | token:: BinOp ( token:: Star ) |
116
- token:: BinOp ( token:: And ) | token:: BinOp ( token:: Or ) |
117
- token:: AndAnd | token:: OrOr |
118
- token:: DotDot | token:: DotDotDot | token:: DotDotEq => false ,
119
- _ => true ,
120
- }
121
- {
122
- self . warn_missing_semicolon ( ) ;
123
- StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) )
124
- } else {
125
- let e = self . mk_expr ( lo. to ( hi) , ExprKind :: Mac ( mac) , ThinVec :: new ( ) ) ;
126
- let e = self . maybe_recover_from_bad_qpath ( e, true ) ?;
127
- let e = self . parse_dot_or_call_expr_with ( e, lo, attrs. into ( ) ) ?;
128
- let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
129
- StmtKind :: Expr ( e)
130
- } ;
131
- self . mk_stmt ( lo. to ( hi) , kind)
79
+ let expr = self . with_res ( Restrictions :: STMT_EXPR , |this| {
80
+ let expr = this. parse_dot_or_call_expr_with ( expr, lo, attrs. into ( ) ) ?;
81
+ this. parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( expr) )
82
+ } ) ?;
83
+ return Ok ( Some ( self . mk_stmt ( lo. to ( self . prev_span ) , StmtKind :: Expr ( expr) ) ) ) ;
132
84
} else {
133
85
// FIXME: Bad copy of attrs
134
86
let old_directory_ownership =
@@ -184,6 +136,64 @@ impl<'a> Parser<'a> {
184
136
} ) )
185
137
}
186
138
139
+ /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`.
140
+ /// At this point, the `!` token after the path has already been eaten.
141
+ fn parse_stmt_mac (
142
+ & mut self ,
143
+ lo : Span ,
144
+ attrs : ThinVec < Attribute > ,
145
+ path : ast:: Path ,
146
+ legacy_warnings : bool ,
147
+ ) -> PResult < ' a , Option < Stmt > > {
148
+ let args = self . parse_mac_args ( ) ?;
149
+ let delim = args. delim ( ) ;
150
+ let hi = self . prev_span ;
151
+
152
+ let style = if delim == token:: Brace {
153
+ MacStmtStyle :: Braces
154
+ } else {
155
+ MacStmtStyle :: NoBraces
156
+ } ;
157
+
158
+ let mac = Mac {
159
+ path,
160
+ args,
161
+ prior_type_ascription : self . last_type_ascription ,
162
+ } ;
163
+
164
+ let kind = if delim == token:: Brace
165
+ || self . token == token:: Semi
166
+ || self . token == token:: Eof
167
+ {
168
+ StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) )
169
+ }
170
+ // We used to incorrectly stop parsing macro-expanded statements here.
171
+ // If the next token will be an error anyway but could have parsed with the
172
+ // earlier behavior, stop parsing here and emit a warning to avoid breakage.
173
+ else if legacy_warnings
174
+ && self . token . can_begin_expr ( )
175
+ && match self . token . kind {
176
+ // These can continue an expression, so we can't stop parsing and warn.
177
+ token:: OpenDelim ( token:: Paren ) | token:: OpenDelim ( token:: Bracket ) |
178
+ token:: BinOp ( token:: Minus ) | token:: BinOp ( token:: Star ) |
179
+ token:: BinOp ( token:: And ) | token:: BinOp ( token:: Or ) |
180
+ token:: AndAnd | token:: OrOr |
181
+ token:: DotDot | token:: DotDotDot | token:: DotDotEq => false ,
182
+ _ => true ,
183
+ }
184
+ {
185
+ self . warn_missing_semicolon ( ) ;
186
+ StmtKind :: Mac ( P ( ( mac, style, attrs) ) )
187
+ } else {
188
+ let e = self . mk_expr ( lo. to ( hi) , ExprKind :: Mac ( mac) , ThinVec :: new ( ) ) ;
189
+ let e = self . maybe_recover_from_bad_qpath ( e, true ) ?;
190
+ let e = self . parse_dot_or_call_expr_with ( e, lo, attrs) ?;
191
+ let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
192
+ StmtKind :: Expr ( e)
193
+ } ;
194
+ Ok ( Some ( self . mk_stmt ( lo. to ( hi) , kind) ) )
195
+ }
196
+
187
197
/// Parses a local variable declaration.
188
198
fn parse_local ( & mut self , attrs : ThinVec < Attribute > ) -> PResult < ' a , P < Local > > {
189
199
let lo = self . prev_span ;
0 commit comments