Skip to content

Commit 5adfc55

Browse files
authored
cgen: fix codegen for anon option fn struct field init (fix #24392) (#24400)
1 parent e60d928 commit 5adfc55

3 files changed

Lines changed: 59 additions & 4 deletions

File tree

‎vlib/v/gen/c/cgen.v‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,6 +2295,7 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
22952295
g.writeln('${g.styp(ret_typ)} ${tmp_var};')
22962296
}
22972297
mut expr_is_fixed_array_var := false
2298+
mut fn_option_clone := false
22982299
if ret_typ_is_option {
22992300
if expr_typ_is_option && expr in [ast.StructInit, ast.ArrayInit, ast.MapInit] {
23002301
simple_assign = expr is ast.StructInit
@@ -2328,6 +2329,7 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
23282329
g.write('(')
23292330
g.write_fn_ptr_decl(&final_ret_sym.info, '')
23302331
g.write(')')
2332+
fn_option_clone = expr is ast.SelectorExpr && expr_typ.has_flag(.option)
23312333
}
23322334
}
23332335
}
@@ -2339,6 +2341,9 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
23392341
g.write('_result_ok(&(${styp}[]) { ')
23402342
}
23412343
g.expr_with_cast(expr, expr_typ, ret_typ)
2344+
if fn_option_clone {
2345+
g.write('.data')
2346+
}
23422347
if ret_typ_is_option {
23432348
if simple_assign {
23442349
g.writeln(';')

‎vlib/v/gen/c/struct.v‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -742,21 +742,21 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
742742
g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type,
743743
field_unwrap_sym.info.size)
744744
} else {
745-
g.struct_init_field_default(field_unwrap_typ, sfield)
745+
g.struct_init_field_default(field_unwrap_typ, sfield, field_unwrap_sym)
746746
}
747747
}
748748
else {
749-
g.struct_init_field_default(field_unwrap_typ, sfield)
749+
g.struct_init_field_default(field_unwrap_typ, sfield, field_unwrap_sym)
750750
}
751751
}
752752
} else {
753-
g.struct_init_field_default(field_unwrap_typ, sfield)
753+
g.struct_init_field_default(field_unwrap_typ, sfield, field_unwrap_sym)
754754
}
755755
g.inside_cast_in_heap = inside_cast_in_heap // restore value for further struct inits
756756
}
757757
}
758758

759-
fn (mut g Gen) struct_init_field_default(field_unwrap_typ ast.Type, sfield &ast.StructInitField) {
759+
fn (mut g Gen) struct_init_field_default(field_unwrap_typ ast.Type, sfield &ast.StructInitField, field_unwrap_sym ast.TypeSymbol) {
760760
if field_unwrap_typ != ast.voidptr_type && field_unwrap_typ != ast.nil_type
761761
&& (sfield.expected_type.is_ptr() && !sfield.expected_type.has_flag(.shared_f))
762762
&& !sfield.expected_type.has_flag(.option) && !field_unwrap_typ.is_any_kind_of_pointer()
@@ -769,6 +769,9 @@ fn (mut g Gen) struct_init_field_default(field_unwrap_typ ast.Type, sfield &ast.
769769
g.expr_with_opt(sfield.expr, field_unwrap_typ, sfield.expected_type)
770770
} else if sfield.expr is ast.LambdaExpr && sfield.expected_type.has_flag(.option) {
771771
g.expr_opt_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
772+
} else if field_unwrap_sym.kind == .function && sfield.expected_type.has_flag(.option) {
773+
tmp_out_var := g.new_tmp_var()
774+
g.expr_with_tmp_var(sfield.expr, field_unwrap_typ, sfield.expected_type, tmp_out_var)
772775
} else {
773776
g.left_is_opt = true
774777
g.expr_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
type Baz = Foo
2+
3+
@[heap]
4+
struct Foo {
5+
a int = 123
6+
b string = 'b'
7+
cb ?fn (&Foo)
8+
}
9+
10+
@[heap]
11+
struct Bar {
12+
a int = 321
13+
b string = 'a'
14+
cb ?fn (&Baz)
15+
}
16+
17+
fn g(a Foo) Foo {
18+
return a
19+
}
20+
21+
fn t(a Bar) Foo {
22+
return g(a: 123, b: 'foo', cb: a.cb)
23+
}
24+
25+
fn test_main() {
26+
a := Foo{
27+
cb: none
28+
}
29+
30+
b := Foo{
31+
cb: fn (a &Foo) {
32+
}
33+
}
34+
35+
w := Bar{
36+
cb: b.cb
37+
}
38+
39+
z := Bar{
40+
cb: a.cb
41+
}
42+
43+
t(a: 1, cb: a.cb)
44+
t(a: 2, cb: b.cb)
45+
t(a: 3, cb: w.cb)
46+
t(a: 4, cb: z.cb)
47+
}

0 commit comments

Comments
 (0)