Skip to content

Commit

Permalink
Rollup merge of rust-lang#89974 - est31:let_else_if_error, r=nagisa
Browse files Browse the repository at this point in the history
Nicer error message if the user attempts to do let...else if

Gives a nice "conditional `else if` is not supported for `let...else`" error when encountering a `let...else if` pattern, as suggested in the [let...else tracking issue](rust-lang#87335 (comment)).
  • Loading branch information
matthiaskrgr authored Oct 17, 2021
2 parents ef27866 + 8565419 commit b4f4c3c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
21 changes: 16 additions & 5 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_ast::{
};
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt};
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
use rustc_errors::{Applicability, PResult};
use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym};

Expand Down Expand Up @@ -300,6 +300,12 @@ impl<'a> Parser<'a> {
None => LocalKind::Decl,
Some(init) => {
if self.eat_keyword(kw::Else) {
if self.token.is_keyword(kw::If) {
// `let...else if`. Emit the same error that `parse_block()` would,
// but explicitly point out that this pattern is not allowed.
let msg = "conditional `else if` is not supported for `let...else`";
return Err(self.error_block_no_opening_brace_msg(msg));
}
let els = self.parse_block()?;
self.check_let_else_init_bool_expr(&init);
self.check_let_else_init_trailing_brace(&init);
Expand Down Expand Up @@ -392,10 +398,9 @@ impl<'a> Parser<'a> {
Ok(block)
}

fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
fn error_block_no_opening_brace_msg(&mut self, msg: &str) -> DiagnosticBuilder<'a> {
let sp = self.token.span;
let tok = super::token_descr(&self.token);
let mut e = self.struct_span_err(sp, &format!("expected `{{`, found {}", tok));
let mut e = self.struct_span_err(sp, msg);
let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon;

// Check to see if the user has written something like
Expand Down Expand Up @@ -435,7 +440,13 @@ impl<'a> Parser<'a> {
_ => {}
}
e.span_label(sp, "expected `{`");
Err(e)
e
}

fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
let tok = super::token_descr(&self.token);
let msg = format!("expected `{{`, found {}", tok);
Err(self.error_block_no_opening_brace_msg(&msg))
}

/// Parses a block. Inner attributes are allowed.
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/let-else/let-else-if.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![feature(let_else)]

fn main() {
let Some(_) = Some(()) else if true {
//~^ ERROR conditional `else if` is not supported for `let...else`
return;
} else {
return;
};
}
18 changes: 18 additions & 0 deletions src/test/ui/let-else/let-else-if.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: conditional `else if` is not supported for `let...else`
--> $DIR/let-else-if.rs:4:33
|
LL | let Some(_) = Some(()) else if true {
| ^^ expected `{`
|
help: try placing this code inside a block
|
LL ~ let Some(_) = Some(()) else { if true {
LL +
LL + return;
LL + } else {
LL + return;
LL ~ } };
|

error: aborting due to previous error

0 comments on commit b4f4c3c

Please sign in to comment.