1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast, parser, cgen: fix generic struct init with inconsistent generic types (#17639)

This commit is contained in:
yuyi 2023-03-14 19:24:52 +08:00 committed by GitHub
parent cb7e25e47e
commit 2643d6645f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 30 additions and 3 deletions

View File

@ -1714,6 +1714,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
Struct, Interface, SumType {
if sym.info.is_generic {
mut nrt := '${sym.name}['
mut rnrt := '${sym.rname}['
mut t_generic_names := generic_names.clone()
mut t_concrete_types := concrete_types.clone()
if sym.generic_types.len > 0 && sym.generic_types.len == sym.info.generic_types.len
@ -1744,17 +1745,23 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
{
gts := t.sym(ct)
nrt += gts.name
rnrt += gts.name
if i != sym.info.generic_types.len - 1 {
nrt += ', '
rnrt += ', '
}
} else {
return none
}
}
nrt += ']'
rnrt += ']'
mut idx := t.type_idxs[nrt]
if idx == 0 {
idx = t.add_placeholder_type(nrt, .v)
idx = t.type_idxs[rnrt]
if idx == 0 {
idx = t.add_placeholder_type(nrt, .v)
}
}
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}

View File

@ -94,6 +94,7 @@ pub mut:
kind Kind
name string // the internal & source name of the type, i.e. `[5]int`.
cname string // the name with no dots for use in the generated C code
rname string // the raw name
methods []Fn
generic_types []Type
mod string

View File

@ -983,7 +983,11 @@ fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) {
mut concrete_types := []ast.Type{}
match arg_sym.info {
ast.Struct, ast.Interface, ast.SumType {
generic_types = arg_sym.info.generic_types.clone()
if param_type_sym.generic_types.len > 0 {
generic_types = param_type_sym.generic_types.clone()
} else {
generic_types = arg_sym.info.generic_types.clone()
}
concrete_types = arg_sym.info.concrete_types.clone()
}
else {}

View File

@ -1325,7 +1325,7 @@ fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
// TODO: this needs to be removed; cgen shouldn't resolve generic types (job of checker)
match sym.info {
ast.Struct, ast.Interface, ast.SumType {
if sym.info.is_generic {
if sym.info.is_generic && sym.generic_types.len == 0 {
mut sgtyps := '_T'
for gt in sym.info.generic_types {
gts := g.table.sym(g.unwrap_generic(gt))

View File

@ -682,6 +682,7 @@ pub fn (mut p Parser) find_type_or_add_placeholder(name string, language ast.Lan
idx = p.table.register_sym(ast.TypeSymbol{
...sym
name: sym_name
rname: sym.name
generic_types: p.struct_init_generic_types.clone()
})
}

View File

@ -0,0 +1,14 @@
struct MyData[T] {
}
fn myfunc[U](a MyData[U]) string {
println(a)
return '${a}'
}
fn test_generics_struct_init_with_inconsistent_generic_types() {
d1 := MyData[int]{}
r1 := myfunc(d1)
println(r1)
assert r1 == 'MyData[int]{}'
}