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

pull/13332/head weekly.2022.05
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 {
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 {
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) {
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 {
@ -1451,7 +1459,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
concrete_types)
{
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 {
@ -1459,16 +1471,24 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
concrete_types)
{
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 {
mut func := sym.info.func
mut has_generic := false
if func.return_type.has_flag(.generic) {
if typ := t.resolve_generic_to_concrete(func.return_type, generic_names,
concrete_types)
{
func.return_type = typ
if typ.has_flag(.generic) {
has_generic = true
}
}
}
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)
{
param.typ = typ
if typ.has_flag(.generic) {
has_generic = true
}
}
}
}
func.name = ''
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 {
mut types := []Type{}
@ -1498,7 +1525,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
if type_changed {
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 {
@ -1519,7 +1550,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
if type_changed {
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 {

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 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
} else if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names,
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!')
}
}