From cc55aa5b36e50756df65e43e4cbc96b5b569d6cc Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 28 Oct 2024 16:56:12 +0200 Subject: [PATCH] checker: allow for `f() or { T{} }` in a generic method, for `fn f() ?T {`, being called with `T`, being a container like []int etc, not just a primitive type like int (#22672) --- vlib/v/checker/checker.v | 3 + ...eric_default_expression_in_or_block_test.v | 91 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 vlib/v/tests/generics/generic_default_expression_in_or_block_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index cc6ae0a697..6d4f278e4e 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1419,6 +1419,9 @@ fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, expr } type_name := c.table.type_to_str(last_stmt_typ) expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result()) + if ret_type.has_flag(.generic) { + return + } c.error('wrong return type `${type_name}` in the `or {}` block, expected `${expected_type_name}`', stmt.expr.pos()) } diff --git a/vlib/v/tests/generics/generic_default_expression_in_or_block_test.v b/vlib/v/tests/generics/generic_default_expression_in_or_block_test.v new file mode 100644 index 0000000000..21ca0f2ecb --- /dev/null +++ b/vlib/v/tests/generics/generic_default_expression_in_or_block_test.v @@ -0,0 +1,91 @@ +struct St[T] { +mut: + a []T +} + +fn (s St[T]) peek() ?T { + if s.a.len > 0 { + return s.a[0] + } else { + return none + } +} + +fn (mut s St[T]) peek_or_default() T { + return s.peek() or { T{} } +} + +fn (mut s St[T]) push(e T) { + x := s.peek() or { T{} } // this is deliberate + $if x is $array { + dump(x) + if s.a.len > 0 { + assert x.len > 0 + } else { + assert x.len == 0 + } + } + $if x is $int { + dump(x) + if s.a.len > 0 { + assert x == 2 + } else { + assert x == 0 + } + } + $if x is $map { + dump(x) + if s.a.len > 0 { + assert x == { + 'abc': u8(4) + 'def': 7 + } + } + } + s.a << e +} + +fn test_ints() { + mut s := St[int]{} + r := s.peek_or_default() + s.push(2) + s.push(3) + s.push(99) + assert s.a == [2, 3, 99] + dump(s) +} + +fn test_array_of_ints() { + mut s := St[[]int]{} + r := s.peek_or_default() + s.push([2, 3, 5]) + s.push([]int{}) + s.push([10, 20, 99]) + s.push([55, 88]) + assert s.a == [[2, 3, 5], []int{}, [10, 20, 99], [55, 88]] + dump(s) +} + +fn test_maps_of_u8s() { + mut s := St[map[string]u8]{} + r := s.peek_or_default() + s.push({ + 'abc': u8(4) + 'def': 7 + }) + s.push({ + 'xyz': u8(13) + }) + s.push({ + 'zzz': u8(99) + }) + assert s.a == [{ + 'abc': u8(4) + 'def': 7 + }, { + 'xyz': u8(13) + }, { + 'zzz': u8(99) + }] + dump(s) +}