From c0321c81a89d2e1723b64aa49c020c40e45abe58 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 21 Dec 2023 18:32:49 +0800 Subject: [PATCH] checker: fix generic array method call with multi-types (#20237) --- vlib/v/checker/fn.v | 15 +++++-- ..._array_method_call_with_multi_types_test.v | 44 +++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/generics_array_method_call_with_multi_types_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index c8d1fae5b0e0f1..e4156ec6c236cc 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1741,10 +1741,10 @@ fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { } else if (left_sym.kind == .map || final_left_sym.kind == .map) && method_name in ['clone', 'keys', 'values', 'move', 'delete'] { if left_sym.kind == .map { - return c.map_builtin_method_call(mut node, unwrapped_left_type, c.table.sym(unwrapped_left_type)) + return c.map_builtin_method_call(mut node, left_type) } else if left_sym.info is ast.Alias { - parent_type := c.unwrap_generic(left_sym.info.parent_type) - return c.map_builtin_method_call(mut node, parent_type, c.table.final_sym(unwrapped_left_type)) + parent_type := left_sym.info.parent_type + return c.map_builtin_method_call(mut node, parent_type) } } else if left_sym.kind == .array && method_name in ['insert', 'prepend'] { if method_name == 'insert' { @@ -2652,9 +2652,16 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast } } -fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.Type, left_sym ast.TypeSymbol) ast.Type { +fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type_ ast.Type) ast.Type { method_name := node.name mut ret_type := ast.void_type + // resolve T + left_type := if c.table.final_sym(left_type_).kind == .any { + c.unwrap_generic(left_type_) + } else { + left_type_ + } + left_sym := c.table.final_sym(left_type) match method_name { 'clone', 'move' { if node.args.len != 0 { diff --git a/vlib/v/tests/generics_array_method_call_with_multi_types_test.v b/vlib/v/tests/generics_array_method_call_with_multi_types_test.v new file mode 100644 index 00000000000000..5d7a4aeb8c7226 --- /dev/null +++ b/vlib/v/tests/generics_array_method_call_with_multi_types_test.v @@ -0,0 +1,44 @@ +pub type EventListener[T] = fn (T) ! + +pub type Check[T] = fn (T) bool + +pub struct EventController[T] { +mut: + id int + listeners map[int]EventListener[T] +} + +fn (mut ec EventController[T]) generate_id() int { + return ec.id++ +} + +@[params] +pub struct EmitOptions { +pub: + error_handler ?fn (int, IError) +} + +pub fn (mut ec EventController[T]) emit(e T, options EmitOptions) { + if ec.listeners.len == 1 { + f := ec.listeners.values()[0] + f(e) or { + if g := options.error_handler { + g(0, err) + } + } + return + } +} + +struct Foo {} + +struct Bar {} + +fn test_generic_array_method_call_with_multi_types() { + foo := EventController[Foo]{} + println(foo) + assert foo.id == 0 + bar := EventController[Bar]{} + println(bar) + assert bar.id == 0 +}