From 149cbba39b60796bc0cbc5e4f6f08471ebf2fc21 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 14 Apr 2024 11:52:12 -0300 Subject: [PATCH] cgen: fix `none` passed to a generic option cast expression (fix #21215) (#21276) --- vlib/v/gen/c/assign.v | 8 ++++-- vlib/v/tests/option_generic_cast_none_test.v | 27 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/option_generic_cast_none_test.v diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index f17e603524ee95..310de68b41deb7 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -71,8 +71,12 @@ fn (mut g Gen) expr_opt_with_cast(expr ast.Expr, expr_typ ast.Type, ret_typ ast. styp := g.base_type(ret_typ) decl_styp := g.typ(ret_typ).replace('*', '_ptr') g.writeln('${decl_styp} ${past.tmp_var};') - g.write('_option_ok(&(${styp}[]) {') - + is_none := expr is ast.CastExpr && expr.expr is ast.None + if is_none { + g.write('_option_none(&(${styp}[]) {') + } else { + 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) diff --git a/vlib/v/tests/option_generic_cast_none_test.v b/vlib/v/tests/option_generic_cast_none_test.v new file mode 100644 index 00000000000000..4b8cffd02a30a0 --- /dev/null +++ b/vlib/v/tests/option_generic_cast_none_test.v @@ -0,0 +1,27 @@ +pub type MyFn[T] = fn (mut my_state T) + +fn higher_order_fn[T](initial_state T, maybe_callback ?MyFn[T]) State { + mut my_state := initial_state + if callback := maybe_callback { + callback[T](mut my_state) + callback[T](mut my_state) + } + return my_state +} + +pub struct State { +mut: + x int +} + +fn handler(mut my_state State) { + my_state.x += 1 +} + +fn test_main() { + mut state := State{} + state = higher_order_fn[State](state, ?MyFn[State](handler)) + state = higher_order_fn[State](state, ?MyFn[State](none)) + state = higher_order_fn[State](state, handler) + assert state.x == 4 +}