Skip to content

Commit

Permalink
parser, checker: move more match validation from the parser into the …
Browse files Browse the repository at this point in the history
…checker, add error for match without branches (#21181)
  • Loading branch information
ttytm committed Apr 4, 2024
1 parent d133f64 commit ba577e4
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 48 deletions.
25 changes: 18 additions & 7 deletions vlib/v/checker/match.v
Original file line number Diff line number Diff line change
Expand Up @@ -535,17 +535,28 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
}
}
}
if node.branches.len == 0 {
c.error('`match` must have at least two branches including `else`, or an exhaustive set of branches',
node.pos)
return
}
mut else_branch := node.branches.last()
mut has_else := else_branch.is_else
if !has_else {
for i, branch in node.branches {
if branch.is_else && i != node.branches.len - 1 {
c.error('`else` must be the last branch of `match`', branch.pos)
else_branch = branch
has_else = true
mut has_else, mut has_non_else := else_branch.is_else, !else_branch.is_else
for branch in node.branches[..node.branches.len - 1] {
if branch.is_else {
if has_else {
c.error('`match` can have only one `else` branch', branch.pos)
}
c.error('`else` must be the last branch of `match`', branch.pos)
else_branch = branch
has_else = true
} else {
has_non_else = true
}
}
if !has_non_else {
c.error('`match` must have at least one non `else` branch', else_branch.pos)
}
if is_exhaustive {
if has_else && !c.pref.translated && !c.file.is_translated {
c.error('match expression is exhaustive, `else` is unnecessary', else_branch.pos)
Expand Down
33 changes: 33 additions & 0 deletions vlib/v/checker/tests/match_missing.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
vlib/v/checker/tests/match_missing.vv:1:1: error: `match` must have at least two branches including `else`, or an exhaustive set of branches
1 | match true {
| ~~~~~
2 | }
3 |
vlib/v/checker/tests/match_missing.vv:5:2: error: `match` can have only one `else` branch
3 |
4 | match true {
5 | else {}
| ~~~~
6 | else {}
7 | }
vlib/v/checker/tests/match_missing.vv:5:2: error: `else` must be the last branch of `match`
3 |
4 | match true {
5 | else {}
| ~~~~
6 | else {}
7 | }
vlib/v/checker/tests/match_missing.vv:5:2: error: `match` must have at least one non `else` branch
3 |
4 | match true {
5 | else {}
| ~~~~
6 | else {}
7 | }
vlib/v/checker/tests/match_missing.vv:9:1: error: match must be exhaustive (add match branches for: `true`, `false` or `else {}` at the end)
7 | }
8 |
9 | match true {
| ~~~~~~~~~~~~
10 | 'foo' == 'bar' {}
11 | }
11 changes: 11 additions & 0 deletions vlib/v/checker/tests/match_missing.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
match true {
}

match true {
else {}
else {}
}

match true {
'foo' == 'bar' {}
}
7 changes: 0 additions & 7 deletions vlib/v/checker/tests/return_missing_match_simple.out

This file was deleted.

12 changes: 0 additions & 12 deletions vlib/v/checker/tests/return_missing_match_simple.vv

This file was deleted.

14 changes: 6 additions & 8 deletions vlib/v/parser/if_match.v
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ fn (mut p Parser) is_match_sumtype_type() bool {

fn (mut p Parser) match_expr() ast.MatchExpr {
match_first_pos := p.tok.pos()
mut else_count := 0
p.inside_match = true
p.check(.key_match)
mut is_sum_type := false
Expand All @@ -258,7 +257,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
mut is_else := false
if p.tok.kind == .key_else {
is_else = true
else_count += 1
p.next()
} else if p.is_match_sumtype_type() || p.is_only_array_type()
|| p.tok.kind == .key_fn
Expand Down Expand Up @@ -289,6 +287,12 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
}
is_sum_type = true
} else {
if p.tok.kind == .rcbr {
p.next()
return ast.MatchExpr{
pos: match_first_pos
}
}
// Expression match
for {
p.inside_match_case = true
Expand Down Expand Up @@ -351,12 +355,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
post_comments: post_comments
scope: branch_scope
}
if is_else && branches.len == 1 {
p.error_with_pos('`match` must have at least one non `else` branch', pos)
}
if else_count > 1 {
p.error_with_pos('`match` can have only one `else` branch', pos)
}
if p.tok.kind == .rcbr || (is_else && no_lcbr) {
break
}
Expand Down
7 changes: 0 additions & 7 deletions vlib/v/parser/tests/match_multi_else_branch_err.out

This file was deleted.

7 changes: 0 additions & 7 deletions vlib/v/parser/tests/match_multi_else_branch_err.vv

This file was deleted.

0 comments on commit ba577e4

Please sign in to comment.