diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index 0cf8c5a3309edd..9e746540543796 100644 --- a/vlib/v/checker/match.v +++ b/vlib/v/checker/match.v @@ -102,6 +102,8 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type { if ret_type.idx() != expr_type.idx() { if node.expected_type.has_option_or_result() && c.table.sym(stmt.typ).kind == .struct_ + && (c.table.sym(ret_type).kind != .sum_type + || !c.check_types(expr_type, ret_type)) && c.type_implements(stmt.typ, ast.error_type, node.pos) { stmt.expr = ast.CastExpr{ expr: stmt.expr diff --git a/vlib/v/tests/return_match_expr_of_sumtype_do_not_cast_to_ierror_test.v b/vlib/v/tests/return_match_expr_of_sumtype_do_not_cast_to_ierror_test.v new file mode 100644 index 00000000000000..b520e5287f0ce7 --- /dev/null +++ b/vlib/v/tests/return_match_expr_of_sumtype_do_not_cast_to_ierror_test.v @@ -0,0 +1,73 @@ +type Foo = int | string | Bar + +struct Bar {} + +fn foo_result_struct_second() !Foo { + return match true { + true { 1 } + else { Bar{} } + } +} + +fn foo_option_struct_second() ?Foo { + return match true { + true { 1 } + else { Bar{} } + } +} + +fn foo_result_string_second() !Foo { + return match true { + true { 1 } + else { '' } + } +} + +fn foo_option_string_second() ?Foo { + return match true { + true { 1 } + else { '' } + } +} + +fn foo_result_struct_first() !Foo { + return match true { + true { Bar{} } + else { 7 } + } +} + +fn foo_option_struct_first() ?Foo { + return match true { + true { Bar{} } + else { 7 } + } +} + +fn test_return_match_expr_of_sumtype_opt_res() { + mut ret := Foo{} + + ret = foo_result_struct_second() or { return } + println(ret) + assert '${ret}' == 'Foo(1)' + + ret = foo_option_struct_second() or { return } + println(ret) + assert '${ret}' == 'Foo(1)' + + ret = foo_result_string_second() or { return } + println(ret) + assert '${ret}' == 'Foo(1)' + + ret = foo_option_string_second() or { return } + println(ret) + assert '${ret}' == 'Foo(1)' + + ret = foo_result_struct_first() or { return } + println(ret) + assert '${ret}' == 'Foo(Bar{})' + + ret = foo_option_struct_first() or { return } + println(ret) + assert '${ret}' == 'Foo(Bar{})' +}