diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index ba7b0a6133..127835d15a 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -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 { diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 2485c8101b..3735bc43ac 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -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) diff --git a/vlib/v/tests/generics_with_complex_nested_generics_type_test.v b/vlib/v/tests/generics_with_complex_nested_generics_type_test.v new file mode 100644 index 0000000000..5c8fde260f --- /dev/null +++ b/vlib/v/tests/generics_with_complex_nested_generics_type_test.v @@ -0,0 +1,26 @@ +fn test_generics_with_complex_nested_generics_type() { + mut buf := []byte{} + initial(buf) +} + +fn initial(buf []byte) map[K]V { + mut ret := map[K]V{} + for _ in 0 .. 3 { + k := get(buf) + v := get(buf) + ret[k] = v + } + println(ret) + assert '$ret' == "{'get': 22}" + return ret +} + +fn get(buf []byte) T { + $if T is string { + return buf.bytestr() + 'get' + } $else $if T is u64 { + return u64(22) + } $else { + panic('oops!') + } +}