Bail out when encountering likely missing turbofish in parser

When encountering a likely intended turbofish without `::`, bubble
up the diagnostic instead of emitting it to allow the parser to recover
more gracefully and avoid uneccessary type errors that are likely to be
wrong.
This commit is contained in:
Esteban Küber 2019-09-05 13:15:42 -07:00
parent dfd43f0fdd
commit afcf9b262d
8 changed files with 12 additions and 116 deletions

View file

@ -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(

View file

@ -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 {

View file

@ -1,27 +1,16 @@
fn foo() {
(0..13).collect<Vec<i32>>();
//~^ 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<i32>::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<Vec<i32>();
//~^ 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() {}

View file

@ -8,7 +8,7 @@ LL | (0..13).collect<Vec<i32>>();
= 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<i32>::new();
| ^^^^^^^
@ -17,7 +17,7 @@ LL | Vec<i32>::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<Vec<i32>();
| ^^^^^^^^
@ -25,79 +25,5 @@ LL | (0..13).collect<Vec<i32>();
= 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<Vec<i32>();
| ^^^^^^
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
= help: or use `(...)` if you meant to specify fn arguments
error: aborting due to 3 previous errors
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-40396.rs:2:21
|
LL | (0..13).collect<Vec<i32>>();
| ^^^ did you mean `Vec { /* fields */ }`?
error[E0423]: expected value, found builtin type `i32`
--> $DIR/issue-40396.rs:2:25
|
LL | (0..13).collect<Vec<i32>>();
| ^^^ not a value
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-40396.rs:10:5
|
LL | Vec<i32>::new();
| ^^^ did you mean `Vec { /* fields */ }`?
error[E0423]: expected value, found builtin type `i32`
--> $DIR/issue-40396.rs:10:9
|
LL | Vec<i32>::new();
| ^^^ not a value
error[E0425]: cannot find function `new` in the crate root
--> $DIR/issue-40396.rs:10:15
|
LL | Vec<i32>::new();
| ^^^ not found in the crate root
error[E0423]: expected value, found struct `Vec`
--> $DIR/issue-40396.rs:18:21
|
LL | (0..13).collect<Vec<i32>();
| ^^^ did you mean `Vec { /* fields */ }`?
error[E0423]: expected value, found builtin type `i32`
--> $DIR/issue-40396.rs:18:25
|
LL | (0..13).collect<Vec<i32>();
| ^^^ 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<Vec<i32>>();
| ^^^^^^^ 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<Vec<i32>();
| ^^^^^^^ help: use parentheses to call the method: `collect()`
error[E0308]: mismatched types
--> $DIR/issue-40396.rs:18:29
|
LL | (0..13).collect<Vec<i32>();
| ^^ expected bool, found ()
|
= note: expected type `bool`
found type `()`
error: aborting due to 14 previous errors
Some errors have detailed explanations: E0308, E0423, E0425, E0615.
For more information about an error, try `rustc --explain E0308`.

View file

@ -11,8 +11,7 @@ fn main() {
//~| ERROR: mismatched types
f<X>();
//~^ 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 `(...)`
}

View file

@ -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>();
| -^- X
| |
| fn() {f::<_>}
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() {f::<_>}`
error: aborting due to 5 previous errors
error: aborting due to 6 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`.

View file

@ -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() {}

View file

@ -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