From 2d81ab2a365edd829341d7648607ba9ab18c01b6 Mon Sep 17 00:00:00 2001 From: CreeperFace <165158232+dy-tea@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:10:26 +0000 Subject: [PATCH] checker: allow cast from voidptr to sumtype in unsafe block (fix #25652) (#25657) --- vlib/v/checker/checker.v | 10 +++++++-- .../tests/sumtype_from_voidptr_err.out | 7 ++++++ .../checker/tests/sumtype_from_voidptr_err.vv | 15 +++++++++++++ .../sumtypes/sumtype_cast_from_voidptr_test.v | 22 +++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 vlib/v/checker/tests/sumtype_from_voidptr_err.out create mode 100644 vlib/v/checker/tests/sumtype_from_voidptr_err.vv create mode 100644 vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4dbd75d74..a52957c96 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3511,9 +3511,15 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { from_type = node.expr_type } if !c.table.sumtype_has_variant(to_type, from_type, false) { - ft := c.table.type_to_str(from_type) tt := c.table.type_to_str(to_type) - c.error('cannot cast `${ft}` to `${tt}`', node.pos) + if from_type == ast.voidptr_type_idx && to_type.is_ptr() { + if !c.inside_unsafe { + c.error('cannot cast voidptr to `${tt}` outside `unsafe`', node.pos) + } + } else { + ft := c.table.type_to_str(from_type) + c.error('cannot cast `${ft}` to `${tt}`', node.pos) + } } } else if mut to_sym.info is ast.Alias && !(final_to_sym.kind == .struct && final_to_is_ptr) { if (!c.check_types(from_type, to_sym.info.parent_type) && !(final_to_sym.is_int() diff --git a/vlib/v/checker/tests/sumtype_from_voidptr_err.out b/vlib/v/checker/tests/sumtype_from_voidptr_err.out new file mode 100644 index 000000000..b5b3b2c66 --- /dev/null +++ b/vlib/v/checker/tests/sumtype_from_voidptr_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/sumtype_from_voidptr_err.vv:13:11: error: cannot cast voidptr to `&Event` outside `unsafe` + 11 | fn main() { + 12 | some_ptr := voidptr(1234) + 13 | event := &Event(some_ptr) + | ~~~~~~~~~~~~~~~~ + 14 | _ = event + 15 | } diff --git a/vlib/v/checker/tests/sumtype_from_voidptr_err.vv b/vlib/v/checker/tests/sumtype_from_voidptr_err.vv new file mode 100644 index 000000000..173fa8fa6 --- /dev/null +++ b/vlib/v/checker/tests/sumtype_from_voidptr_err.vv @@ -0,0 +1,15 @@ +struct EventA { + a u32 +} + +struct EventB { + b u32 +} + +type Event = EventA | EventB + +fn main() { + some_ptr := voidptr(1234) + event := &Event(some_ptr) + _ = event +} diff --git a/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v b/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v new file mode 100644 index 000000000..5f716d233 --- /dev/null +++ b/vlib/v/tests/sumtypes/sumtype_cast_from_voidptr_test.v @@ -0,0 +1,22 @@ +struct EventA { + a u32 +} + +struct EventB { + b u32 +} + +type Event = EventA | EventB + +fn test_main() { + some_ptr := voidptr(&EventA{ + a: 1234 + }) + event := unsafe { &Event(some_ptr) } + + d1 := &EventA(event) + assert d1.a == 1234 + + d2 := &EventB(event) + assert d2.b == 1234 +} -- 2.39.5