@@ -3789,13 +3789,8 @@ impl<'a> Parser<'a> {
37893789
37903790 /// Parse a statement. This stops just before trailing semicolons on everything but items.
37913791 /// 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- /// ```
37973792 pub fn parse_stmt ( & mut self ) -> PResult < ' a , Option < Stmt > > {
3798- Ok ( self . parse_stmt_ ( ) )
3793+ Ok ( self . parse_stmt_ ( true ) )
37993794 }
38003795
38013796 // Eat tokens until we can be relatively sure we reached the end of the
@@ -3859,15 +3854,15 @@ impl<'a> Parser<'a> {
38593854 }
38603855 }
38613856
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| {
38643859 e. emit ( ) ;
38653860 self . recover_stmt_ ( SemiColonMode :: Break ) ;
38663861 None
38673862 } )
38683863 }
38693864
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 > > {
38713866 maybe_whole ! ( Some deref self , NtStmt ) ;
38723867
38733868 let attrs = self . parse_outer_attributes ( ) ?;
@@ -3930,10 +3925,34 @@ impl<'a> Parser<'a> {
39303925
39313926 if id. name == keywords:: Invalid . name ( ) {
39323927 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+ } ;
39333952 Stmt {
39343953 id : ast:: DUMMY_NODE_ID ,
3935- node : StmtKind :: Mac ( P ( ( mac, style, attrs. into ( ) ) ) ) ,
39363954 span : mk_sp ( lo, hi) ,
3955+ node : node,
39373956 }
39383957 } else {
39393958 // if it has a special ident, it's definitely an item
@@ -4061,49 +4080,12 @@ impl<'a> Parser<'a> {
40614080 }
40624081
40634082 /// Parse a statement, including the trailing semicolon.
4064- /// This parses expression statements that begin with macros correctly (c.f. `parse_stmt`).
40654083 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 ) {
40674085 Some ( stmt) => stmt,
40684086 None => return Ok ( None ) ,
40694087 } ;
40704088
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 > {
41074089 match stmt. node {
41084090 StmtKind :: Expr ( ref expr) if self . token != token:: Eof => {
41094091 // expression without semicolon
@@ -4133,7 +4115,7 @@ impl<'a> Parser<'a> {
41334115 }
41344116
41354117 stmt. span . hi = self . last_span . hi ;
4136- Ok ( stmt)
4118+ Ok ( Some ( stmt) )
41374119 }
41384120
41394121 fn warn_missing_semicolon ( & self ) {
0 commit comments