Skip to content

Commit

Permalink
fix checking match branch call expr twice
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Feb 26, 2024
1 parent 43e96ce commit d29b711
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 10 deletions.
21 changes: 11 additions & 10 deletions vlib/v/checker/match.v
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,19 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
c.error('`none` cannot be a match condition', node.pos)
}
// If the last statement is an expression, return its type
if branch.stmts.len > 0 {
if branch.stmts.len > 0 && node.is_expr {
mut stmt := branch.stmts.last()
if mut stmt is ast.ExprStmt {
if node.is_expr {
c.expected_type = node.expected_type
c.expected_type = node.expected_type
expr_type := if stmt.expr is ast.CallExpr {
stmt.typ
} else {
c.expr(mut stmt.expr)
}
expr_type := c.expr(mut stmt.expr)
stmt.typ = expr_type
if first_iteration {
if node.is_expr && (node.expected_type.has_flag(.option)
|| node.expected_type.has_flag(.result)
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return]) {
if node.expected_type.has_flag(.option) || node.expected_type.has_flag(.result)
|| c.table.type_kind(node.expected_type) in [.sum_type, .multi_return] {
c.check_match_branch_last_stmt(stmt, node.expected_type, expr_type)
ret_type = node.expected_type
} else {
Expand All @@ -98,7 +99,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
infer_cast_type = stmt.expr.typ
}
} else {
if node.is_expr && ret_type.idx() != expr_type.idx() {
if ret_type.idx() != expr_type.idx() {
if (node.expected_type.has_flag(.option)
|| node.expected_type.has_flag(.result))
&& c.table.sym(stmt.typ).kind == .struct_
Expand All @@ -115,7 +116,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
c.check_match_branch_last_stmt(stmt, ret_type, expr_type)
}
}
if node.is_expr && stmt.typ != ast.error_type {
if stmt.typ != ast.error_type {
ret_sym := c.table.sym(ret_type)
stmt_sym := c.table.sym(stmt.typ)
if ret_sym.kind !in [.sum_type, .interface_]
Expand Down Expand Up @@ -208,7 +209,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
}
}
} else if stmt !in [ast.Return, ast.BranchStmt] {
if node.is_expr && ret_type != ast.void_type {
if ret_type != ast.void_type {
c.error('`match` expression requires an expression as the last statement of every branch',
stmt.pos)
}
Expand Down
28 changes: 28 additions & 0 deletions vlib/v/checker/tests/match_branch_call_expr_arg_mismatch.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
vlib/v/checker/tests/match_branch_call_expr_arg_mismatch.vv:16:19: error: cannot use `&Foobar` as `&Foo` in argument 1 to `mutate_foo`
14 | match foobar {
15 | Foo {
16 | mutate_foo(mut foobar)
| ~~~~~~
17 | }
18 | Bar {
vlib/v/checker/tests/match_branch_call_expr_arg_mismatch.vv:19:19: error: cannot use `&Foobar` as `&Bar` in argument 1 to `mutate_bar`
17 | }
18 | Bar {
19 | mutate_bar(mut foobar)
| ~~~~~~
20 | }
21 | }
vlib/v/checker/tests/match_branch_call_expr_arg_mismatch.vv:27:19: error: cannot use `&Foobar` as `&Foo` in argument 1 to `mutate_foo`
25 | return match foobar {
26 | Foo {
27 | mutate_foo(mut foobar)
| ~~~~~~
28 | }
29 | Bar {
vlib/v/checker/tests/match_branch_call_expr_arg_mismatch.vv:30:19: error: cannot use `&Foobar` as `&Bar` in argument 1 to `mutate_bar`
28 | }
29 | Bar {
30 | mutate_bar(mut foobar)
| ~~~~~~
31 | }
32 | }
49 changes: 49 additions & 0 deletions vlib/v/checker/tests/match_branch_call_expr_arg_mismatch.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
struct Foo {
mut:
x int
}

struct Bar {
mut:
y int
}

type Foobar = Foo | Bar

fn mutate_foobar1(mut foobar Foobar) {
match foobar {
Foo {
mutate_foo(mut foobar)
}
Bar {
mutate_bar(mut foobar)
}
}
}

fn mutate_foobar2(mut foobar Foobar) int {
return match foobar {
Foo {
mutate_foo(mut foobar)
}
Bar {
mutate_bar(mut foobar)
}
}
}

fn mutate_foo(mut foo Foo) int {
foo.x = 5
return 5
}

fn mutate_bar(mut bar Bar) int {
bar.y = 10
return 10
}

fn main() {
mut bar := Bar{y: 0}
mutate_foobar1(mut bar)
mutate_foobar2(mut bar)
}

0 comments on commit d29b711

Please sign in to comment.