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

ast, checker: fix error for calling complex nested generic type function (fix #13025) (#13328)

This commit is contained in:
yuyi 2022-01-31 19:00:27 +08:00 committed by GitHub
parent 46a096b95d
commit b34860e39b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 7 deletions

View File

@ -1428,7 +1428,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
if typ == 0 { if typ == 0 {
return none return none
} }
return typ.derive_add_muls(generic_type).clear_flag(.generic) if typ.has_flag(.generic) {
return typ.derive_add_muls(generic_type).set_flag(.generic)
} else {
return typ.derive_add_muls(generic_type).clear_flag(.generic)
}
} }
match mut sym.info { match mut sym.info {
Array { Array {
@ -1443,7 +1447,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
} }
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) { if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
idx := t.find_or_register_array_with_dims(typ, dims) idx := t.find_or_register_array_with_dims(typ, dims)
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic) if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
} }
} }
ArrayFixed { ArrayFixed {
@ -1451,7 +1459,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
concrete_types) concrete_types)
{ {
idx := t.find_or_register_array_fixed(typ, sym.info.size, None{}) idx := t.find_or_register_array_fixed(typ, sym.info.size, None{})
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic) if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
} }
} }
Chan { Chan {
@ -1459,16 +1471,24 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
concrete_types) concrete_types)
{ {
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0) idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic) if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
} }
} }
FnType { FnType {
mut func := sym.info.func mut func := sym.info.func
mut has_generic := false
if func.return_type.has_flag(.generic) { if func.return_type.has_flag(.generic) {
if typ := t.resolve_generic_to_concrete(func.return_type, generic_names, if typ := t.resolve_generic_to_concrete(func.return_type, generic_names,
concrete_types) concrete_types)
{ {
func.return_type = typ func.return_type = typ
if typ.has_flag(.generic) {
has_generic = true
}
} }
} }
func.params = func.params.clone() func.params = func.params.clone()
@ -1478,12 +1498,19 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
concrete_types) concrete_types)
{ {
param.typ = typ param.typ = typ
if typ.has_flag(.generic) {
has_generic = true
}
} }
} }
} }
func.name = '' func.name = ''
idx := t.find_or_register_fn_type('', func, true, false) idx := t.find_or_register_fn_type('', func, true, false)
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic) if has_generic {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
} }
MultiReturn { MultiReturn {
mut types := []Type{} mut types := []Type{}
@ -1498,7 +1525,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
} }
if type_changed { if type_changed {
idx := t.find_or_register_multi_return(types) idx := t.find_or_register_multi_return(types)
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic) if types.any(it.has_flag(.generic)) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
} }
} }
Map { Map {
@ -1519,7 +1550,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
} }
if type_changed { if type_changed {
idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type) idx := t.find_or_register_map(unwrapped_key_type, unwrapped_value_type)
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic) if unwrapped_key_type.has_flag(.generic) || unwrapped_value_type.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
} else {
return new_type(idx).derive_add_muls(generic_type).clear_flag(.generic)
}
} }
} }
Struct, Interface, SumType { Struct, Interface, SumType {

View File

@ -963,6 +963,13 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
} }
if func.generic_names.len > 0 { if func.generic_names.len > 0 {
if has_generic { if has_generic {
if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
node.concrete_types)
{
if typ.has_flag(.generic) {
node.return_type = typ
}
}
return node.return_type return node.return_type
} else if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names, } else if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
concrete_types) concrete_types)

View File

@ -0,0 +1,26 @@
fn test_generics_with_complex_nested_generics_type() {
mut buf := []byte{}
initial<string, u64>(buf)
}
fn initial<K, V>(buf []byte) map[K]V {
mut ret := map[K]V{}
for _ in 0 .. 3 {
k := get<K>(buf)
v := get<V>(buf)
ret[k] = v
}
println(ret)
assert '$ret' == "{'get': 22}"
return ret
}
fn get<T>(buf []byte) T {
$if T is string {
return buf.bytestr() + 'get'
} $else $if T is u64 {
return u64(22)
} $else {
panic('oops!')
}
}