cgen: auto cast sum type in array init. fixes #6907

pull/7038/head^2
joe-conigliaro 2020-12-01 20:03:45 +11:00
parent fe0ded9a91
commit 34e124d5f7
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
4 changed files with 36 additions and 9 deletions

View File

@ -825,6 +825,7 @@ pub:
has_cap bool
has_default bool
pub mut:
expr_types []table.Type // [Dog, Cat] // also used for interface_types
is_interface bool // array of interfaces e.g. `[]Animal` `[Dog{}, Cat{}]`
interface_types []table.Type // [Dog, Cat]
interface_type table.Type // Animal

View File

@ -2353,8 +2353,6 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
if array_init.exprs.len > 0 && array_init.elem_type == table.void_type {
mut expected_value_type := table.void_type
mut expecting_interface_array := false
cap := array_init.exprs.len
mut interface_types := []table.Type{cap: cap}
if c.expected_type != 0 {
expected_value_type = c.table.value_type(c.expected_type)
if c.table.get_type_symbol(expected_value_type).kind == .interface_ {
@ -2372,12 +2370,13 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
// }
for i, expr in array_init.exprs {
typ := c.expr(expr)
array_init.expr_types << typ
// The first element's type
if expecting_interface_array {
if i == 0 {
elem_type = expected_value_type
c.expected_type = elem_type
}
interface_types << typ
continue
}
// The first element's type
@ -2390,9 +2389,6 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
c.error('invalid array element: $err', expr.position())
}
}
if expecting_interface_array {
array_init.interface_types = interface_types
}
if array_init.is_fixed {
idx := c.table.find_or_register_array_fixed(elem_type, array_init.exprs.len,
1)

View File

@ -5844,11 +5844,11 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
}
for i, expr in it.exprs {
if it.is_interface {
// sym := g.table.get_type_symbol(it.interface_types[i])
// sym := g.table.get_type_symbol(it.expr_types[i])
// isym := g.table.get_type_symbol(it.interface_type)
g.interface_call(it.interface_types[i], it.interface_type)
g.interface_call(it.expr_types[i], it.interface_type)
}
g.expr(expr)
g.expr_with_cast(expr, it.expr_types[i], it.elem_type)
if it.is_interface {
g.write(')')
}

View File

@ -194,3 +194,33 @@ fn test_array_init_direct_call() {
assert []int{len: 2, init: 0}.len == 2
assert []int{len: 3, init: 1}.map(it*2) == [2,2,2]
}
// test array init with sumtype
type Alphabet = Abc | Xyz
struct Abc {
val int
}
struct Xyz {
val int
}
fn test_array_init_with_sumtype () {
a := [Alphabet(Abc{1}), Xyz{2}]
a0 := a[0]
a1 := a[1]
match a0 {
Abc {
assert a0.val == 1
}
else {
assert false
}
}
match a1 {
Xyz {
assert a1.val == 2
}
else {
assert false
}
}
}