diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f8cb824020..05e8e8294a 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -57,25 +57,26 @@ fn all_valid_comptime_idents() []string { pub struct Checker { pref &pref.Preferences // Preferences shared from V struct pub mut: - table &ast.Table - file &ast.File = 0 - nr_errors int - nr_warnings int - nr_notices int - errors []errors.Error - warnings []errors.Warning - notices []errors.Notice - error_lines []int // to avoid printing multiple errors for the same line - expected_type ast.Type - expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type - mod string // current module name - const_decl string - const_deps []string - const_names []string - global_names []string - locked_names []string // vars that are currently locked - rlocked_names []string // vars that are currently read-locked - in_for_count int // if checker is currently in a for loop + table &ast.Table + file &ast.File = 0 + nr_errors int + nr_warnings int + nr_notices int + errors []errors.Error + warnings []errors.Warning + notices []errors.Notice + error_lines []int // to avoid printing multiple errors for the same line + expected_type ast.Type + expected_or_type ast.Type // fn() or { 'this type' } eg. string. expected or block type + expected_expr_type ast.Type // if/match is_expr: expected_type + mod string // current module name + const_decl string + const_deps []string + const_names []string + global_names []string + locked_names []string // vars that are currently locked + rlocked_names []string // vars that are currently read-locked + in_for_count int // if checker is currently in a for loop // checked_ident string // to avoid infinite checker loops should_abort bool // when too many errors/warnings/notices are accumulated, .should_abort becomes true. It is checked in statement/expression loops, so the checker can return early, instead of wasting time. returns bool @@ -3835,7 +3836,11 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type { // with this value. pub fn (mut c Checker) enum_val(mut node ast.EnumVal) ast.Type { mut typ_idx := if node.enum_name == '' { - c.expected_type.idx() + if c.expected_type == ast.void_type && c.expected_expr_type != ast.void_type { + c.expected_expr_type.idx() + } else { + c.expected_type.idx() + } } else { c.table.find_type_idx(node.enum_name) } diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index d43005e281..36cd435118 100644 --- a/vlib/v/checker/match.v +++ b/vlib/v/checker/match.v @@ -13,6 +13,12 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type { c.error('unnecessary `()` in `match` condition, use `match expr {` instead of `match (expr) {`.', node.cond.pos) } + if node.is_expr { + c.expected_expr_type = c.expected_type + defer { + c.expected_expr_type = ast.void_type + } + } cond_type := c.expr(node.cond) // we setting this here rather than at the end of the method // since it is used in c.match_exprs() it saves checking twice diff --git a/vlib/v/tests/match_expr_with_enum_test.v b/vlib/v/tests/match_expr_with_enum_test.v new file mode 100644 index 0000000000..0ba8196db6 --- /dev/null +++ b/vlib/v/tests/match_expr_with_enum_test.v @@ -0,0 +1,24 @@ +enum Foo { + a + b + c +} + +fn get() Foo { + return .a +} + +fn foo(f Foo) string { + println(f) + return '$f' +} + +fn test_match_expr_with_enum() { + ret := foo(match get() { + .a { .b } + .b { .c } + .c { .a } + }) + println(ret) + assert ret == 'b' +}