From 9d164d07b34069c1cf04531cdfb544589026736a Mon Sep 17 00:00:00 2001 From: Tim Marston Date: Tue, 8 Oct 2024 08:04:27 +0100 Subject: [PATCH] checker: don't cast match branch structs to IError, when the return type of a function is !SumType (#22444) --- vlib/v/checker/match.v | 2 + ...pr_of_sumtype_do_not_cast_to_ierror_test.v | 73 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 vlib/v/tests/return_match_expr_of_sumtype_do_not_cast_to_ierror_test.v diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index 0cf8c5a33..9e7465405 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 000000000..b520e5287 --- /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{})' +} -- 2.39.5