From 5adfc55b82c822142089aae0afb9c27c8ec4a082 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 5 May 2025 02:41:00 -0300 Subject: [PATCH] cgen: fix codegen for anon option fn struct field init (fix #24392) (#24400) --- vlib/v/gen/c/cgen.v | 5 ++ vlib/v/gen/c/struct.v | 11 +++-- .../options/option_fn_struct_init_test.v | 47 +++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/options/option_fn_struct_init_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 65f376af9..0638fb2b3 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2295,6 +2295,7 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T g.writeln('${g.styp(ret_typ)} ${tmp_var};') } mut expr_is_fixed_array_var := false + mut fn_option_clone := false if ret_typ_is_option { if expr_typ_is_option && expr in [ast.StructInit, ast.ArrayInit, ast.MapInit] { 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 g.write('(') g.write_fn_ptr_decl(&final_ret_sym.info, '') g.write(')') + fn_option_clone = expr is ast.SelectorExpr && expr_typ.has_flag(.option) } } } @@ -2339,6 +2341,9 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T g.write('_result_ok(&(${styp}[]) { ') } g.expr_with_cast(expr, expr_typ, ret_typ) + if fn_option_clone { + g.write('.data') + } if ret_typ_is_option { if simple_assign { g.writeln(';') diff --git a/vlib/v/gen/c/struct.v b/vlib/v/gen/c/struct.v index e8081664c..b51dfd2e4 100644 --- a/vlib/v/gen/c/struct.v +++ b/vlib/v/gen/c/struct.v @@ -742,21 +742,21 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type, field_unwrap_sym.info.size) } else { - g.struct_init_field_default(field_unwrap_typ, sfield) + g.struct_init_field_default(field_unwrap_typ, sfield, field_unwrap_sym) } } else { - g.struct_init_field_default(field_unwrap_typ, sfield) + g.struct_init_field_default(field_unwrap_typ, sfield, field_unwrap_sym) } } } else { - g.struct_init_field_default(field_unwrap_typ, sfield) + g.struct_init_field_default(field_unwrap_typ, sfield, field_unwrap_sym) } g.inside_cast_in_heap = inside_cast_in_heap // restore value for further struct inits } } -fn (mut g Gen) struct_init_field_default(field_unwrap_typ ast.Type, sfield &ast.StructInitField) { +fn (mut g Gen) struct_init_field_default(field_unwrap_typ ast.Type, sfield &ast.StructInitField, field_unwrap_sym ast.TypeSymbol) { if field_unwrap_typ != ast.voidptr_type && field_unwrap_typ != ast.nil_type && (sfield.expected_type.is_ptr() && !sfield.expected_type.has_flag(.shared_f)) && !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. g.expr_with_opt(sfield.expr, field_unwrap_typ, sfield.expected_type) } else if sfield.expr is ast.LambdaExpr && sfield.expected_type.has_flag(.option) { g.expr_opt_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type) + } else if field_unwrap_sym.kind == .function && sfield.expected_type.has_flag(.option) { + tmp_out_var := g.new_tmp_var() + g.expr_with_tmp_var(sfield.expr, field_unwrap_typ, sfield.expected_type, tmp_out_var) } else { g.left_is_opt = true g.expr_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type) diff --git a/vlib/v/tests/options/option_fn_struct_init_test.v b/vlib/v/tests/options/option_fn_struct_init_test.v new file mode 100644 index 000000000..55613c898 --- /dev/null +++ b/vlib/v/tests/options/option_fn_struct_init_test.v @@ -0,0 +1,47 @@ +type Baz = Foo + +@[heap] +struct Foo { + a int = 123 + b string = 'b' + cb ?fn (&Foo) +} + +@[heap] +struct Bar { + a int = 321 + b string = 'a' + cb ?fn (&Baz) +} + +fn g(a Foo) Foo { + return a +} + +fn t(a Bar) Foo { + return g(a: 123, b: 'foo', cb: a.cb) +} + +fn test_main() { + a := Foo{ + cb: none + } + + b := Foo{ + cb: fn (a &Foo) { + } + } + + w := Bar{ + cb: b.cb + } + + z := Bar{ + cb: a.cb + } + + t(a: 1, cb: a.cb) + t(a: 2, cb: b.cb) + t(a: 3, cb: w.cb) + t(a: 4, cb: z.cb) +} -- 2.39.5