diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index ff203d196b..e9b99b0a98 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -367,6 +367,12 @@ fn (mut c Checker) check_basic(got ast.Type, expected ast.Type) bool { if c.table.sumtype_has_variant(expected, ast.mktyp(got), false) { return true } + // struct + if exp_sym.kind == .struct_ && got_sym.kind == .struct_ { + if c.table.type_to_str(expected) == c.table.type_to_str(got) { + return true + } + } // type alias if (got_sym.kind == .alias && got_sym.parent_idx == expected.idx()) || (exp_sym.kind == .alias && exp_sym.parent_idx == got.idx()) { @@ -671,7 +677,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) if field_sym.name == gt_name { for t in node.fields { if ft.name == t.name && t.typ != 0 { - concrete_types << t.typ + concrete_types << ast.mktyp(t.typ) continue gname } } @@ -695,7 +701,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) && elem_typ.nr_muls() > 0 { elem_typ = elem_typ.set_nr_muls(0) } - concrete_types << elem_typ + concrete_types << ast.mktyp(elem_typ) continue gname } break @@ -723,7 +729,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) && elem_typ.nr_muls() > 0 { elem_typ = elem_typ.set_nr_muls(0) } - concrete_types << elem_typ + concrete_types << ast.mktyp(elem_typ) continue gname } break @@ -744,7 +750,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) && key_typ.nr_muls() > 0 { key_typ = key_typ.set_nr_muls(0) } - concrete_types << key_typ + concrete_types << ast.mktyp(key_typ) continue gname } if field_sym.info.value_type.has_flag(.generic) @@ -754,7 +760,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) && val_typ.nr_muls() > 0 { val_typ = val_typ.set_nr_muls(0) } - concrete_types << val_typ + concrete_types << ast.mktyp(val_typ) continue gname } } @@ -773,7 +779,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) if fn_param.typ.nr_muls() > 0 && arg_typ.nr_muls() > 0 { arg_typ = arg_typ.set_nr_muls(0) } - concrete_types << arg_typ + concrete_types << ast.mktyp(arg_typ) continue gname } } @@ -784,7 +790,7 @@ fn (mut c Checker) infer_struct_generic_types(typ ast.Type, node ast.StructInit) && ret_typ.nr_muls() > 0 { ret_typ = ret_typ.set_nr_muls(0) } - concrete_types << ret_typ + concrete_types << ast.mktyp(ret_typ) continue gname } } diff --git a/vlib/v/tests/generics_struct_init_with_generic_struct_items_test.v b/vlib/v/tests/generics_struct_init_with_generic_struct_items_test.v new file mode 100644 index 0000000000..d82981221e --- /dev/null +++ b/vlib/v/tests/generics_struct_init_with_generic_struct_items_test.v @@ -0,0 +1,85 @@ +struct Item[T] { + val T +} + +struct Items[A, B] { + item1 Item[A] + item2 Item[B] +} + +fn combine[A, B](a A, b B) Items[A, B] { + return Items[A, B]{ + item1: Item[A]{ + val: a + } + item2: Item[B]{ + val: b + } + } +} + +fn test_generic_struct_with_generic_struct_items() { + _ := Items[int, string]{Item{42}, Item{'bye'}} + _ := Items[int, string]{ + item1: Item{42} + item2: Item{'bye'} + } + _ := Items[int, string]{ + item1: Item{ + val: 42 + } + item2: Item{ + val: 'bye' + } + } + _ := Items[int, string]{ + item1: Item[int]{ + val: 42 + } + item2: Item[string]{ + val: 'bye' + } + } + _ := Items[string, int]{ + item1: Item[string]{ + val: 'hallo' + } + item2: Item[int]{ + val: 42 + } + } + _ := Items[string, string]{ + item1: Item[string]{ + val: 'hallo' + } + item2: Item[string]{ + val: 'bye' + } + } + + // calling function all combination OK + r1 := combine('Hallo', 42) + println(r1) + assert r1.item1.val == 'Hallo' + assert r1.item2.val == 42 + + r2 := combine(42, 'Hallo') + println(r2) + assert r2.item1.val == 42 + assert r2.item2.val == 'Hallo' + + r3 := combine('Hallo', 'Bye') + println(r3) + assert r3.item1.val == 'Hallo' + assert r3.item2.val == 'Bye' + + r4 := combine(42, 44) + println(r4) + assert r4.item1.val == 42 + assert r4.item2.val == 44 + + r5 := combine(`🥸`, `🤡`) + println(r5) + assert r5.item1.val == `🥸` + assert r5.item2.val == `🤡` +}