Skip to content

Commit b34860e

Browse files
authored
ast, checker: fix error for calling complex nested generic type function (fix #13025) (#13328)
1 parent 46a096b commit b34860e

File tree

3 files changed

+75
-7
lines changed

3 files changed

+75
-7
lines changed

vlib/v/ast/table.v

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,7 +1428,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
14281428
if typ == 0 {
14291429
return none
14301430
}
1431-
return typ.derive_add_muls(generic_type).clear_flag(.generic)
1431+
if typ.has_flag(.generic) {
1432+
return typ.derive_add_muls(generic_type).set_flag(.generic)
1433+
} else {
1434+
return typ.derive_add_muls(generic_type).clear_flag(.generic)
1435+
}
14321436
}
14331437
match mut sym.info {
14341438
Array {
@@ -1443,32 +1447,48 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
14431447
}
14441448
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
14451449
idx := t.find_or_register_array_with_dims(typ, dims)
1446-
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1450+
if typ.has_flag(.generic) {
1451+
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
1452+
} else {
1453+
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1454+
}
14471455
}
14481456
}
14491457
ArrayFixed {
14501458
if typ := t.resolve_generic_to_concrete(sym.info.elem_type, generic_names,
14511459
concrete_types)
14521460
{
14531461
idx := t.find_or_register_array_fixed(typ, sym.info.size, None{})
1454-
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1462+
if typ.has_flag(.generic) {
1463+
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
1464+
} else {
1465+
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1466+
}
14551467
}
14561468
}
14571469
Chan {
14581470
if typ := t.resolve_generic_to_concrete(sym.info.elem_type, generic_names,
14591471
concrete_types)
14601472
{
14611473
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
1462-
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1474+
if typ.has_flag(.generic) {
1475+
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
1476+
} else {
1477+
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1478+
}
14631479
}
14641480
}
14651481
FnType {
14661482
mut func := sym.info.func
1483+
mut has_generic := false
14671484
if func.return_type.has_flag(.generic) {
14681485
if typ := t.resolve_generic_to_concrete(func.return_type, generic_names,
14691486
concrete_types)
14701487
{
14711488
func.return_type = typ
1489+
if typ.has_flag(.generic) {
1490+
has_generic = true
1491+
}
14721492
}
14731493
}
14741494
func.params = func.params.clone()
@@ -1478,12 +1498,19 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
14781498
concrete_types)
14791499
{
14801500
param.typ = typ
1501+
if typ.has_flag(.generic) {
1502+
has_generic = true
1503+
}
14811504
}
14821505
}
14831506
}
14841507
func.name = ''
14851508
idx := t.find_or_register_fn_type('', func, true, false)
1486-
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1509+
if has_generic {
1510+
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
1511+
} else {
1512+
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1513+
}
14871514
}
14881515
MultiReturn {
14891516
mut types := []Type{}
@@ -1498,7 +1525,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
14981525
}
14991526
if type_changed {
15001527
idx := t.find_or_register_multi_return(types)
1501-
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1528+
if types.any(it.has_flag(.generic)) {
1529+
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
1530+
} else {
1531+
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1532+
}
15021533
}
15031534
}
15041535
Map {
@@ -1519,7 +1550,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
15191550
}
15201551
if type_changed {
15211552
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
1522-
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1553+
if unwrapped_key_type.has_flag(.generic) || unwrapped_value_type.has_flag(.generic) {
1554+
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
1555+
} else {
1556+
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
1557+
}
15231558
}
15241559
}
15251560
Struct, Interface, SumType {

vlib/v/checker/fn.v

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,13 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
963963
}
964964
if func.generic_names.len > 0 {
965965
if has_generic {
966+
if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
967+
node.concrete_types)
968+
{
969+
if typ.has_flag(.generic) {
970+
node.return_type = typ
971+
}
972+
}
966973
return node.return_type
967974
} else if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
968975
concrete_types)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
fn test_generics_with_complex_nested_generics_type() {
2+
mut buf := []byte{}
3+
initial<string, u64>(buf)
4+
}
5+
6+
fn initial<K, V>(buf []byte) map[K]V {
7+
mut ret := map[K]V{}
8+
for _ in 0 .. 3 {
9+
k := get<K>(buf)
10+
v := get<V>(buf)
11+
ret[k] = v
12+
}
13+
println(ret)
14+
assert '$ret' == "{'get': 22}"
15+
return ret
16+
}
17+
18+
fn get<T>(buf []byte) T {
19+
$if T is string {
20+
return buf.bytestr() + 'get'
21+
} $else $if T is u64 {
22+
return u64(22)
23+
} $else {
24+
panic('oops!')
25+
}
26+
}

0 commit comments

Comments
 (0)