mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 23:34:48 +00:00
Rollup merge of #91435 - FabianWolff:issue-91421-if-then, r=lcnr
Improve diagnostic for missing half of binary operator in `if` condition Fixes #91421. I've also changed it so that it doesn't consume the `else` token in the error case, because it will try to consume it again afterwards, leading to this incorrect error message (where the `else` reported as missing is actually there): ``` error: expected one of `.`, `;`, `?`, `else`, or an operator, found `{` --> src/main.rs:4:12 | 4 | } else { 4 }; | ^ expected one of `.`, `;`, `?`, `else`, or an operator ``` r? `@lcnr`
This commit is contained in:
commit
dbb9e224af
@ -1988,25 +1988,34 @@ impl<'a> Parser<'a> {
|
||||
let lo = self.prev_token.span;
|
||||
let cond = self.parse_cond_expr()?;
|
||||
|
||||
let missing_then_block_binop_span = || {
|
||||
match cond.kind {
|
||||
ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right)
|
||||
if let ExprKind::Block(..) = right.kind => Some(binop_span),
|
||||
_ => None
|
||||
}
|
||||
};
|
||||
|
||||
// Verify that the parsed `if` condition makes sense as a condition. If it is a block, then
|
||||
// verify that the last statement is either an implicit return (no `;`) or an explicit
|
||||
// return. This won't catch blocks with an explicit `return`, but that would be caught by
|
||||
// the dead code lint.
|
||||
let thn = if self.eat_keyword(kw::Else) || !cond.returns() {
|
||||
self.error_missing_if_cond(lo, cond.span)
|
||||
let thn = if self.token.is_keyword(kw::Else) || !cond.returns() {
|
||||
if let Some(binop_span) = missing_then_block_binop_span() {
|
||||
self.error_missing_if_then_block(lo, None, Some(binop_span)).emit();
|
||||
self.mk_block_err(cond.span)
|
||||
} else {
|
||||
self.error_missing_if_cond(lo, cond.span)
|
||||
}
|
||||
} else {
|
||||
let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery.
|
||||
let not_block = self.token != token::OpenDelim(token::Brace);
|
||||
let block = self.parse_block().map_err(|mut err| {
|
||||
let block = self.parse_block().map_err(|err| {
|
||||
if not_block {
|
||||
err.span_label(lo, "this `if` expression has a condition, but no block");
|
||||
if let ExprKind::Binary(_, _, ref right) = cond.kind {
|
||||
if let ExprKind::Block(_, _) = right.kind {
|
||||
err.help("maybe you forgot the right operand of the condition?");
|
||||
}
|
||||
}
|
||||
self.error_missing_if_then_block(lo, Some(err), missing_then_block_binop_span())
|
||||
} else {
|
||||
err
|
||||
}
|
||||
err
|
||||
})?;
|
||||
self.error_on_if_block_attrs(lo, false, block.span, &attrs);
|
||||
block
|
||||
@ -2015,6 +2024,28 @@ impl<'a> Parser<'a> {
|
||||
Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs))
|
||||
}
|
||||
|
||||
fn error_missing_if_then_block(
|
||||
&self,
|
||||
if_span: Span,
|
||||
err: Option<DiagnosticBuilder<'a>>,
|
||||
binop_span: Option<Span>,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let msg = "this `if` expression has a condition, but no block";
|
||||
|
||||
let mut err = if let Some(mut err) = err {
|
||||
err.span_label(if_span, msg);
|
||||
err
|
||||
} else {
|
||||
self.struct_span_err(if_span, msg)
|
||||
};
|
||||
|
||||
if let Some(binop_span) = binop_span {
|
||||
err.span_help(binop_span, "maybe you forgot the right operand of the condition?");
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> {
|
||||
let sp = self.sess.source_map().next_point(lo);
|
||||
self.struct_span_err(sp, "missing condition for `if` expression")
|
||||
|
@ -7,7 +7,11 @@ LL | if 5 == {
|
||||
LL | }
|
||||
| ^ expected `{`
|
||||
|
|
||||
= help: maybe you forgot the right operand of the condition?
|
||||
help: maybe you forgot the right operand of the condition?
|
||||
--> $DIR/if-without-block.rs:3:10
|
||||
|
|
||||
LL | if 5 == {
|
||||
| ^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
10
src/test/ui/parser/issue-91421.rs
Normal file
10
src/test/ui/parser/issue-91421.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// Regression test for issue #91421.
|
||||
|
||||
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?
|
||||
3
|
||||
//~^ ERROR: mismatched types [E0308]
|
||||
} else { 4 };
|
||||
}
|
21
src/test/ui/parser/issue-91421.stderr
Normal file
21
src/test/ui/parser/issue-91421.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error: this `if` expression has a condition, but no block
|
||||
--> $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
|
||||
|
|
||||
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
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user