From d661e4b9f461baec390e01f1ac028f337591d6ac Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 9 Sep 2025 19:16:46 -0300 Subject: [PATCH] fix --- cmd/tools/vast/vast.v | 1 + vlib/v/ast/ast.v | 1 + vlib/v/checker/fn.v | 1 + vlib/v/gen/c/fn.v | 16 ++++++++++++-- vlib/v/markused/walker.v | 3 +++ .../v/tests/options/option_fn_variadic_test.v | 21 +++++++++++++++++++ 6 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/options/option_fn_variadic_test.v diff --git a/cmd/tools/vast/vast.v b/cmd/tools/vast/vast.v index d38a95accb..87c674f7ab 100644 --- a/cmd/tools/vast/vast.v +++ b/cmd/tools/vast/vast.v @@ -1613,6 +1613,7 @@ fn (t Tree) call_expr(node ast.CallExpr) &Node { obj.add_terse('is_ctor_new', t.bool_node(node.is_ctor_new)) obj.add_terse('is_return_used', t.bool_node(node.is_return_used)) obj.add_terse('is_static_method', t.bool_node(node.is_static_method)) + obj.add_terse('is_variadic', t.bool_node(node.is_variadic)) obj.add('should_be_skipped', t.bool_node(node.should_be_skipped)) obj.add_terse('free_receiver', t.bool_node(node.free_receiver)) obj.add('scope', t.number_node(int(node.scope))) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index cdf72c96f7..69a29286c0 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -830,6 +830,7 @@ pub mut: is_ctor_new bool // if JS ctor calls requires `new` before call, marked as `[use_new]` in V is_file_translated bool // true, when the file it resides in is `@[translated]` is_static_method bool // it is a static method call + is_variadic bool args []CallArg expected_arg_types []Type comptime_ret_val bool diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 12b2d8a357..ea7c1f1805 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -2906,6 +2906,7 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) ! min_required_params-- } if f.is_variadic { + node.is_variadic = f.is_variadic min_required_params-- c.markused_array_method(!c.is_builtin_mod, '') } else { diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index f371e032ea..07d39bd82b 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2369,8 +2369,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) { } } // only v variadic, C variadic args will be appended like normal args - is_variadic := expected_types.len > 0 && expected_types.last().has_flag(.variadic) - && node.language == .v + is_variadic := node.language == .v && node.is_variadic mut already_decomposed := false for i, arg in args { if is_variadic && i == expected_types.len - 1 { @@ -2539,6 +2538,14 @@ fn (mut g Gen) call_args(node ast.CallExpr) { false) } else { noscan := g.check_noscan(arr_info.elem_type) + is_option := arr_info.elem_type.has_flag(.option) + tmp_var := if is_option { g.new_tmp_var() } else { '' } + base_type := g.base_type(varg_type) + tmp := if is_option { g.go_before_last_stmt() } else { '' } + if is_option { + g.writeln('${g.styp(varg_type)} ${tmp_var};') + g.write('_option_ok((${base_type}[]) {') + } g.write('new_array_from_c_array${noscan}(${variadic_count}, ${variadic_count}, sizeof(${elem_type}), _MOV((${elem_type}[${variadic_count}]){') for j in arg_nr .. args.len { g.ref_or_deref_arg(args[j], arr_info.elem_type, node.language, @@ -2548,6 +2555,11 @@ fn (mut g Gen) call_args(node ast.CallExpr) { } } g.write('}))') + if is_option { + g.writeln(' }, (${option_name}*)&${tmp_var}, sizeof(${base_type}));') + g.write(tmp) + g.write(tmp_var) + } } } } else { diff --git a/vlib/v/markused/walker.v b/vlib/v/markused/walker.v index ecbf77fe99..8349fae1cc 100644 --- a/vlib/v/markused/walker.v +++ b/vlib/v/markused/walker.v @@ -944,6 +944,9 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) { for arg in node.args { w.expr(arg.expr) } + if node.is_variadic && node.expected_arg_types.last().has_flag(.option) { + w.used_option++ + } for concrete_type in node.concrete_types { w.mark_by_type(concrete_type) } diff --git a/vlib/v/tests/options/option_fn_variadic_test.v b/vlib/v/tests/options/option_fn_variadic_test.v new file mode 100644 index 0000000000..f2671fa2fd --- /dev/null +++ b/vlib/v/tests/options/option_fn_variadic_test.v @@ -0,0 +1,21 @@ +struct Empty { +} + +type Elem = int | Empty + +fn new_elems(elems ...??int) []Elem { + mut out := []Elem{} + for elem in elems { + if elem == none { + out << Empty{} + } else { + out << elem + } + } + return out +} + +fn test_main() { + elems := new_elems(0, none, 2) + assert '${elems}' == '[Elem(0), Elem(Empty{}), Elem(2)]' +}