checker: fix generics with multi generic struct types (#10808)

pull/10819/head
yuyi 2021-07-15 22:39:55 +08:00 committed by GitHub
parent 06edbc8a38
commit ddaac5af92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 1 deletions

View File

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

View File

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

View File

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