Skip to content

Commit 995aacf

Browse files
committed
show diagnostic for } token followed by else in let else statement
1 parent 31c12ec commit 995aacf

File tree

5 files changed

+101
-8
lines changed

5 files changed

+101
-8
lines changed

crates/parser/src/grammar/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub(super) fn meta(p: &mut Parser<'_>) {
4343
match p.current() {
4444
T![=] => {
4545
p.bump(T![=]);
46-
if !expressions::expr(p) {
46+
if expressions::expr(p).is_none() {
4747
p.error("expected expression");
4848
}
4949
}

crates/parser/src/grammar/expressions.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ pub(super) enum Semicolon {
1616

1717
const EXPR_FIRST: TokenSet = LHS_FIRST;
1818

19-
pub(super) fn expr(p: &mut Parser<'_>) -> bool {
19+
pub(super) fn expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
2020
let r = Restrictions { forbid_structs: false, prefer_stmt: false };
21-
expr_bp(p, None, r, 1).is_some()
21+
expr_bp(p, None, r, 1).map(|(m, _)| m)
2222
}
2323

2424
pub(super) fn expr_stmt(
@@ -120,16 +120,32 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
120120
// fn f() { let x: i32; }
121121
types::ascription(p);
122122
}
123+
124+
let mut is_block_like_expr_after_eq = false;
123125
if p.eat(T![=]) {
124126
// test let_stmt_init
125127
// fn f() { let x = 92; }
126-
expressions::expr(p);
128+
let expr = expressions::expr(p);
129+
130+
if let Some(expr) = expr {
131+
is_block_like_expr_after_eq = match expr.kind() {
132+
IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR => true,
133+
_ => false,
134+
};
135+
}
127136
}
128137

129138
if p.at(T![else]) {
139+
// test_err let_else_right_curly_brace
140+
// fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
141+
if is_block_like_expr_after_eq {
142+
p.error(
143+
"right curly brace `}` before `else` in a `let...else` statement not allowed",
144+
)
145+
}
146+
130147
// test let_else
131148
// fn f() { let Some(x) = opt else { return }; }
132-
133149
let m = p.start();
134150
p.bump(T![else]);
135151
block_expr(p);
@@ -578,7 +594,14 @@ fn arg_list(p: &mut Parser<'_>) {
578594
// fn main() {
579595
// foo(#[attr] 92)
580596
// }
581-
delimited(p, T!['('], T![')'], T![,], EXPR_FIRST.union(ATTRIBUTE_FIRST), expr);
597+
delimited(
598+
p,
599+
T!['('],
600+
T![')'],
601+
T![,],
602+
EXPR_FIRST.union(ATTRIBUTE_FIRST),
603+
|p: &mut Parser<'_>| expr(p).is_some(),
604+
);
582605
m.complete(p, ARG_LIST);
583606
}
584607

crates/parser/src/grammar/expressions/atom.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ fn tuple_expr(p: &mut Parser<'_>) -> CompletedMarker {
188188

189189
// test tuple_attrs
190190
// const A: (i64, i64) = (1, #[cfg(test)] 2);
191-
if !expr(p) {
191+
if expr(p).is_none() {
192192
break;
193193
}
194194

@@ -221,7 +221,7 @@ fn array_expr(p: &mut Parser<'_>) -> CompletedMarker {
221221

222222
// test array_attrs
223223
// const A: &[i64] = &[1, #[cfg(test)] 2];
224-
if !expr(p) {
224+
if expr(p).is_none() {
225225
break;
226226
}
227227

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "func"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE " "
15+
LET_STMT
16+
LET_KW "let"
17+
WHITESPACE " "
18+
TUPLE_STRUCT_PAT
19+
PATH
20+
PATH_SEGMENT
21+
NAME_REF
22+
IDENT "Some"
23+
L_PAREN "("
24+
WILDCARD_PAT
25+
UNDERSCORE "_"
26+
R_PAREN ")"
27+
WHITESPACE " "
28+
EQ "="
29+
WHITESPACE " "
30+
BLOCK_EXPR
31+
STMT_LIST
32+
L_CURLY "{"
33+
CALL_EXPR
34+
PATH_EXPR
35+
PATH
36+
PATH_SEGMENT
37+
NAME_REF
38+
IDENT "Some"
39+
ARG_LIST
40+
L_PAREN "("
41+
LITERAL
42+
INT_NUMBER "1"
43+
R_PAREN ")"
44+
R_CURLY "}"
45+
WHITESPACE " "
46+
LET_ELSE
47+
ELSE_KW "else"
48+
WHITESPACE " "
49+
BLOCK_EXPR
50+
STMT_LIST
51+
L_CURLY "{"
52+
WHITESPACE " "
53+
MACRO_EXPR
54+
MACRO_CALL
55+
PATH
56+
PATH_SEGMENT
57+
NAME_REF
58+
IDENT "panic"
59+
BANG "!"
60+
TOKEN_TREE
61+
L_PAREN "("
62+
STRING "\"h\""
63+
R_PAREN ")"
64+
WHITESPACE " "
65+
R_CURLY "}"
66+
SEMICOLON ";"
67+
R_CURLY "}"
68+
WHITESPACE "\n"
69+
error 35: right curly brace `}` before `else` in a `let...else` statement not allowed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn func() { let Some(_) = {Some(1)} else { panic!("h") };}

0 commit comments

Comments
 (0)