Skip to content

Commit dc4e598

Browse files
committed
fix: Improve error recovery for match arms
1 parent 232125b commit dc4e598

File tree

3 files changed

+165
-17
lines changed

3 files changed

+165
-17
lines changed

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

+41-17
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,18 @@ fn match_expr(p: &mut Parser<'_>) -> CompletedMarker {
490490
m.complete(p, MATCH_EXPR)
491491
}
492492

493+
// test_err match_arms_recovery
494+
// fn foo() {
495+
// match () {
496+
// _ => (),,
497+
// _ => ,
498+
// _ => (),
499+
// => (),
500+
// if true => (),
501+
// _ => (),
502+
// () if => (),
503+
// }
504+
// }
493505
pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
494506
assert!(p.at(T!['{']));
495507
let m = p.start();
@@ -511,6 +523,10 @@ pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
511523
error_block(p, "expected match arm");
512524
continue;
513525
}
526+
if p.at(T![,]) {
527+
p.err_and_bump("expected pattern");
528+
continue;
529+
}
514530
match_arm(p);
515531
}
516532
p.expect(T!['}']);
@@ -544,26 +560,30 @@ fn match_arm(p: &mut Parser<'_>) {
544560
// }
545561
attributes::outer_attrs(p);
546562

547-
patterns::pattern_top_r(p, TokenSet::EMPTY);
563+
patterns::pattern_top_r(p, TokenSet::new(&[T![=], T![if]]));
548564
if p.at(T![if]) {
549565
match_guard(p);
550566
}
551567
p.expect(T![=>]);
552-
let blocklike = match expr_stmt(p, None) {
553-
Some((_, blocklike)) => blocklike,
554-
None => BlockLike::NotBlock,
555-
};
556-
557-
// test match_arms_commas
558-
// fn foo() {
559-
// match () {
560-
// _ => (),
561-
// _ => {}
562-
// _ => ()
563-
// }
564-
// }
565-
if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
566-
p.error("expected `,`");
568+
if p.eat(T![,]) {
569+
p.error("expected expression");
570+
} else {
571+
let blocklike = match expr_stmt(p, None) {
572+
Some((_, blocklike)) => blocklike,
573+
None => BlockLike::NotBlock,
574+
};
575+
576+
// test match_arms_commas
577+
// fn foo() {
578+
// match () {
579+
// _ => (),
580+
// _ => {}
581+
// _ => ()
582+
// }
583+
// }
584+
if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
585+
p.error("expected `,`");
586+
}
567587
}
568588
m.complete(p, MATCH_ARM);
569589
}
@@ -579,7 +599,11 @@ fn match_guard(p: &mut Parser<'_>) -> CompletedMarker {
579599
assert!(p.at(T![if]));
580600
let m = p.start();
581601
p.bump(T![if]);
582-
expr(p);
602+
if p.at(T![=]) {
603+
p.error("expected expression");
604+
} else {
605+
expr(p);
606+
}
583607
m.complete(p, MATCH_GUARD)
584608
}
585609

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
SOURCE_FILE
2+
FN
3+
FN_KW "fn"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "foo"
7+
PARAM_LIST
8+
L_PAREN "("
9+
R_PAREN ")"
10+
WHITESPACE " "
11+
BLOCK_EXPR
12+
STMT_LIST
13+
L_CURLY "{"
14+
WHITESPACE "\n "
15+
MATCH_EXPR
16+
MATCH_KW "match"
17+
WHITESPACE " "
18+
TUPLE_EXPR
19+
L_PAREN "("
20+
R_PAREN ")"
21+
WHITESPACE " "
22+
MATCH_ARM_LIST
23+
L_CURLY "{"
24+
WHITESPACE "\n "
25+
MATCH_ARM
26+
WILDCARD_PAT
27+
UNDERSCORE "_"
28+
WHITESPACE " "
29+
FAT_ARROW "=>"
30+
WHITESPACE " "
31+
TUPLE_EXPR
32+
L_PAREN "("
33+
R_PAREN ")"
34+
COMMA ","
35+
ERROR
36+
COMMA ","
37+
WHITESPACE "\n "
38+
MATCH_ARM
39+
WILDCARD_PAT
40+
UNDERSCORE "_"
41+
WHITESPACE " "
42+
FAT_ARROW "=>"
43+
WHITESPACE " "
44+
COMMA ","
45+
WHITESPACE "\n "
46+
MATCH_ARM
47+
WILDCARD_PAT
48+
UNDERSCORE "_"
49+
WHITESPACE " "
50+
FAT_ARROW "=>"
51+
WHITESPACE " "
52+
TUPLE_EXPR
53+
L_PAREN "("
54+
R_PAREN ")"
55+
COMMA ","
56+
WHITESPACE "\n "
57+
MATCH_ARM
58+
FAT_ARROW "=>"
59+
WHITESPACE " "
60+
TUPLE_EXPR
61+
L_PAREN "("
62+
R_PAREN ")"
63+
COMMA ","
64+
WHITESPACE "\n "
65+
MATCH_ARM
66+
MATCH_GUARD
67+
IF_KW "if"
68+
WHITESPACE " "
69+
LITERAL
70+
TRUE_KW "true"
71+
WHITESPACE " "
72+
FAT_ARROW "=>"
73+
WHITESPACE " "
74+
TUPLE_EXPR
75+
L_PAREN "("
76+
R_PAREN ")"
77+
COMMA ","
78+
WHITESPACE "\n "
79+
MATCH_ARM
80+
WILDCARD_PAT
81+
UNDERSCORE "_"
82+
WHITESPACE " "
83+
FAT_ARROW "=>"
84+
WHITESPACE " "
85+
TUPLE_EXPR
86+
L_PAREN "("
87+
R_PAREN ")"
88+
COMMA ","
89+
WHITESPACE "\n "
90+
MATCH_ARM
91+
TUPLE_PAT
92+
L_PAREN "("
93+
R_PAREN ")"
94+
WHITESPACE " "
95+
MATCH_GUARD
96+
IF_KW "if"
97+
WHITESPACE " "
98+
FAT_ARROW "=>"
99+
WHITESPACE " "
100+
TUPLE_EXPR
101+
L_PAREN "("
102+
R_PAREN ")"
103+
COMMA ","
104+
WHITESPACE "\n "
105+
R_CURLY "}"
106+
WHITESPACE "\n"
107+
R_CURLY "}"
108+
WHITESPACE "\n"
109+
error 42: expected pattern
110+
error 58: expected expression
111+
error 85: expected pattern
112+
error 100: expected pattern
113+
error 145: expected expression
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn foo() {
2+
match () {
3+
_ => (),,
4+
_ => ,
5+
_ => (),
6+
=> (),
7+
if true => (),
8+
_ => (),
9+
() if => (),
10+
}
11+
}

0 commit comments

Comments
 (0)