diff options
| author | bors <bors@rust-lang.org> | 2022-06-15 02:58:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-06-15 02:58:44 +0000 |
| commit | ddb6cc85243ac4761fbc32a407b10216544fe57b (patch) | |
| tree | 6c0ca223e784365531787dc5bd13a92795aeb7fb /src | |
| parent | 2d1e0750792529248ed6f11061940c7203d668c9 (diff) | |
| parent | d1ba2d25d483a65f41ca6277c160e2ea6d813e3b (diff) | |
| download | rust-ddb6cc85243ac4761fbc32a407b10216544fe57b.tar.gz rust-ddb6cc85243ac4761fbc32a407b10216544fe57b.zip | |
Auto merge of #97474 - compiler-errors:if-cond-and-block, r=oli-obk
Improve parsing errors and suggestions for bad `if` statements
1. Parses `if {}` as `if <err> {}` (block-like conditions that are missing a "then" block), and `if true && {}` as `if true && <err> {}` (unfinished binary operation), which is a more faithful recovery and leads to better typeck errors later on.
1. Points out the span of the condition if we don't see a "then" block after it, to help the user understand what is being parsed as a condition (and by elimination, what isn't).
1. Allow `if cond token else { }` to be fixed properly to `if cond { token } else { }`.
1. Fudge with the error messages a bit. This is somewhat arbitrary and I can revert my rewordings if they're useless.
----
Also this PR addresses a strange parsing regression (1.20 -> 1.21) where we chose to reject this piece of code somewhat arbitrarily, even though we should parse it fine:
```rust
fn main() {
if { if true { return } else { return }; } {}
}
```
For context, all of these other expressions parse correctly:
```rust
fn main() {
if { if true { return } else { return } } {}
if { return; } {}
if { return } {}
if { return if true { } else { }; } {}
}
```
The parser used a heuristic to determine if the "the parsed `if` condition makes sense as a condition" that did like a one-expr-deep reachability analysis. This should not be handled by the parser though.
Diffstat (limited to 'src')
19 files changed, 243 insertions, 100 deletions
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr index 609a5efd46f..3ccc14bba54 100644 --- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr +++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -25,10 +25,16 @@ LL | println!("Then when?"); error: expected `{`, found `;` --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31 | -LL | if not // lack of braces is [sic] - | -- this `if` expression has a condition, but no block LL | println!("Then when?"); | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:19:8 + | +LL | if not // lack of braces is [sic] + | ________^ +LL | | println!("Then when?"); + | |______________________________^ error: unexpected `2` after identifier --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 diff --git a/src/test/ui/expr/if/if-without-block.rs b/src/test/ui/expr/if/if-without-block.rs index 8a4c59f3261..5add9dfda4b 100644 --- a/src/test/ui/expr/if/if-without-block.rs +++ b/src/test/ui/expr/if/if-without-block.rs @@ -1,9 +1,7 @@ fn main() { let n = 1; if 5 == { - //~^ NOTE this `if` expression has a condition, but no block + //~^ ERROR this `if` expression is missing a block after the condition println!("five"); } } -//~^ ERROR expected `{`, found `}` -//~| NOTE expected `{` diff --git a/src/test/ui/expr/if/if-without-block.stderr b/src/test/ui/expr/if/if-without-block.stderr index d3f6ca07617..2d1ee04ce09 100644 --- a/src/test/ui/expr/if/if-without-block.stderr +++ b/src/test/ui/expr/if/if-without-block.stderr @@ -1,17 +1,14 @@ -error: expected `{`, found `}` - --> $DIR/if-without-block.rs:7:1 +error: this `if` expression is missing a block after the condition + --> $DIR/if-without-block.rs:3:5 | LL | if 5 == { - | -- this `if` expression has a condition, but no block -... -LL | } - | ^ expected `{` + | ^^ | -help: maybe you forgot the right operand of the condition? - --> $DIR/if-without-block.rs:3:10 +help: this binary operation is possibly unfinished + --> $DIR/if-without-block.rs:3:8 | LL | if 5 == { - | ^^ + | ^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr index feabe3814dc..387ef0776ff 100644 --- a/src/test/ui/issues/issue-39848.stderr +++ b/src/test/ui/issues/issue-39848.stderr @@ -2,13 +2,19 @@ error: expected `{`, found `foo` --> $DIR/issue-39848.rs:3:21 | LL | if $tgt.has_$field() {} - | -- ^^^^^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^^^^^ expected `{` ... LL | get_opt!(bar, foo); | ------------------ in this macro invocation | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-39848.rs:3:12 + | +LL | if $tgt.has_$field() {} + | ^^^^^^^^^ +... +LL | get_opt!(bar, foo); + | ------------------ in this macro invocation = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) help: try placing this code inside a block | diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr index 148e214e58e..16954223a45 100644 --- a/src/test/ui/missing/missing-block-hint.stderr +++ b/src/test/ui/missing/missing-block-hint.stderr @@ -2,18 +2,25 @@ error: expected `{`, found `=>` --> $DIR/missing-block-hint.rs:3:18 | LL | if (foo) => {} - | -- ^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/missing-block-hint.rs:3:12 + | +LL | if (foo) => {} + | ^^^^^ error: expected `{`, found `bar` --> $DIR/missing-block-hint.rs:7:13 | -LL | if (foo) - | -- this `if` expression has a condition, but no block LL | bar; | ^^^ expected `{` | +note: the `if` expression is missing a block after this condition + --> $DIR/missing-block-hint.rs:6:12 + | +LL | if (foo) + | ^^^^^ help: try placing this code inside a block | LL | { bar; } diff --git a/src/test/ui/parser/bad-if-statements.rs b/src/test/ui/parser/bad-if-statements.rs new file mode 100644 index 00000000000..2c501e3a5b3 --- /dev/null +++ b/src/test/ui/parser/bad-if-statements.rs @@ -0,0 +1,38 @@ +fn a() { + if {} + //~^ ERROR missing condition for `if` expression +} + +fn b() { + if true && {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn c() { + let x = {}; + if true x + //~^ ERROR expected `{`, found `x` +} + +fn a2() { + if {} else {} + //~^ ERROR missing condition for `if` expression +} + +fn b2() { + if true && {} else {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn c2() { + let x = {}; + if true x else {} + //~^ ERROR expected `{`, found `x` +} + +fn d() { + if true else {} + //~^ ERROR this `if` expression is missing a block after the condition +} + +fn main() {} diff --git a/src/test/ui/parser/bad-if-statements.stderr b/src/test/ui/parser/bad-if-statements.stderr new file mode 100644 index 00000000000..ee839db6455 --- /dev/null +++ b/src/test/ui/parser/bad-if-statements.stderr @@ -0,0 +1,86 @@ +error: missing condition for `if` expression + --> $DIR/bad-if-statements.rs:2:7 + | +LL | if {} + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:7:5 + | +LL | if true && {} + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/bad-if-statements.rs:7:8 + | +LL | if true && {} + | ^^^^^^^ + +error: expected `{`, found `x` + --> $DIR/bad-if-statements.rs:13:13 + | +LL | if true x + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/bad-if-statements.rs:13:8 + | +LL | if true x + | ^^^^ +help: try placing this code inside a block + | +LL | if true { x } + | + + + +error: missing condition for `if` expression + --> $DIR/bad-if-statements.rs:18:7 + | +LL | if {} else {} + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:23:5 + | +LL | if true && {} else {} + | ^^ + | +help: this binary operation is possibly unfinished + --> $DIR/bad-if-statements.rs:23:8 + | +LL | if true && {} else {} + | ^^^^^^^ + +error: expected `{`, found `x` + --> $DIR/bad-if-statements.rs:29:13 + | +LL | if true x else {} + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/bad-if-statements.rs:29:8 + | +LL | if true x else {} + | ^^^^ +help: try placing this code inside a block + | +LL | if true { x } else {} + | + + + +error: this `if` expression is missing a block after the condition + --> $DIR/bad-if-statements.rs:34:5 + | +LL | if true else {} + | ^^ + | +help: add a block here + --> $DIR/bad-if-statements.rs:34:12 + | +LL | if true else {} + | ^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/parser/if-block-unreachable-expr.rs b/src/test/ui/parser/if-block-unreachable-expr.rs new file mode 100644 index 00000000000..4063a337084 --- /dev/null +++ b/src/test/ui/parser/if-block-unreachable-expr.rs @@ -0,0 +1,8 @@ +// check-pass + +// This regressed from 1.20 -> 1.21 -- the condition is unreachable, +// but it's still an expression, and should parse fine. + +fn main() { + if { if true { return; } else { return; }; } {} +} diff --git a/src/test/ui/parser/issue-61858.stderr b/src/test/ui/parser/issue-61858.stderr index 8b95d9c6ae4..03f51c6e3a8 100644 --- a/src/test/ui/parser/issue-61858.stderr +++ b/src/test/ui/parser/issue-61858.stderr @@ -2,9 +2,13 @@ error: expected `{`, found `)` --> $DIR/issue-61858.rs:2:15 | LL | (if foobar) - | -- ^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-61858.rs:2:9 + | +LL | (if foobar) + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs b/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs index 00f90cc73b3..57d36feb37b 100644 --- a/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs +++ b/src/test/ui/parser/issue-68091-unicode-ident-after-if.rs @@ -1,7 +1,8 @@ macro_rules! x { ($($c:tt)*) => { - $($c)ö* {} //~ ERROR missing condition for `if` expression - }; //~| ERROR mismatched types + $($c)ö* {} + //~^ ERROR missing condition for `if` expression + }; } fn main() { diff --git a/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr b/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr index cdd4c670500..6674b924e9c 100644 --- a/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr +++ b/src/test/ui/parser/issue-68091-unicode-ident-after-if.stderr @@ -2,19 +2,9 @@ error: missing condition for `if` expression --> $DIR/issue-68091-unicode-ident-after-if.rs:3:14 | LL | $($c)ö* {} - | ^ expected if condition here + | ^ - if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here -error[E0308]: mismatched types - --> $DIR/issue-68091-unicode-ident-after-if.rs:3:17 - | -LL | $($c)ö* {} - | ^^ expected `bool`, found `()` -... -LL | x!(if); - | ------ in this macro invocation - | - = note: this error originates in the macro `x` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issue-91421.rs b/src/test/ui/parser/issue-91421.rs index 9959df56638..8bba27f3724 100644 --- a/src/test/ui/parser/issue-91421.rs +++ b/src/test/ui/parser/issue-91421.rs @@ -2,9 +2,8 @@ fn main() { let value = if true && { - //~^ ERROR: this `if` expression has a condition, but no block - //~| HELP: maybe you forgot the right operand of the condition? + //~^ ERROR: this `if` expression is missing a block after the condition + //~| HELP: this binary operation is possibly unfinished 3 - //~^ ERROR: mismatched types [E0308] } else { 4 }; } diff --git a/src/test/ui/parser/issue-91421.stderr b/src/test/ui/parser/issue-91421.stderr index 04284d5e3b2..2d9652051dd 100644 --- a/src/test/ui/parser/issue-91421.stderr +++ b/src/test/ui/parser/issue-91421.stderr @@ -1,21 +1,14 @@ -error: this `if` expression has a condition, but no block +error: this `if` expression is missing a block after the condition --> $DIR/issue-91421.rs:4:17 | LL | let value = if true && { | ^^ | -help: maybe you forgot the right operand of the condition? - --> $DIR/issue-91421.rs:4:25 +help: this binary operation is possibly unfinished + --> $DIR/issue-91421.rs:4:20 | LL | let value = if true && { - | ^^ + | ^^^^^^^ -error[E0308]: mismatched types - --> $DIR/issue-91421.rs:7:9 - | -LL | 3 - | ^ expected `bool`, found integer - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issues/issue-13483.rs b/src/test/ui/parser/issues/issue-13483.rs index a2fd9264b15..4e32fcab3f0 100644 --- a/src/test/ui/parser/issues/issue-13483.rs +++ b/src/test/ui/parser/issues/issue-13483.rs @@ -1,15 +1,15 @@ fn main() { if true { - } else if { //~ ERROR missing condition - //~^ ERROR mismatched types + } else if { + //~^ ERROR missing condition for `if` expression } else { } } fn foo() { if true { - } else if { //~ ERROR missing condition - //~^ ERROR mismatched types + } else if { + //~^ ERROR missing condition for `if` expression } bar(); } diff --git a/src/test/ui/parser/issues/issue-13483.stderr b/src/test/ui/parser/issues/issue-13483.stderr index 5fd05b18ce0..f5534090f18 100644 --- a/src/test/ui/parser/issues/issue-13483.stderr +++ b/src/test/ui/parser/issues/issue-13483.stderr @@ -2,32 +2,17 @@ error: missing condition for `if` expression --> $DIR/issue-13483.rs:3:14 | LL | } else if { - | ^ expected if condition here + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here error: missing condition for `if` expression --> $DIR/issue-13483.rs:11:14 | LL | } else if { - | ^ expected if condition here + | ^- if this block is the condition of the `if` expression, then it must be followed by another block + | | + | expected condition here -error[E0308]: mismatched types - --> $DIR/issue-13483.rs:3:15 - | -LL | } else if { - | _______________^ -LL | | -LL | | } else { - | |_____^ expected `bool`, found `()` - -error[E0308]: mismatched types - --> $DIR/issue-13483.rs:11:15 - | -LL | } else if { - | _______________^ -LL | | -LL | | } - | |_____^ expected `bool`, found `()` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issues/issue-51602.stderr b/src/test/ui/parser/issues/issue-51602.stderr index d800890bca3..4a5653fdb51 100644 --- a/src/test/ui/parser/issues/issue-51602.stderr +++ b/src/test/ui/parser/issues/issue-51602.stderr @@ -2,9 +2,13 @@ error: expected `{`, found keyword `in` --> $DIR/issue-51602.rs:2:10 | LL | if i in 1..10 { - | -- ^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^ expected `{` + | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-51602.rs:2:8 + | +LL | if i in 1..10 { + | ^ error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-62554.stderr b/src/test/ui/parser/issues/issue-62554.stderr index 3589016e1dc..9e62572e388 100644 --- a/src/test/ui/parser/issues/issue-62554.stderr +++ b/src/test/ui/parser/issues/issue-62554.stderr @@ -57,10 +57,13 @@ error: expected `{`, found `macro_rules` --> $DIR/issue-62554.rs:6:23 | LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { - | -- ^^^^^^^^^^^ expected `{` - | | - | this `if` expression has a condition, but no block + | ^^^^^^^^^^^ expected `{` | +note: the `if` expression is missing a block after this condition + --> $DIR/issue-62554.rs:6:20 + | +LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { + | ^^ help: try placing this code inside a block | LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { } diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs index e24649ea044..e66caa19ec9 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs @@ -21,15 +21,15 @@ fn main() { }; if let Some(n) = opt else { - //~^ ERROR missing condition for `if` expression + //~^ ERROR this `if` expression is missing a block after the condition return; }; if let Some(n) = opt && n == 1 else { - //~^ ERROR missing condition for `if` expression + //~^ ERROR this `if` expression is missing a block after the condition return; }; if let Some(n) = opt && let another = n else { - //~^ ERROR missing condition for `if` expression + //~^ ERROR this `if` expression is missing a block after the condition return; }; diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr index aebfc1a72b7..eea8ed0c963 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr @@ -20,23 +20,41 @@ help: wrap the expression in parentheses LL | let Some(n) = (opt && let another = n) else { | + + -error: missing condition for `if` expression - --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:7 +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:5 | LL | if let Some(n) = opt else { - | ^ expected if condition here + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:23:25 + | +LL | if let Some(n) = opt else { + | ^ -error: missing condition for `if` expression - --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:7 +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:5 | LL | if let Some(n) = opt && n == 1 else { - | ^ expected if condition here + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:27:35 + | +LL | if let Some(n) = opt && n == 1 else { + | ^ -error: missing condition for `if` expression - --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:7 +error: this `if` expression is missing a block after the condition + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:5 + | +LL | if let Some(n) = opt && let another = n else { + | ^^ + | +help: add a block here + --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:31:44 | LL | if let Some(n) = opt && let another = n else { - | ^ expected if condition here + | ^ error: expected `{`, found keyword `else` --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:37:33 |
