Skip to content

Commit

Permalink
cgen: fix codegen for option sumtype with option variant (fix #23653) (
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Feb 5, 2025
1 parent 424c453 commit 4c8c892
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
14 changes: 11 additions & 3 deletions vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,17 @@ fn (mut g Gen) expr_opt_with_cast(expr ast.Expr, expr_typ ast.Type, ret_typ ast.
g.write('_option_ok(&(${styp}[]) {')
}
if expr is ast.CastExpr && expr_typ.has_flag(.option) {
g.write('*((${g.base_type(expr_typ)}*)')
g.expr(expr)
g.write('.data)')
ret_sym := g.table.sym(ret_typ)
if ret_sym.kind == .sum_type {
exp_sym := g.table.sym(expr_typ)
fname := g.get_sumtype_casting_fn(expr_typ, ret_typ)
g.call_cfn_for_casting_expr(fname, expr, ret_typ.is_ptr(), ret_sym.cname,
expr_typ.is_ptr(), exp_sym.kind == .function, g.styp(expr_typ))
} else {
g.write('*((${g.base_type(expr_typ)}*)')
g.expr(expr)
g.write('.data)')
}
} else {
old_inside_opt_or_res := g.inside_opt_or_res
g.inside_opt_or_res = false
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 @@ -2585,7 +2585,7 @@ struct SumtypeCastingFn {

fn (mut g Gen) get_sumtype_casting_fn(got_ ast.Type, exp_ ast.Type) string {
mut got, exp := got_.idx_type(), exp_.idx_type()
i := int(got) | int(u32(exp) << 17) | int(u32(exp_.has_flag(.option)) << 16)
i := int(got) | int(u32(exp) << 18) | int(u32(exp_.has_flag(.option)) << 17) | int(u32(got_.has_flag(.option)) << 16)
exp_sym := g.table.sym(exp)
mut got_sym := g.table.sym(got)
cname := if exp == ast.int_type_idx {
Expand Down
12 changes: 12 additions & 0 deletions vlib/v/tests/options/option_sumtype_option_variant_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
type Any = ?int | string | ?string

fn test_main() {
b := ?Any(?string('bar'))
assert b?.str() == "Any(Option('bar'))"

c := ?Any(string('baz'))
assert c?.str() == "Any('baz')"

d := ?Any('baz')
assert d?.str() == "Any('baz')"
}

0 comments on commit 4c8c892

Please sign in to comment.