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

checker: fix generic struct init with generic struct items (#18152)

This commit is contained in:
yuyi 2023-05-11 00:06:34 +08:00 committed by GitHub
parent 492a93ecd9
commit a87f2d9d11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 98 additions and 7 deletions

View File

@ -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) { if c.table.sumtype_has_variant(expected, ast.mktyp(got), false) {
return true 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 // type alias
if (got_sym.kind == .alias && got_sym.parent_idx == expected.idx()) if (got_sym.kind == .alias && got_sym.parent_idx == expected.idx())
|| (exp_sym.kind == .alias && exp_sym.parent_idx == got.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 { if field_sym.name == gt_name {
for t in node.fields { for t in node.fields {
if ft.name == t.name && t.typ != 0 { if ft.name == t.name && t.typ != 0 {
concrete_types << t.typ concrete_types << ast.mktyp(t.typ)
continue gname 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.nr_muls() > 0 {
elem_typ = elem_typ.set_nr_muls(0) elem_typ = elem_typ.set_nr_muls(0)
} }
concrete_types << elem_typ concrete_types << ast.mktyp(elem_typ)
continue gname continue gname
} }
break 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.nr_muls() > 0 {
elem_typ = elem_typ.set_nr_muls(0) elem_typ = elem_typ.set_nr_muls(0)
} }
concrete_types << elem_typ concrete_types << ast.mktyp(elem_typ)
continue gname continue gname
} }
break 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.nr_muls() > 0 {
key_typ = key_typ.set_nr_muls(0) key_typ = key_typ.set_nr_muls(0)
} }
concrete_types << key_typ concrete_types << ast.mktyp(key_typ)
continue gname continue gname
} }
if field_sym.info.value_type.has_flag(.generic) 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.nr_muls() > 0 {
val_typ = val_typ.set_nr_muls(0) val_typ = val_typ.set_nr_muls(0)
} }
concrete_types << val_typ concrete_types << ast.mktyp(val_typ)
continue gname 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 { if fn_param.typ.nr_muls() > 0 && arg_typ.nr_muls() > 0 {
arg_typ = arg_typ.set_nr_muls(0) arg_typ = arg_typ.set_nr_muls(0)
} }
concrete_types << arg_typ concrete_types << ast.mktyp(arg_typ)
continue gname 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.nr_muls() > 0 {
ret_typ = ret_typ.set_nr_muls(0) ret_typ = ret_typ.set_nr_muls(0)
} }
concrete_types << ret_typ concrete_types << ast.mktyp(ret_typ)
continue gname continue gname
} }
} }

View File

@ -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 == `🤡`
}