@@ -186,6 +186,7 @@ enum PrevTokenKind {
186
186
Interpolated ,
187
187
Eof ,
188
188
Ident ,
189
+ BitOr ,
189
190
Other ,
190
191
}
191
192
@@ -1375,6 +1376,7 @@ impl<'a> Parser<'a> {
1375
1376
token:: DocComment ( ..) => PrevTokenKind :: DocComment ,
1376
1377
token:: Comma => PrevTokenKind :: Comma ,
1377
1378
token:: BinOp ( token:: Plus ) => PrevTokenKind :: Plus ,
1379
+ token:: BinOp ( token:: Or ) => PrevTokenKind :: BitOr ,
1378
1380
token:: Interpolated ( ..) => PrevTokenKind :: Interpolated ,
1379
1381
token:: Eof => PrevTokenKind :: Eof ,
1380
1382
token:: Ident ( ..) => PrevTokenKind :: Ident ,
@@ -2806,6 +2808,12 @@ impl<'a> Parser<'a> {
2806
2808
let msg = format ! ( "expected expression, found {}" ,
2807
2809
self . this_token_descr( ) ) ;
2808
2810
let mut err = self . fatal ( & msg) ;
2811
+ let sp = self . sess . source_map ( ) . start_point ( self . span ) ;
2812
+ if let Some ( sp) = self . sess . ambiguous_block_expr_parse . borrow ( )
2813
+ . get ( & sp)
2814
+ {
2815
+ self . sess . expr_parentheses_needed ( & mut err, * sp, None ) ;
2816
+ }
2809
2817
err. span_label ( self . span , "expected expression" ) ;
2810
2818
return Err ( err) ;
2811
2819
}
@@ -2845,7 +2853,7 @@ impl<'a> Parser<'a> {
2845
2853
"struct literals are not allowed here" ,
2846
2854
) ;
2847
2855
err. multipart_suggestion (
2848
- "surround the struct literal with parenthesis " ,
2856
+ "surround the struct literal with parentheses " ,
2849
2857
vec ! [
2850
2858
( lo. shrink_to_lo( ) , "(" . to_string( ) ) ,
2851
2859
( expr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
@@ -3506,9 +3514,42 @@ impl<'a> Parser<'a> {
3506
3514
}
3507
3515
} ;
3508
3516
3509
- if self . expr_is_complete ( & lhs) {
3510
- // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
3511
- return Ok ( lhs) ;
3517
+ match ( self . expr_is_complete ( & lhs) , AssocOp :: from_token ( & self . token ) ) {
3518
+ ( true , None ) => {
3519
+ // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071
3520
+ return Ok ( lhs) ;
3521
+ }
3522
+ ( false , _) => { } // continue parsing the expression
3523
+ // An exhaustive check is done in the following block, but these are checked first
3524
+ // because they *are* ambiguous but also reasonable looking incorrect syntax, so we
3525
+ // want to keep their span info to improve diagnostics in these cases in a later stage.
3526
+ ( true , Some ( AssocOp :: Multiply ) ) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
3527
+ ( true , Some ( AssocOp :: Subtract ) ) | // `{ 42 } -5`
3528
+ ( true , Some ( AssocOp :: Add ) ) => { // `{ 42 } + 42
3529
+ // These cases are ambiguous and can't be identified in the parser alone
3530
+ let sp = self . sess . source_map ( ) . start_point ( self . span ) ;
3531
+ self . sess . ambiguous_block_expr_parse . borrow_mut ( ) . insert ( sp, lhs. span ) ;
3532
+ return Ok ( lhs) ;
3533
+ }
3534
+ ( true , Some ( ref op) ) if !op. can_continue_expr_unambiguously ( ) => {
3535
+ return Ok ( lhs) ;
3536
+ }
3537
+ ( true , Some ( _) ) => {
3538
+ // We've found an expression that would be parsed as a statement, but the next
3539
+ // token implies this should be parsed as an expression.
3540
+ // For example: `if let Some(x) = x { x } else { 0 } / 2`
3541
+ let mut err = self . sess . span_diagnostic . struct_span_err ( self . span , & format ! (
3542
+ "expected expression, found `{}`" ,
3543
+ pprust:: token_to_string( & self . token) ,
3544
+ ) ) ;
3545
+ err. span_label ( self . span , "expected expression" ) ;
3546
+ self . sess . expr_parentheses_needed (
3547
+ & mut err,
3548
+ lhs. span ,
3549
+ Some ( pprust:: expr_to_string ( & lhs) ,
3550
+ ) ) ;
3551
+ err. emit ( ) ;
3552
+ }
3512
3553
}
3513
3554
self . expected_tokens . push ( TokenType :: Operator ) ;
3514
3555
while let Some ( op) = AssocOp :: from_token ( & self . token ) {
@@ -4819,6 +4860,10 @@ impl<'a> Parser<'a> {
4819
4860
) ;
4820
4861
let mut err = self . fatal ( & msg) ;
4821
4862
err. span_label ( self . span , format ! ( "expected {}" , expected) ) ;
4863
+ let sp = self . sess . source_map ( ) . start_point ( self . span ) ;
4864
+ if let Some ( sp) = self . sess . ambiguous_block_expr_parse . borrow ( ) . get ( & sp) {
4865
+ self . sess . expr_parentheses_needed ( & mut err, * sp, None ) ;
4866
+ }
4822
4867
return Err ( err) ;
4823
4868
}
4824
4869
}
0 commit comments