@@ -3789,13 +3789,8 @@ impl<'a> Parser<'a> {
3789
3789
3790
3790
/// Parse a statement. This stops just before trailing semicolons on everything but items.
3791
3791
/// e.g. a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
3792
- ///
3793
- /// Also, if a macro begins an expression statement, this only parses the macro. For example,
3794
- /// ```rust
3795
- /// vec![1].into_iter(); //< `parse_stmt` only parses the "vec![1]"
3796
- /// ```
3797
3792
pub fn parse_stmt ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3798
- Ok ( self . parse_stmt_ ( ) )
3793
+ Ok ( self . parse_stmt_ ( true ) )
3799
3794
}
3800
3795
3801
3796
// Eat tokens until we can be relatively sure we reached the end of the
@@ -3859,15 +3854,15 @@ impl<'a> Parser<'a> {
3859
3854
}
3860
3855
}
3861
3856
3862
- fn parse_stmt_ ( & mut self ) -> Option < Stmt > {
3863
- self . parse_stmt_without_recovery ( ) . unwrap_or_else ( |mut e| {
3857
+ fn parse_stmt_ ( & mut self , macro_expanded : bool ) -> Option < Stmt > {
3858
+ self . parse_stmt_without_recovery ( macro_expanded ) . unwrap_or_else ( |mut e| {
3864
3859
e. emit ( ) ;
3865
3860
self . recover_stmt_ ( SemiColonMode :: Break ) ;
3866
3861
None
3867
3862
} )
3868
3863
}
3869
3864
3870
- fn parse_stmt_without_recovery ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3865
+ fn parse_stmt_without_recovery ( & mut self , macro_expanded : bool ) -> PResult < ' a , Option < Stmt > > {
3871
3866
maybe_whole ! ( Some deref self , NtStmt ) ;
3872
3867
3873
3868
let attrs = self . parse_outer_attributes ( ) ?;
@@ -3930,10 +3925,34 @@ impl<'a> Parser<'a> {
3930
3925
3931
3926
if id. name == keywords:: Invalid . name ( ) {
3932
3927
let mac = spanned ( lo, hi, Mac_ { path : pth, tts : tts } ) ;
3928
+ let node = if delim == token:: Brace ||
3929
+ self . token == token:: Semi || self . token == token:: Eof {
3930
+ StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) )
3931
+ }
3932
+ // We used to incorrectly stop parsing macro-expanded statements here.
3933
+ // If the next token will be an error anyway but could have parsed with the
3934
+ // earlier behavior, stop parsing here and emit a warning to avoid breakage.
3935
+ else if macro_expanded && self . token . can_begin_expr ( ) && match self . token {
3936
+ // These can continue an expression, so we can't stop parsing and warn.
3937
+ token:: OpenDelim ( token:: Paren ) | token:: OpenDelim ( token:: Bracket ) |
3938
+ token:: BinOp ( token:: Minus ) | token:: BinOp ( token:: Star ) |
3939
+ token:: BinOp ( token:: And ) | token:: BinOp ( token:: Or ) |
3940
+ token:: AndAnd | token:: OrOr |
3941
+ token:: DotDot | token:: DotDotDot => false ,
3942
+ _ => true ,
3943
+ } {
3944
+ self . warn_missing_semicolon ( ) ;
3945
+ StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) )
3946
+ } else {
3947
+ let e = self . mk_mac_expr ( lo, hi, mac. node , ThinVec :: new ( ) ) ;
3948
+ let e = self . parse_dot_or_call_expr_with ( e, lo, attrs. into ( ) ) ?;
3949
+ let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
3950
+ StmtKind :: Expr ( e)
3951
+ } ;
3933
3952
Stmt {
3934
3953
id : ast:: DUMMY_NODE_ID ,
3935
- node : StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) ) ,
3936
3954
span : mk_sp ( lo, hi) ,
3955
+ node : node,
3937
3956
}
3938
3957
} else {
3939
3958
// if it has a special ident, it's definitely an item
@@ -4061,49 +4080,12 @@ impl<'a> Parser<'a> {
4061
4080
}
4062
4081
4063
4082
/// Parse a statement, including the trailing semicolon.
4064
- /// This parses expression statements that begin with macros correctly (c.f. `parse_stmt`).
4065
4083
pub fn parse_full_stmt ( & mut self , macro_expanded : bool ) -> PResult < ' a , Option < Stmt > > {
4066
- let mut stmt = match self . parse_stmt_ ( ) {
4084
+ let mut stmt = match self . parse_stmt_ ( macro_expanded ) {
4067
4085
Some ( stmt) => stmt,
4068
4086
None => return Ok ( None ) ,
4069
4087
} ;
4070
4088
4071
- if let StmtKind :: Mac ( mac) = stmt. node {
4072
- if mac. 1 != MacStmtStyle :: NoBraces ||
4073
- self . token == token:: Semi || self . token == token:: Eof {
4074
- stmt. node = StmtKind :: Mac ( mac) ;
4075
- } else {
4076
- // We used to incorrectly stop parsing macro-expanded statements here.
4077
- // If the next token will be an error anyway but could have parsed with the
4078
- // earlier behavior, stop parsing here and emit a warning to avoid breakage.
4079
- if macro_expanded && self . token . can_begin_expr ( ) && match self . token {
4080
- // These tokens can continue an expression, so we can't stop parsing and warn.
4081
- token:: OpenDelim ( token:: Paren ) | token:: OpenDelim ( token:: Bracket ) |
4082
- token:: BinOp ( token:: Minus ) | token:: BinOp ( token:: Star ) |
4083
- token:: BinOp ( token:: And ) | token:: BinOp ( token:: Or ) |
4084
- token:: AndAnd | token:: OrOr |
4085
- token:: DotDot | token:: DotDotDot => false ,
4086
- _ => true ,
4087
- } {
4088
- self . warn_missing_semicolon ( ) ;
4089
- stmt. node = StmtKind :: Mac ( mac) ;
4090
- return Ok ( Some ( stmt) ) ;
4091
- }
4092
-
4093
- let ( mac, _style, attrs) = mac. unwrap ( ) ;
4094
- let e = self . mk_mac_expr ( stmt. span . lo , stmt. span . hi , mac. node , ThinVec :: new ( ) ) ;
4095
- let e = self . parse_dot_or_call_expr_with ( e, stmt. span . lo , attrs) ?;
4096
- let e = self . parse_assoc_expr_with ( 0 , LhsExpr :: AlreadyParsed ( e) ) ?;
4097
- stmt. node = StmtKind :: Expr ( e) ;
4098
- }
4099
- }
4100
-
4101
- stmt = self . handle_trailing_semicolon ( stmt, macro_expanded) ?;
4102
- Ok ( Some ( stmt) )
4103
- }
4104
-
4105
- fn handle_trailing_semicolon ( & mut self , mut stmt : Stmt , macro_expanded : bool )
4106
- -> PResult < ' a , Stmt > {
4107
4089
match stmt. node {
4108
4090
StmtKind :: Expr ( ref expr) if self . token != token:: Eof => {
4109
4091
// expression without semicolon
@@ -4133,7 +4115,7 @@ impl<'a> Parser<'a> {
4133
4115
}
4134
4116
4135
4117
stmt. span . hi = self . last_span . hi ;
4136
- Ok ( stmt)
4118
+ Ok ( Some ( stmt) )
4137
4119
}
4138
4120
4139
4121
fn warn_missing_semicolon ( & self ) {
0 commit comments