mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix generic struct init with inconsistent generic optional types (#16766)
This commit is contained in:
parent
21d6bd930e
commit
64ed007f94
@ -168,10 +168,43 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
}
|
||||
}
|
||||
if field.name in inited_fields {
|
||||
sfield := node.fields[inited_fields[field.name]]
|
||||
mut sfield := node.fields[inited_fields[field.name]]
|
||||
if sfield.typ == 0 {
|
||||
continue
|
||||
}
|
||||
if sfield.expected_type.has_flag(.generic) && g.cur_fn != unsafe { nil } {
|
||||
mut mut_table := unsafe { &ast.Table(g.table) }
|
||||
mut t_generic_names := g.table.cur_fn.generic_names.clone()
|
||||
mut t_concrete_types := g.cur_concrete_types.clone()
|
||||
ts := g.table.sym(node.typ)
|
||||
if ts.generic_types.len > 0 && ts.generic_types.len == info.generic_types.len
|
||||
&& ts.generic_types != info.generic_types {
|
||||
t_generic_names = info.generic_types.map(g.table.sym(it).name)
|
||||
t_concrete_types = []
|
||||
for t_typ in ts.generic_types {
|
||||
if !t_typ.has_flag(.generic) {
|
||||
t_concrete_types << t_typ
|
||||
} else if g.table.sym(t_typ).kind == .any {
|
||||
tname := g.table.sym(t_typ).name
|
||||
index := g.table.cur_fn.generic_names.index(tname)
|
||||
if index >= 0 && index < g.cur_concrete_types.len {
|
||||
t_concrete_types << g.cur_concrete_types[index]
|
||||
}
|
||||
} else {
|
||||
if tt := mut_table.resolve_generic_to_concrete(t_typ,
|
||||
g.table.cur_fn.generic_names, g.cur_concrete_types)
|
||||
{
|
||||
t_concrete_types << tt
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if tt := mut_table.resolve_generic_to_concrete(sfield.expected_type,
|
||||
t_generic_names, t_concrete_types)
|
||||
{
|
||||
sfield.expected_type = tt
|
||||
}
|
||||
}
|
||||
g.struct_init_field(sfield, sym.language)
|
||||
if is_multiline {
|
||||
g.writeln(',')
|
||||
|
@ -0,0 +1,94 @@
|
||||
struct Tuple2[A, B] {
|
||||
a ?A // Option
|
||||
b ?B // Option
|
||||
}
|
||||
|
||||
// map to array of Tuple2[int, Tuple2[key, value]] tuples
|
||||
fn map_to_array_int_kv[K, V](m map[K]V) []Tuple2[int, Tuple2[K, V]] {
|
||||
mut r := []Tuple2[int, Tuple2[K, V]]{cap: m.len}
|
||||
mut i := 0
|
||||
for k, v in m {
|
||||
r << Tuple2[int, Tuple2[K, V]]{i, Tuple2[K, V]{k, v}}
|
||||
i += 1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// map to array of Tuple2[int, Tuple2[Tuple2[key, value], Tuple2[value, key]]] tuples
|
||||
fn map_to_array_int_kv_vk[K, V](m map[K]V) []Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]] {
|
||||
mut r := []Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]]{cap: m.len}
|
||||
mut i := 0
|
||||
for k, v in m {
|
||||
r << Tuple2[int, Tuple2[Tuple2[K, V], Tuple2[V, K]]]{i, Tuple2[Tuple2[K, V], Tuple2[V, K]]{Tuple2[K, V]{k, v}, Tuple2[V, K]{v, k}}}
|
||||
i += 1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
fn test_generics_struct_init_with_inconsistent_generic_types() {
|
||||
x := {
|
||||
'one': 1
|
||||
'two': 2
|
||||
}
|
||||
y := {
|
||||
3: 'three'
|
||||
4: 'four'
|
||||
}
|
||||
|
||||
println(x)
|
||||
rx1 := map_to_array_int_kv(x)
|
||||
println(rx1)
|
||||
assert rx1[0].a? == 0
|
||||
assert rx1[0].b?.a? == 'one'
|
||||
assert rx1[0].b?.b? == 1
|
||||
assert rx1[1].a? == 1
|
||||
assert rx1[1].b?.a? == 'two'
|
||||
assert rx1[1].b?.b? == 2
|
||||
|
||||
rx2 := map_to_array_int_kv_vk(x)
|
||||
println(rx2)
|
||||
assert rx2[0].a? == 0
|
||||
assert rx2[0].b?.a?.a? == 'one'
|
||||
assert rx2[0].b?.a?.b? == 1
|
||||
assert rx2[0].b?.b?.a? == 1
|
||||
assert rx2[0].b?.b?.b? == 'one'
|
||||
assert rx2[1].a? == 1
|
||||
assert rx2[1].b?.a?.a? == 'two'
|
||||
assert rx2[1].b?.a?.b? == 2
|
||||
assert rx2[1].b?.b?.a? == 2
|
||||
assert rx2[1].b?.b?.b? == 'two'
|
||||
|
||||
println(y)
|
||||
ry1 := map_to_array_int_kv(y)
|
||||
println(ry1)
|
||||
assert ry1[0].a? == 0
|
||||
assert ry1[0].b?.a? == 3
|
||||
assert ry1[0].b?.b? == 'three'
|
||||
assert ry1[1].a? == 1
|
||||
assert ry1[1].b?.a? == 4
|
||||
assert ry1[1].b?.b? == 'four'
|
||||
|
||||
ry2 := map_to_array_int_kv_vk(y)
|
||||
println(ry2)
|
||||
assert ry2[0].a? == 0
|
||||
assert ry2[0].b?.a?.a? == 3
|
||||
assert ry2[0].b?.a?.b? == 'three'
|
||||
assert ry2[0].b?.b?.a? == 'three'
|
||||
assert ry2[0].b?.b?.b? == 3
|
||||
assert ry2[1].a? == 1
|
||||
assert ry2[1].b?.a?.a? == 4
|
||||
assert ry2[1].b?.a?.b? == 'four'
|
||||
assert ry2[1].b?.b?.a? == 'four'
|
||||
assert ry2[1].b?.b?.b? == 4
|
||||
|
||||
zx1 := []Tuple2[int, Tuple2[string, int]]{}
|
||||
println(typeof(zx1).name)
|
||||
println(typeof(rx1).name)
|
||||
zx2 := []Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]{}
|
||||
println(typeof(zx2).name)
|
||||
println(typeof(rx2).name)
|
||||
assert typeof(zx1).name == '[]Tuple2[int, Tuple2[string, int]]'
|
||||
assert typeof(zx2).name == '[]Tuple2[int, Tuple2[Tuple2[string, int], Tuple2[int, string]]]'
|
||||
assert typeof(zx1).name == typeof(rx1).name
|
||||
assert typeof(zx2).name == typeof(rx2).name
|
||||
}
|
Loading…
Reference in New Issue
Block a user