mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix generics with multi generics struct receiver (#9853)
This commit is contained in:
parent
49a2de562b
commit
dd2002cc57
@ -1075,7 +1075,7 @@ pub fn (mut t Table) generic_struct_insts_to_concrete() {
|
||||
fields[i].typ = t_typ
|
||||
}
|
||||
}
|
||||
parent_info.generic_types = []
|
||||
parent_info.is_generic = false
|
||||
parent_info.concrete_types = info.concrete_types.clone()
|
||||
parent_info.fields = fields
|
||||
parent_info.parent_type = new_type(info.parent_idx).set_flag(.generic)
|
||||
|
@ -722,6 +722,7 @@ pub mut:
|
||||
is_typedef bool // C. [typedef]
|
||||
is_union bool
|
||||
is_heap bool
|
||||
is_generic bool
|
||||
generic_types []Type
|
||||
concrete_types []Type
|
||||
parent_type Type
|
||||
|
@ -486,13 +486,15 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx
|
||||
mut typ := ast.void_type
|
||||
for i, param in f.params {
|
||||
mut to_set := ast.void_type
|
||||
// resolve generic struct receiver (TODO: multi generic struct)
|
||||
// resolve generic struct receiver
|
||||
if i == 0 && call_expr.is_method && param.typ.has_flag(.generic) {
|
||||
sym := c.table.get_type_symbol(call_expr.receiver_type)
|
||||
if sym.kind == .struct_ {
|
||||
info := sym.info as ast.Struct
|
||||
if info.concrete_types.len > 0 {
|
||||
typ = info.concrete_types[0]
|
||||
receiver_generic_names := info.generic_types.map(c.table.get_type_symbol(it).name)
|
||||
if gt_name in receiver_generic_names {
|
||||
idx := receiver_generic_names.index(gt_name)
|
||||
typ = info.concrete_types[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1433,7 +1433,7 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, call_exp
|
||||
fn (mut c Checker) check_return_generics_struct(return_type ast.Type, mut call_expr ast.CallExpr, generic_types []ast.Type) {
|
||||
rts := c.table.get_type_symbol(return_type)
|
||||
if rts.info is ast.Struct {
|
||||
if rts.info.generic_types.len > 0 {
|
||||
if rts.info.is_generic {
|
||||
mut nrt := '$rts.name<'
|
||||
mut c_nrt := '${rts.name}_T_'
|
||||
for i in 0 .. call_expr.generic_types.len {
|
||||
@ -1462,7 +1462,7 @@ fn (mut c Checker) check_return_generics_struct(return_type ast.Type, mut call_e
|
||||
}
|
||||
}
|
||||
mut info := rts.info
|
||||
info.generic_types = []
|
||||
info.is_generic = false
|
||||
info.concrete_types = generic_types.clone()
|
||||
info.parent_type = return_type
|
||||
info.fields = fields
|
||||
|
@ -693,7 +693,7 @@ fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
|
||||
mut styp := sym.cname
|
||||
// TODO: this needs to be removed; cgen shouldn't resolve generic types (job of checker)
|
||||
if mut sym.info is ast.Struct {
|
||||
if sym.info.generic_types.len > 0 {
|
||||
if sym.info.is_generic {
|
||||
mut sgtyps := '_T'
|
||||
for gt in sym.info.generic_types {
|
||||
gts := g.table.get_type_symbol(g.unwrap_generic(gt))
|
||||
@ -5438,7 +5438,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||
mut name := typ.cname
|
||||
match mut typ.info {
|
||||
ast.Struct {
|
||||
if typ.info.generic_types.len > 0 {
|
||||
if typ.info.is_generic {
|
||||
continue
|
||||
}
|
||||
if name.contains('_T_') {
|
||||
|
@ -299,6 +299,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
||||
is_typedef: attrs.contains('typedef')
|
||||
is_union: is_union
|
||||
is_heap: attrs.contains('heap')
|
||||
is_generic: generic_types.len > 0
|
||||
generic_types: generic_types
|
||||
attrs: attrs
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
struct Foo<A, B> {
|
||||
a A
|
||||
b B
|
||||
}
|
||||
|
||||
fn (num Foo<A, B>) get_foo1<A, B>() (A, B) {
|
||||
return num.a, num.b
|
||||
}
|
||||
|
||||
fn (num Foo<A, B>) get_foo2<B, A>() (A, B) {
|
||||
return num.a, num.b
|
||||
}
|
||||
|
||||
fn test_generics_with_multi_generics_struct_receiver() {
|
||||
num := Foo<int,string>{
|
||||
a: 3
|
||||
b: 'aaa'
|
||||
}
|
||||
a1, b1 := num.get_foo1()
|
||||
println('$a1, $b1')
|
||||
assert a1 == 3
|
||||
assert b1 == 'aaa'
|
||||
|
||||
a2, b2 := num.get_foo2()
|
||||
println('$a2, $b2')
|
||||
assert a2 == 3
|
||||
assert b2 == 'aaa'
|
||||
}
|
Loading…
Reference in New Issue
Block a user