checker: fix generics with multi generic struct types (#10808)
parent
06edbc8a38
commit
ddaac5af92
|
@ -1968,6 +1968,13 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type {
|
|||
left_type := c.expr(call_expr.left)
|
||||
c.expected_type = left_type
|
||||
mut is_generic := left_type.has_flag(.generic)
|
||||
// x is Bar<T>, x.foo() -> x.foo<T>()
|
||||
if is_generic && call_expr.concrete_types.len == 0 {
|
||||
rec_sym := c.table.get_type_symbol(left_type)
|
||||
if rec_sym.info is ast.Struct {
|
||||
call_expr.concrete_types = rec_sym.info.generic_types
|
||||
}
|
||||
}
|
||||
call_expr.left_type = left_type
|
||||
// Set default values for .return_type & .receiver_type too,
|
||||
// or there will be hard to diagnose 0 type panics in cgen.
|
||||
|
|
|
@ -831,6 +831,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
// left & left_type will be `x` and `x type` in `x.fieldfn()`
|
||||
// will be `0` for `foo()`
|
||||
mut is_interface_call := false
|
||||
mut is_selector_call := false
|
||||
if node.left_type != 0 {
|
||||
left_sym := g.table.get_type_symbol(node.left_type)
|
||||
if left_sym.kind == .interface_ {
|
||||
|
@ -843,6 +844,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
} else {
|
||||
g.write('.')
|
||||
}
|
||||
is_selector_call = true
|
||||
}
|
||||
mut name := node.name
|
||||
is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic']
|
||||
|
@ -914,7 +916,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
panic('cgen: obf name "$key" not found, this should never happen')
|
||||
}
|
||||
}
|
||||
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||
if !is_selector_call {
|
||||
name = g.generic_fn_name(node.concrete_types, name, false)
|
||||
}
|
||||
// TODO2
|
||||
// cgen shouldn't modify ast nodes, this should be moved
|
||||
// g.generate_tmp_autofree_arg_vars(node, name)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
struct Animal<T> {
|
||||
metadata T
|
||||
}
|
||||
|
||||
fn (a Animal<T>) get<T>() T {
|
||||
return a.metadata
|
||||
}
|
||||
|
||||
fn extract<T>(x Animal<T>) T {
|
||||
return x.get()
|
||||
}
|
||||
|
||||
fn test_generics_with_multi_generic_struct_types() {
|
||||
a := Animal<int>{123}
|
||||
b := Animal<string>{'456'}
|
||||
|
||||
assert extract<int>(a) == 123
|
||||
assert extract<string>(b) == '456'
|
||||
}
|
Loading…
Reference in New Issue