@@ -3327,6 +3327,8 @@ impl<'a> Parser<'a> {
3327
3327
let pats = self . parse_pats ( ) ?;
3328
3328
self . expect ( & token:: Eq ) ?;
3329
3329
let expr = self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL , None ) ?;
3330
+ self . while_if_let_ambiguity ( & expr) ;
3331
+
3330
3332
let thn = self . parse_block ( ) ?;
3331
3333
let ( hi, els) = if self . eat_keyword ( keywords:: Else ) {
3332
3334
let expr = self . parse_else_expr ( ) ?;
@@ -3337,6 +3339,56 @@ impl<'a> Parser<'a> {
3337
3339
Ok ( self . mk_expr ( lo. to ( hi) , ExprKind :: IfLet ( pats, expr, thn, els) , attrs) )
3338
3340
}
3339
3341
3342
+ /// With eRFC 2497, we need to check whether an expression is ambigious and warn or error
3343
+ /// depending on the edition, this function handles that.
3344
+ fn while_if_let_ambiguity ( & self , expr : & P < Expr > ) {
3345
+ if let Some ( ( span, op_kind) ) = self . while_if_let_expr_ambiguity ( & expr) {
3346
+ let message = format ! ( "ambigious use of `{}`" , op_kind. to_string( ) ) ;
3347
+ let mut err = if self . span . edition ( ) >= Edition :: Edition2018 {
3348
+ self . diagnostic ( ) . struct_span_err ( span, & message)
3349
+ } else {
3350
+ self . diagnostic ( ) . struct_span_warn ( span, & message)
3351
+ } ;
3352
+
3353
+ let note = if self . span . edition ( ) >= Edition :: Edition2018 {
3354
+ "This will be a error until the `let_chains` feature is stabilized."
3355
+ } else {
3356
+ "This will be a error in Rust 2018 until the `let_chains` feature is stabilized."
3357
+ } ;
3358
+ err. note ( note) ;
3359
+
3360
+ if let Ok ( snippet) = self . sess . source_map ( ) . span_to_snippet ( span) {
3361
+ err. span_suggestion (
3362
+ span, "consider adding parenthesis" , format ! ( "({})" , snippet) ,
3363
+ ) ;
3364
+ }
3365
+
3366
+ err. emit ( ) ;
3367
+ }
3368
+ }
3369
+
3370
+ /// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of
3371
+ /// `&&` and `||` in a if-let statement be unambigious. This function returns a span and
3372
+ /// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined
3373
+ /// that the current expression parsed is ambigious and will break in future.
3374
+ fn while_if_let_expr_ambiguity ( & self , expr : & P < Expr > ) -> Option < ( Span , BinOpKind ) > {
3375
+ debug ! ( "while_if_let_expr_ambiguity: expr.node: {:?}" , expr. node) ;
3376
+ match & expr. node {
3377
+ ExprKind :: Binary ( op, _, _) if op. node == BinOpKind :: And || op. node == BinOpKind :: Or => {
3378
+ Some ( ( expr. span , op. node ) )
3379
+ } ,
3380
+ ExprKind :: Range ( ref lhs, ref rhs, _) => {
3381
+ let lhs_ambigious = lhs. as_ref ( )
3382
+ . and_then ( |lhs| self . while_if_let_expr_ambiguity ( lhs) ) ;
3383
+ let rhs_ambigious = rhs. as_ref ( )
3384
+ . and_then ( |rhs| self . while_if_let_expr_ambiguity ( rhs) ) ;
3385
+
3386
+ lhs_ambigious. or ( rhs_ambigious)
3387
+ }
3388
+ _ => None ,
3389
+ }
3390
+ }
3391
+
3340
3392
// `move |args| expr`
3341
3393
fn parse_lambda_expr ( & mut self ,
3342
3394
attrs : ThinVec < Attribute > )
@@ -3437,6 +3489,7 @@ impl<'a> Parser<'a> {
3437
3489
let pats = self . parse_pats ( ) ?;
3438
3490
self . expect ( & token:: Eq ) ?;
3439
3491
let expr = self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL , None ) ?;
3492
+ self . while_if_let_ambiguity ( & expr) ;
3440
3493
let ( iattrs, body) = self . parse_inner_attrs_and_block ( ) ?;
3441
3494
attrs. extend ( iattrs) ;
3442
3495
let span = span_lo. to ( body. span ) ;
0 commit comments