From 35ad110f48ae8d57e659c19a4056026e002aeae1 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 01:26:27 +0300 Subject: [PATCH] cgen: fix invalid memory access when smart casting an alias fntype (fixes #17799) --- vlib/v/gen/c/cgen.v | 11 ++++++++++- .../sumtype_alias_fntype_smartcast_test.v | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/sumtypes/sumtype_alias_fntype_smartcast_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 038fd8a6f..bc58dd2d1 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -7835,6 +7835,9 @@ fn (mut g Gen) ident(node ast.Ident) { for i, typ in smartcast_types { is_option_unwrap := i == 0 && is_option && typ == resolved_var.orig_type.clear_flag(.option) + smartcast_final_sym := g.table.final_sym(g.unwrap_generic(typ)) + sumtype_fn_value_smartcast := obj_sym.kind == .sum_type && !is_auto_heap + && smartcast_final_sym.info is ast.FnType && !is_option_unwrap g.write('(') if i == 0 && resolved_var.is_unwrapped && resolved_var.ct_type_var == .smartcast { @@ -7850,7 +7853,7 @@ fn (mut g Gen) ident(node ast.Ident) { styp := g.base_type(resolved_var.typ) g.write('*(${styp}*)') } - } else if !g.arg_no_auto_deref && !typ.is_ptr() { + } else if !g.arg_no_auto_deref && !sumtype_fn_value_smartcast { g.write('*') } } else if interface_var_needs_deref @@ -7869,6 +7872,9 @@ fn (mut g Gen) ident(node ast.Ident) { for i, typ in smartcast_types { is_option_unwrap := is_option && typ == resolved_var.typ.clear_flag(.option) cast_sym := g.table.sym(g.unwrap_generic(typ)) + final_cast_sym := g.table.final_sym(g.unwrap_generic(typ)) + sumtype_fn_value_smartcast := obj_sym.kind == .sum_type && !is_auto_heap + && final_cast_sym.info is ast.FnType && !is_option_unwrap if obj_sym.kind == .interface && cast_sym.kind == .interface { if cast_sym.cname != obj_sym.cname { ptr := '*'.repeat(resolved_var.typ.nr_muls()) @@ -7882,6 +7888,9 @@ fn (mut g Gen) ident(node ast.Ident) { g.write('${ptr}${node.name}') } } else { + if sumtype_fn_value_smartcast { + g.write('(${g.styp(typ)})') + } mut is_ptr := false if i == 0 { if resolved_var.is_inherited { diff --git a/vlib/v/tests/sumtypes/sumtype_alias_fntype_smartcast_test.v b/vlib/v/tests/sumtypes/sumtype_alias_fntype_smartcast_test.v new file mode 100644 index 000000000..679a8eb43 --- /dev/null +++ b/vlib/v/tests/sumtypes/sumtype_alias_fntype_smartcast_test.v @@ -0,0 +1,19 @@ +type FunString17799 = FnAlias17799 | string + +type FnAlias17799 = fn () string + +fn foo_bar_17799(foo FnAlias17799) string { + return foo() +} + +fn test_sumtype_alias_fntype_smartcast() { + fs := FunString17799(FnAlias17799(fn () string { + return 'bar' + })) + assert foo_bar_17799(fs as FnAlias17799) == 'bar' + if fs is FnAlias17799 { + assert foo_bar_17799(fs) == 'bar' + return + } + assert false +} -- 2.39.5