From d3f2879241b90a12182d1d78a04fc91088c584e0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 9 Jan 2025 17:09:48 -0800 Subject: [PATCH 1/3] Add regression test for chained comparisons with bailout thread 'test_fixup' panicked at tests/test_expr.rs:843:25: failed to parse `x > .. > x`: comparison operators cannot be chained note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace --- tests/test_expr.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_expr.rs b/tests/test_expr.rs index cfbf16236..226c044db 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -799,6 +799,7 @@ fn test_fixup() { quote! { (1 + 1).abs() }, quote! { (lo..hi)[..] }, quote! { (a..b)..(c..d) }, + quote! { (x > ..) > x }, quote! { (&mut fut).await }, quote! { &mut (x as i32) }, quote! { -(x as i32) }, From fd198d9b0c9cd850666618156758f78df45d73e0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 9 Jan 2025 17:07:49 -0800 Subject: [PATCH 2/3] Generalize Expr::Range bailout to any operator that can begin expr --- src/fixup.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/fixup.rs b/src/fixup.rs index 9414d8384..2576ec365 100644 --- a/src/fixup.rs +++ b/src/fixup.rs @@ -639,10 +639,13 @@ fn scan_right( Scan::Fail } } - None => match fixup.next_operator { - Precedence::Range => Scan::Consume, - _ => Scan::Fail, - }, + None => { + if fixup.next_operator_can_begin_expr { + Scan::Consume + } else { + Scan::Fail + } + } }, Expr::Break(e) => match &e.expr { Some(value) => { From 49443622bd2ff2986554ca58d7ee13436d784c22 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 9 Jan 2025 17:11:12 -0800 Subject: [PATCH 3/3] Fix parenthesization of chained comparisons containing bailout --- src/fixup.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fixup.rs b/src/fixup.rs index 2576ec365..e49f81131 100644 --- a/src/fixup.rs +++ b/src/fixup.rs @@ -547,6 +547,9 @@ fn scan_right( return Scan::Consume; } let binop_prec = Precedence::of_binop(&e.op); + if binop_prec == Precedence::Compare && fixup.next_operator == Precedence::Compare { + return Scan::Consume; + } let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec); let scan = scan_right( &e.right,