Skip to content

Commit

Permalink
cgen: fix generic alias option assigning (fix #23382) (#23393)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Jan 7, 2025
1 parent 0c9d076 commit 81b4a64
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 18 deletions.
32 changes: 17 additions & 15 deletions vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -55,29 +55,31 @@ 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()
g.empty_line = true

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(' ')
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
17 changes: 17 additions & 0 deletions vlib/v/tests/options/option_generic_alias_test.v
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 81b4a64

Please sign in to comment.