1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix struct initialization with option value (#17539)

This commit is contained in:
Felipe Pena 2023-03-07 17:53:56 -03:00 committed by GitHub
parent b4f0bb247d
commit 2597efa7f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 9 deletions

View File

@ -70,7 +70,7 @@ fn (mut g Gen) expr_opt_with_cast(expr ast.Expr, expr_typ ast.Type, ret_typ ast.
} else { } else {
old_inside_opt_or_res := g.inside_opt_or_res old_inside_opt_or_res := g.inside_opt_or_res
g.inside_opt_or_res = false g.inside_opt_or_res = false
g.expr(expr) g.expr_with_cast(expr, expr_typ, ret_typ)
g.inside_opt_or_res = old_inside_opt_or_res g.inside_opt_or_res = old_inside_opt_or_res
} }
g.writeln(' }, (${option_name}*)(&${tmp_var}), sizeof(${styp}));') g.writeln(' }, (${option_name}*)(&${tmp_var}), sizeof(${styp}));')

View File

@ -2260,8 +2260,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
return return
} }
if got_sym.info !is ast.Interface && exp_sym.info is ast.Interface if got_sym.info !is ast.Interface && exp_sym.info is ast.Interface
&& got_type.idx() != expected_type.idx() && !expected_type.has_flag(.option) && got_type.idx() != expected_type.idx() && !expected_type.has_flag(.result) {
&& !expected_type.has_flag(.result) {
if expr is ast.StructInit && !got_type.is_ptr() { if expr is ast.StructInit && !got_type.is_ptr() {
g.inside_cast_in_heap++ g.inside_cast_in_heap++
got_styp := g.cc_type(got_type.ref(), true) got_styp := g.cc_type(got_type.ref(), true)

View File

@ -336,12 +336,21 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
g.write('.${field_name} = ') g.write('.${field_name} = ')
if field.has_default_expr { if field.has_default_expr {
if sym.kind in [.sum_type, .interface_] { if sym.kind in [.sum_type, .interface_] {
g.expr_with_cast(field.default_expr, field.default_expr_typ, field.typ) if field.typ.has_flag(.option) {
g.expr_opt_with_cast(field.default_expr, field.default_expr_typ.set_flag(.option),
field.typ)
} else {
g.expr_with_cast(field.default_expr, field.default_expr_typ, field.typ)
}
return true return true
} }
if (field.typ.has_flag(.option) && !field.default_expr_typ.has_flag(.option)) if field.typ.has_flag(.option) {
|| (field.typ.has_flag(.result) && !field.default_expr_typ.has_flag(.result)) { tmp_var := g.new_tmp_var()
g.expr_with_tmp_var(field.default_expr, field.default_expr_typ, field.typ,
tmp_var)
return true
} else if field.typ.has_flag(.result) && !field.default_expr_typ.has_flag(.result) {
tmp_var := g.new_tmp_var() tmp_var := g.new_tmp_var()
g.expr_with_tmp_var(field.default_expr, field.default_expr_typ, field.typ, g.expr_with_tmp_var(field.default_expr, field.default_expr_typ, field.typ,
tmp_var) tmp_var)
@ -538,10 +547,9 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
g.write('/* autoref */&') g.write('/* autoref */&')
} }
if (sfield.expected_type.has_flag(.option) && !sfield.typ.has_flag(.option)) if sfield.expected_type.has_flag(.option)
|| (sfield.expected_type.has_flag(.result) && !sfield.typ.has_flag(.result)) { || (sfield.expected_type.has_flag(.result) && !sfield.typ.has_flag(.result)) {
tmp_var := g.new_tmp_var() g.expr_with_opt(sfield.expr, sfield.typ, sfield.expected_type)
g.expr_with_tmp_var(sfield.expr, sfield.typ, sfield.expected_type, tmp_var)
} else { } else {
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type) g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
} }

View File

@ -0,0 +1,18 @@
interface IPerson {
name string
age int
}
struct PersonImpl {
name string
age int
}
struct Person {
other ?IPerson = PersonImpl{}
}
fn test_main() {
a := Person{}
assert a.other != none
}

View File

@ -0,0 +1,19 @@
struct Foo {
x ?string
}
fn test_main() {
x := ?string('hi')
foo := Foo{
x: x
}
assert foo.x? == 'hi'
}
fn test_none() {
x := ?string(none)
foo := Foo{
x: x
}
assert foo.x == none
}