From 81b4a64f184e9c1579d0d5b1d9164615682339b9 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 7 Jan 2025 04:43:07 -0300 Subject: [PATCH] cgen: fix generic alias option assigning (fix #23382) (#23393) --- vlib/v/gen/c/assign.v | 32 ++++++++++--------- vlib/v/gen/c/cgen.v | 2 +- vlib/v/gen/c/fn.v | 4 +-- .../tests/options/option_generic_alias_test.v | 17 ++++++++++ 4 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 vlib/v/tests/options/option_generic_alias_test.v diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 88fc9abb9..3541b54a5 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -55,7 +55,7 @@ fn (mut g Gen) expr_with_opt_or_block(expr ast.Expr, expr_typ ast.Type, var_expr } // expr_opt_with_alias handles conversion from different option alias type name -fn (mut g Gen) expr_opt_with_alias(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type, tmp_var string) string { +fn (mut g Gen) expr_opt_with_alias(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type) string { styp := g.base_type(ret_typ) line := g.go_before_last_stmt().trim_space() @@ -63,21 +63,23 @@ fn (mut g Gen) expr_opt_with_alias(expr ast.Expr, expr_typ ast.Type, ret_typ ast ret_var := g.new_tmp_var() ret_styp := g.styp(ret_typ).replace('*', '_ptr') - g.writeln('${ret_styp} ${ret_var} = {0};') + g.writeln('${ret_styp} ${ret_var} = {.state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION}};') - g.write('_option_clone((${option_name}*)') - has_addr := expr !in [ast.Ident, ast.SelectorExpr] - if has_addr { - expr_styp := g.styp(expr_typ).replace('*', '_ptr') - g.write('ADDR(${expr_styp}, ') - } else { - g.write('&') - } - g.expr(expr) - if has_addr { - g.write(')') + if expr !is ast.None { + g.write('_option_clone((${option_name}*)') + has_addr := expr !in [ast.Ident, ast.SelectorExpr] + if has_addr { + expr_styp := g.styp(expr_typ).replace('*', '_ptr') + g.write('ADDR(${expr_styp}, ') + } else { + g.write('&') + } + g.expr(expr) + if has_addr { + g.write(')') + } + g.writeln(', (${option_name}*)&${ret_var}, sizeof(${styp}));') } - g.writeln(', (${option_name}*)&${ret_var}, sizeof(${styp}));') g.write(line) if g.inside_return { g.write(' ') @@ -97,7 +99,7 @@ fn (mut g Gen) expr_opt_with_cast(expr ast.Expr, expr_typ ast.Type, ret_typ ast. return g.expr_with_opt(expr, expr_typ, ret_typ) } else { if expr is ast.CallExpr && expr.return_type.has_flag(.option) { - return g.expr_opt_with_alias(expr, expr_typ, ret_typ, '') + return g.expr_opt_with_alias(expr, expr_typ, ret_typ) } else { past := g.past_tmp_var_new() defer { diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 03e560de8..879e81406 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5227,7 +5227,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { g.writeln('_option_ok(&(${g.styp(parent_type)}[]) { ${tmp_var2} }, (${option_name}*)&${tmp_var}, sizeof(${g.styp(parent_type)}));') g.write2(cur_stmt, tmp_var) } else if node.expr_type.has_flag(.option) { - g.expr_opt_with_cast(node.expr, expr_type, node.typ) + g.expr_opt_with_alias(node.expr, expr_type, node.typ) } else { g.expr_with_opt(node.expr, expr_type, node.typ) } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 72fb39c69..8a3019fcc 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2771,8 +2771,8 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as g.write('->val') return } else if expected_type.has_flag(.option) { - if arg_sym.info is ast.Alias && expected_type != arg_typ { - g.expr_opt_with_alias(arg.expr, arg_typ, expected_type, '') + if (arg_sym.info is ast.Alias || exp_sym.info is ast.Alias) && expected_type != arg_typ { + g.expr_opt_with_alias(arg.expr, arg_typ, expected_type) } else { g.expr_with_opt(arg.expr, arg_typ, expected_type) } diff --git a/vlib/v/tests/options/option_generic_alias_test.v b/vlib/v/tests/options/option_generic_alias_test.v new file mode 100644 index 000000000..a4c388014 --- /dev/null +++ b/vlib/v/tests/options/option_generic_alias_test.v @@ -0,0 +1,17 @@ +type I64 = i64 + +fn test[T](a ?T) ?T { + w := ?T(a) + return w +} + +fn test_main() { + a := ?i64(123) + b := test[I64](a) + println(b) + assert b != none + assert b? == 123 + c := test[I64](none) + println(c) + assert c == none +} -- 2.39.5