From 1e86b653d34c41c51a4c2edfc6b3ad19a8bcc4bc Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 21 Apr 2026 06:29:47 +0300 Subject: [PATCH] cgen: fix v-ui binding issues with sumtype ptr cast payload (fixes #22886) --- vlib/v/gen/c/cgen.v | 13 ++++++++- .../sumtype_ptr_cast_uses_payload.c.must_have | 1 + .../testdata/sumtype_ptr_cast_uses_payload.vv | 28 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.c.must_have create mode 100644 vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.vv diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 4d12ffd64..a0b22dd23 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -8611,6 +8611,9 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { g.write(')') return } + use_dynamic_ptr_payload := node_typ.is_ptr() && expr_type.is_ptr() + && final_expr_sym.kind == .sum_type + && final_sym.kind !in [.sum_type, .interface] && final_sym.language == .c if (g.pref.translated || g.file.is_translated) && sym.kind == .function { // TODO: handle the type in fn casts, not just exprs /* @@ -8710,7 +8713,15 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { expr_styp := g.styp(node.expr_type) g.write('(${expr_styp})') } - g.expr(node.expr) + if use_dynamic_ptr_payload { + // C pointer casts from sum types/interfaces must target the stored payload pointer, + // not the wrapper address itself. + g.write('(*((void**)(') + g.expr(node.expr) + g.write(')))') + } else { + g.expr(node.expr) + } g.inside_assign_fn_var = old_inside_assign_fn_var g.inside_cast = old_inside_cast g.write('))') diff --git a/vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.c.must_have b/vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.c.must_have new file mode 100644 index 000000000..025d08faa --- /dev/null +++ b/vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.c.must_have @@ -0,0 +1 @@ +uiConsume(((uiControl*)((*((void**)(c)))))); diff --git a/vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.vv b/vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.vv new file mode 100644 index 000000000..677bd209e --- /dev/null +++ b/vlib/v/gen/c/testdata/sumtype_ptr_cast_uses_payload.vv @@ -0,0 +1,28 @@ +module main + +@[typedef] +struct C.uiControl {} + +@[typedef] +struct C.uiLabel {} + +@[typedef] +struct C.uiBox {} + +fn C.uiNewBox() &C.uiBox + +fn C.uiConsume(x &C.uiControl) + +type Control = C.uiLabel | C.uiBox + +@[unsafe] +fn use_control(c &Control) { + C.uiConsume(&C.uiControl(c)) +} + +fn main() { + box := C.uiNewBox() + unsafe { + use_control(box) + } +} -- 2.39.5