diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index d4e661d1a38b7..d050d4f4ce705 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -544,7 +544,7 @@ impl<'a> Parser<'a> { /// Produce an error if comparison operators are chained (RFC #558). /// We only need to check lhs, not rhs, because all comparison ops /// have same precedence and are left-associative - crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) { + crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> { debug_assert!(outer_op.is_comparison(), "check_no_chained_comparison: {:?} is not comparison", outer_op); @@ -563,11 +563,14 @@ impl<'a> Parser<'a> { err.help( "use `::<...>` instead of `<...>` if you meant to specify type arguments"); err.help("or use `(...)` if you meant to specify fn arguments"); + // These cases cause too many knock-down errors, bail out (#61329). + return Err(err); } err.emit(); } _ => {} } + Ok(()) } crate fn maybe_report_ambiguous_plus( diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 59b936a7eb404..e8c8e199fd06b 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -231,7 +231,7 @@ impl<'a> Parser<'a> { self.bump(); if op.is_comparison() { - self.check_no_chained_comparison(&lhs, &op); + self.check_no_chained_comparison(&lhs, &op)?; } // Special cases: if op == AssocOp::As { diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index b4c154e5d95f7..596f515da2f7f 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -32,13 +32,15 @@ use syntax::print::pprust; use syntax::ptr::P; -fn parse_expr(ps: &ParseSess, src: &str) -> P { +fn parse_expr(ps: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); - let mut p = parse::new_parser_from_source_str(ps, - FileName::Custom(src_as_string.clone()), - src_as_string); - p.parse_expr().unwrap() + let mut p = parse::new_parser_from_source_str( + ps, + FileName::Custom(src_as_string.clone()), + src_as_string, + ); + p.parse_expr().map_err(|mut e| e.cancel()).ok() } @@ -209,22 +211,23 @@ fn run() { let printed = pprust::expr_to_string(&e); println!("printed: {}", printed); - let mut parsed = parse_expr(&ps, &printed); - - // We want to know if `parsed` is structurally identical to `e`, ignoring trivial - // differences like placement of `Paren`s or the exact ranges of node spans. - // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s - // everywhere we can, then pretty-print. This should give an unambiguous representation of - // each `Expr`, and it bypasses nearly all of the parenthesization logic, so we aren't - // relying on the correctness of the very thing we're testing. - RemoveParens.visit_expr(&mut e); - AddParens.visit_expr(&mut e); - let text1 = pprust::expr_to_string(&e); - RemoveParens.visit_expr(&mut parsed); - AddParens.visit_expr(&mut parsed); - let text2 = pprust::expr_to_string(&parsed); - assert!(text1 == text2, - "exprs are not equal:\n e = {:?}\n parsed = {:?}", - text1, text2); + // Ignore expressions with chained comparisons that fail to parse + if let Some(mut parsed) = parse_expr(&ps, &printed) { + // We want to know if `parsed` is structurally identical to `e`, ignoring trivial + // differences like placement of `Paren`s or the exact ranges of node spans. + // Unfortunately, there is no easy way to make this comparison. Instead, we add `Paren`s + // everywhere we can, then pretty-print. This should give an unambiguous representation + // of each `Expr`, and it bypasses nearly all of the parenthesization logic, so we + // aren't relying on the correctness of the very thing we're testing. + RemoveParens.visit_expr(&mut e); + AddParens.visit_expr(&mut e); + let text1 = pprust::expr_to_string(&e); + RemoveParens.visit_expr(&mut parsed); + AddParens.visit_expr(&mut parsed); + let text2 = pprust::expr_to_string(&parsed); + assert!(text1 == text2, + "exprs are not equal:\n e = {:?}\n parsed = {:?}", + text1, text2); + } }); } diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index 63eec50c2d29f..6902779f33d23 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -1,27 +1,16 @@ fn foo() { (0..13).collect>(); //~^ ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR attempted to take value of method `collect` } fn bar() { Vec::new(); //~^ ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR cannot find function `new` in the crate root } fn qux() { (0..13).collect(); //~^ ERROR chained comparison - //~| ERROR chained comparison - //~| ERROR expected value, found struct `Vec` - //~| ERROR expected value, found builtin type `i32` - //~| ERROR attempted to take value of method `collect` - //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index fe517ee34949d..7a08fda27e355 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -8,7 +8,7 @@ LL | (0..13).collect>(); = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:10:8 + --> $DIR/issue-40396.rs:7:8 | LL | Vec::new(); | ^^^^^^^ @@ -17,7 +17,7 @@ LL | Vec::new(); = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:18:20 + --> $DIR/issue-40396.rs:12:20 | LL | (0..13).collect(); | ^^^^^^^^ @@ -25,79 +25,5 @@ LL | (0..13).collect(); = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:18:24 - | -LL | (0..13).collect(); - | ^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:2:21 - | -LL | (0..13).collect>(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:2:25 - | -LL | (0..13).collect>(); - | ^^^ not a value - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:10:5 - | -LL | Vec::new(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:10:9 - | -LL | Vec::new(); - | ^^^ not a value - -error[E0425]: cannot find function `new` in the crate root - --> $DIR/issue-40396.rs:10:15 - | -LL | Vec::new(); - | ^^^ not found in the crate root - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-40396.rs:18:21 - | -LL | (0..13).collect(); - | ^^^ did you mean `Vec { /* fields */ }`? - -error[E0423]: expected value, found builtin type `i32` - --> $DIR/issue-40396.rs:18:25 - | -LL | (0..13).collect(); - | ^^^ not a value - -error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` - --> $DIR/issue-40396.rs:2:13 - | -LL | (0..13).collect>(); - | ^^^^^^^ help: use parentheses to call the method: `collect()` - -error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` - --> $DIR/issue-40396.rs:18:13 - | -LL | (0..13).collect(); - | ^^^^^^^ help: use parentheses to call the method: `collect()` - -error[E0308]: mismatched types - --> $DIR/issue-40396.rs:18:29 - | -LL | (0..13).collect(); - | ^^ expected bool, found () - | - = note: expected type `bool` - found type `()` - -error: aborting due to 14 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0423, E0425, E0615. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 525be5d20e27f..3dcc0c8f3d496 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -11,8 +11,7 @@ fn main() { //~| ERROR: mismatched types f(); - //~^ ERROR: chained comparison operators require parentheses - //~| ERROR: binary operation `<` cannot be applied to type `fn() {f::<_>}` + //~^ ERROR chained comparison operators require parentheses //~| HELP: use `::<...>` instead of `<...>` //~| HELP: or use `(...)` } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 76e548de045aa..e927f4c32484e 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -37,17 +37,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error[E0369]: binary operation `<` cannot be applied to type `fn() {f::<_>}` - --> $DIR/require-parens-for-chained-comparison.rs:13:6 - | -LL | f(); - | -^- X - | | - | fn() {f::<_>} - | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0369. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs index 5bbda4296ca7e..c8b0eb684f33d 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.rs +++ b/src/test/ui/parser/trait-object-lifetime-parens.rs @@ -9,7 +9,6 @@ fn check<'a>() { let _: Box<('a) + Trait>; //~^ ERROR expected type, found `'a` //~| ERROR expected `:`, found `)` - //~| ERROR chained comparison operators require parentheses } fn main() {} diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr index 7ffc26e9edead..319a308c0137c 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.stderr +++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr @@ -16,15 +16,6 @@ error: expected `:`, found `)` LL | let _: Box<('a) + Trait>; | ^ expected `:` -error: chained comparison operators require parentheses - --> $DIR/trait-object-lifetime-parens.rs:9:15 - | -LL | let _: Box<('a) + Trait>; - | ^^^^^^^^^^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - error: expected type, found `'a` --> $DIR/trait-object-lifetime-parens.rs:9:17 | @@ -33,5 +24,5 @@ LL | let _: Box<('a) + Trait>; | | | while parsing the type for `_` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors