cgen: cast default struct field value to correct SumType/interface (#8619)
parent
e2ff26a066
commit
5abd49d9bc
|
@ -465,10 +465,14 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
|
|||
if field.has_default_expr {
|
||||
c.expected_type = field.typ
|
||||
field_expr_type := c.expr(field.default_expr)
|
||||
struct_sym.info.fields[i].default_expr_typ = field_expr_type
|
||||
c.check_expected(field_expr_type, field.typ) or {
|
||||
if !(sym.kind == .interface_
|
||||
&& c.type_implements(field_expr_type, field.typ, field.pos)) {
|
||||
c.error('incompatible initializer for field `$field.name`: $err',
|
||||
field.default_expr.position())
|
||||
}
|
||||
}
|
||||
// Check for unnecessary inits like ` = 0` and ` = ''`
|
||||
if field.typ.is_ptr() {
|
||||
continue
|
||||
|
|
|
@ -5074,8 +5074,14 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
|||
fn (mut g Gen) zero_struct_field(field table.Field) {
|
||||
field_name := c_name(field.name)
|
||||
g.write('.$field_name = ')
|
||||
sym := g.table.get_type_symbol(field.typ)
|
||||
defex := ast.fe2ex(field.default_expr)
|
||||
if field.has_default_expr {
|
||||
g.expr(ast.fe2ex(field.default_expr))
|
||||
if sym.kind in [.sum_type, .interface_] {
|
||||
g.expr_with_cast(defex, field.default_expr_typ, field.typ)
|
||||
return
|
||||
}
|
||||
g.expr(defex)
|
||||
} else {
|
||||
g.write(g.type_default(field.typ))
|
||||
}
|
||||
|
|
|
@ -694,6 +694,7 @@ pub mut:
|
|||
typ Type
|
||||
default_expr FExpr
|
||||
has_default_expr bool
|
||||
default_expr_typ Type
|
||||
default_val string
|
||||
attrs []Attr
|
||||
is_pub bool
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
struct Foo {
|
||||
x int
|
||||
}
|
||||
|
||||
interface FooBar {
|
||||
x int
|
||||
}
|
||||
|
||||
struct Abc {
|
||||
foobar FooBar = Foo { x: 123 }
|
||||
}
|
||||
|
||||
fn test_struct_field_default_value_interface_cast() {
|
||||
x := Abc{}
|
||||
assert x.foobar is Foo
|
||||
assert x.foobar.x == 123
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
struct Foo {
|
||||
x int
|
||||
}
|
||||
|
||||
struct Bar {}
|
||||
|
||||
type FooBar = Foo | Bar
|
||||
|
||||
struct Abc {
|
||||
foobar FooBar = Foo { x: 123 }
|
||||
}
|
||||
|
||||
fn test_struct_field_default_value_sumtype_cast() {
|
||||
x := Abc{}
|
||||
assert x.foobar is Foo
|
||||
assert (x.foobar as Foo).x == 123
|
||||
}
|
Loading…
Reference in New Issue