checker: fix generic array method call with multi-types (#20237)

This commit is contained in:
yuyi 2023-12-21 18:32:49 +08:00 committed by GitHub
parent 7a16a72cc5
commit c0321c81a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 4 deletions

View File

@ -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) } else if (left_sym.kind == .map || final_left_sym.kind == .map)
&& method_name in ['clone', 'keys', 'values', 'move', 'delete'] { && method_name in ['clone', 'keys', 'values', 'move', 'delete'] {
if left_sym.kind == .map { 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 { } else if left_sym.info is ast.Alias {
parent_type := c.unwrap_generic(left_sym.info.parent_type) parent_type := left_sym.info.parent_type
return c.map_builtin_method_call(mut node, parent_type, c.table.final_sym(unwrapped_left_type)) return c.map_builtin_method_call(mut node, parent_type)
} }
} else if left_sym.kind == .array && method_name in ['insert', 'prepend'] { } else if left_sym.kind == .array && method_name in ['insert', 'prepend'] {
if method_name == 'insert' { 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 method_name := node.name
mut ret_type := ast.void_type 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 { match method_name {
'clone', 'move' { 'clone', 'move' {
if node.args.len != 0 { if node.args.len != 0 {

View File

@ -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
}