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:
parent
b4f0bb247d
commit
2597efa7f6
@ -70,7 +70,7 @@ fn (mut g Gen) expr_opt_with_cast(expr ast.Expr, expr_typ ast.Type, ret_typ ast.
|
||||
} else {
|
||||
old_inside_opt_or_res := g.inside_opt_or_res
|
||||
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.writeln(' }, (${option_name}*)(&${tmp_var}), sizeof(${styp}));')
|
||||
|
@ -2260,8 +2260,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
||||
return
|
||||
}
|
||||
if got_sym.info !is ast.Interface && exp_sym.info is ast.Interface
|
||||
&& got_type.idx() != expected_type.idx() && !expected_type.has_flag(.option)
|
||||
&& !expected_type.has_flag(.result) {
|
||||
&& got_type.idx() != expected_type.idx() && !expected_type.has_flag(.result) {
|
||||
if expr is ast.StructInit && !got_type.is_ptr() {
|
||||
g.inside_cast_in_heap++
|
||||
got_styp := g.cc_type(got_type.ref(), true)
|
||||
|
@ -336,12 +336,21 @@ fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
|
||||
g.write('.${field_name} = ')
|
||||
if field.has_default_expr {
|
||||
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
|
||||
}
|
||||
|
||||
if (field.typ.has_flag(.option) && !field.default_expr_typ.has_flag(.option))
|
||||
|| (field.typ.has_flag(.result) && !field.default_expr_typ.has_flag(.result)) {
|
||||
if field.typ.has_flag(.option) {
|
||||
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()
|
||||
g.expr_with_tmp_var(field.default_expr, field.default_expr_typ, field.typ,
|
||||
tmp_var)
|
||||
@ -538,10 +547,9 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
|
||||
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)) {
|
||||
tmp_var := g.new_tmp_var()
|
||||
g.expr_with_tmp_var(sfield.expr, sfield.typ, sfield.expected_type, tmp_var)
|
||||
g.expr_with_opt(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
} else {
|
||||
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
}
|
||||
|
18
vlib/v/tests/option_struct_init_interface_test.v
Normal file
18
vlib/v/tests/option_struct_init_interface_test.v
Normal 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
|
||||
}
|
19
vlib/v/tests/option_struct_init_with_opt_test.v
Normal file
19
vlib/v/tests/option_struct_init_with_opt_test.v
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user