Skip to content

Commit

Permalink
checker: fix generic array method call with multi-types (#20237)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 committed Dec 21, 2023
1 parent 7a16a72 commit c0321c8
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
15 changes: 11 additions & 4 deletions vlib/v/checker/fn.v
Expand Up @@ -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' {
Expand Down Expand Up @@ -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 {
Expand Down
44 changes: 44 additions & 0 deletions 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
}

0 comments on commit c0321c8

Please sign in to comment.