From daeb548e7b284cf4423362b4a640355845d5e532 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 19 Oct 2024 21:51:02 -0300 Subject: [PATCH] cgen: fix codegen for if with struct init that contains option type (fix #22577) (#22578) --- vlib/v/ast/types.v | 1 + vlib/v/gen/c/if.v | 2 ++ vlib/v/parser/struct.v | 3 ++ .../options/option_struct_init_on_if_test.v | 36 +++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 vlib/v/tests/options/option_struct_init_on_if_test.v diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 271a6fa89..52f951780 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -169,6 +169,7 @@ pub mut: is_minify bool is_anon bool is_generic bool + has_option bool // contains any option field generic_types []Type concrete_types []Type parent_type Type diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index e89cde29e..048eb57ee 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -156,6 +156,8 @@ fn (mut g Gen) need_tmp_var_in_expr(expr ast.Expr) bool { return true } } + sym := g.table.sym(expr.typ) + return sym.info is ast.Struct && sym.info.has_option } else {} } diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index d2d564904..b8ed12afb 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -97,6 +97,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { mut implements_types := []ast.TypeNode{cap: 3} // ast.void_type mut last_line := p.prev_tok.pos().line_nr + 1 mut end_comments := []ast.Comment{} + mut has_option := false if !no_body { if p.tok.kind == .key_implements { is_implements = true @@ -253,6 +254,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { field_pos = field_start_pos.extend(p.prev_tok.pos()) if typ.has_option_or_result() { option_pos = p.peek_token(-2).pos() + has_option = true } } // Comments after type (same line) @@ -372,6 +374,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { generic_types: generic_types attrs: attrs is_anon: is_anon + has_option: has_option } is_pub: is_pub } diff --git a/vlib/v/tests/options/option_struct_init_on_if_test.v b/vlib/v/tests/options/option_struct_init_on_if_test.v new file mode 100644 index 000000000..76b691f1a --- /dev/null +++ b/vlib/v/tests/options/option_struct_init_on_if_test.v @@ -0,0 +1,36 @@ +struct Number { + natural ?string + integer string +} + +fn number(n int) Number { + return if n >= 0 { // a single return here + Number{ + natural: '${n}' + integer: '${n}' + } + } else { + Number{ + integer: '${n}' + } + } +} + +fn test_main() { + mut ret := []Number{} + for n in [1, 0, -1] { + ret << number(n) + } + assert ret[0] == Number{ + natural: ?string('1') + integer: '1' + } + assert ret[1] == Number{ + natural: ?string('0') + integer: '0' + } + assert ret[2] == Number{ + natural: ?string(none) + integer: '-1' + } +} -- 2.39.5