cgen: cast default struct field value to correct SumType/interface (#8619)

pull/8637/head^2
Lukas Neubert 2021-02-08 16:33:05 +01:00 committed by GitHub
parent e2ff26a066
commit 5abd49d9bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 3 deletions

View File

@ -465,10 +465,14 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
if field.has_default_expr { if field.has_default_expr {
c.expected_type = field.typ c.expected_type = field.typ
field_expr_type := c.expr(field.default_expr) 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 { 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', c.error('incompatible initializer for field `$field.name`: $err',
field.default_expr.position()) field.default_expr.position())
} }
}
// Check for unnecessary inits like ` = 0` and ` = ''` // Check for unnecessary inits like ` = 0` and ` = ''`
if field.typ.is_ptr() { if field.typ.is_ptr() {
continue continue

View File

@ -5074,8 +5074,14 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
fn (mut g Gen) zero_struct_field(field table.Field) { fn (mut g Gen) zero_struct_field(field table.Field) {
field_name := c_name(field.name) field_name := c_name(field.name)
g.write('.$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 { 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 { } else {
g.write(g.type_default(field.typ)) g.write(g.type_default(field.typ))
} }

View File

@ -694,6 +694,7 @@ pub mut:
typ Type typ Type
default_expr FExpr default_expr FExpr
has_default_expr bool has_default_expr bool
default_expr_typ Type
default_val string default_val string
attrs []Attr attrs []Attr
is_pub bool is_pub bool

View File

@ -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
}

View File

@ -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
}