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_cap bool
has_default bool has_default bool
pub mut: pub mut:
expr_types []table.Type // [Dog, Cat] // also used for interface_types
is_interface bool // array of interfaces e.g. `[]Animal` `[Dog{}, Cat{}]` is_interface bool // array of interfaces e.g. `[]Animal` `[Dog{}, Cat{}]`
interface_types []table.Type // [Dog, Cat] interface_types []table.Type // [Dog, Cat]
interface_type table.Type // Animal 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 { if array_init.exprs.len > 0 && array_init.elem_type == table.void_type {
mut expected_value_type := table.void_type mut expected_value_type := table.void_type
mut expecting_interface_array := false mut expecting_interface_array := false
cap := array_init.exprs.len
mut interface_types := []table.Type{cap: cap}
if c.expected_type != 0 { if c.expected_type != 0 {
expected_value_type = c.table.value_type(c.expected_type) expected_value_type = c.table.value_type(c.expected_type)
if c.table.get_type_symbol(expected_value_type).kind == .interface_ { 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 { for i, expr in array_init.exprs {
typ := c.expr(expr) typ := c.expr(expr)
array_init.expr_types << typ
// The first element's type
if expecting_interface_array { if expecting_interface_array {
if i == 0 { if i == 0 {
elem_type = expected_value_type elem_type = expected_value_type
c.expected_type = elem_type c.expected_type = elem_type
} }
interface_types << typ
continue continue
} }
// The first element's type // 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()) c.error('invalid array element: $err', expr.position())
} }
} }
if expecting_interface_array {
array_init.interface_types = interface_types
}
if array_init.is_fixed { if array_init.is_fixed {
idx := c.table.find_or_register_array_fixed(elem_type, array_init.exprs.len, idx := c.table.find_or_register_array_fixed(elem_type, array_init.exprs.len,
1) 1)

View File

@ -5844,11 +5844,11 @@ fn (mut g Gen) array_init(it ast.ArrayInit) {
} }
for i, expr in it.exprs { for i, expr in it.exprs {
if it.is_interface { 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) // 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 { if it.is_interface {
g.write(')') 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: 2, init: 0}.len == 2
assert []int{len: 3, init: 1}.map(it*2) == [2,2,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
}
}
}