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)
|
left_type := c.expr(call_expr.left)
|
||||||
c.expected_type = left_type
|
c.expected_type = left_type
|
||||||
mut is_generic := left_type.has_flag(.generic)
|
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
|
call_expr.left_type = left_type
|
||||||
// Set default values for .return_type & .receiver_type too,
|
// Set default values for .return_type & .receiver_type too,
|
||||||
// or there will be hard to diagnose 0 type panics in cgen.
|
// 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()`
|
// left & left_type will be `x` and `x type` in `x.fieldfn()`
|
||||||
// will be `0` for `foo()`
|
// will be `0` for `foo()`
|
||||||
mut is_interface_call := false
|
mut is_interface_call := false
|
||||||
|
mut is_selector_call := false
|
||||||
if node.left_type != 0 {
|
if node.left_type != 0 {
|
||||||
left_sym := g.table.get_type_symbol(node.left_type)
|
left_sym := g.table.get_type_symbol(node.left_type)
|
||||||
if left_sym.kind == .interface_ {
|
if left_sym.kind == .interface_ {
|
||||||
|
@ -843,6 +844,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
} else {
|
} else {
|
||||||
g.write('.')
|
g.write('.')
|
||||||
}
|
}
|
||||||
|
is_selector_call = true
|
||||||
}
|
}
|
||||||
mut name := node.name
|
mut name := node.name
|
||||||
is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic']
|
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')
|
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
|
// TODO2
|
||||||
// cgen shouldn't modify ast nodes, this should be moved
|
// cgen shouldn't modify ast nodes, this should be moved
|
||||||
// g.generate_tmp_autofree_arg_vars(node, name)
|
// 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