From f357603d0c7986119960606f11e5e6bf59af64f2 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 26 Feb 2026 22:22:02 +0300 Subject: [PATCH] checker: fix arrays.sum([]) or {panic(err)} produces misleading error message (fixes #22859) --- vlib/v/checker/fn.v | 19 ++++++++++++++++--- ...mpty_arr_to_generic_param_sum_like_err.out | 13 +++++++++++++ ...empty_arr_to_generic_param_sum_like_err.vv | 17 +++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.out create mode 100644 vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 45a738c4a..0477fca56 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1548,6 +1548,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. node.pos) } mut has_decompose := false + mut has_unresolved_generic_param := false mut nr_multi_values := 0 for i, mut call_arg in node.args { if func.params.len == 0 { @@ -1672,7 +1673,8 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. if arg_typ_sym.kind == .none && !param.typ.has_flag(.option) { c.error('cannot use `none` as generic argument', call_arg.pos) } - c.check_unresolved_generic_param(node, call_arg) + has_unresolved_generic_param = c.check_unresolved_generic_param(node, call_arg) + || has_unresolved_generic_param } param_typ_sym := c.table.sym(param.typ) if func.is_variadic && arg_typ.has_flag(.variadic) && args_len - 1 > i { @@ -1946,6 +1948,10 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. } } } + if has_unresolved_generic_param { + node.return_type = func.return_type + return func.return_type + } if is_json_encode { // json.encode param is set voidptr, we should bound the proper type here node.expected_arg_types = [node.args[0].typ] @@ -2562,6 +2568,7 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool) return method.return_type } mut exp_arg_typ := ast.no_type // type of 1st arg for special builtin methods + mut has_unresolved_generic_param := false mut param_is_mut := false mut no_type_promotion := false if left_sym.info is ast.Chan { @@ -2706,7 +2713,8 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool) } } if exp_arg_typ.has_flag(.generic) { - c.check_unresolved_generic_param(node, arg) + has_unresolved_generic_param = c.check_unresolved_generic_param(node, arg) + || has_unresolved_generic_param method_concrete_types := if method_generic_names_len == rec_concrete_types.len { rec_concrete_types } else { @@ -2801,6 +2809,9 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool) arg.pos) } } + if has_unresolved_generic_param { + return method.return_type + } if method.is_unsafe && !c.inside_unsafe { if !c.pref.translated && !c.file.is_translated { c.warn('method `${left_sym.name}.${method_name}` must be called from an `unsafe` block', @@ -2891,11 +2902,13 @@ fn (mut c Checker) handle_generic_lambda_arg(node &ast.CallExpr, mut lambda ast. } } -fn (mut c Checker) check_unresolved_generic_param(node &ast.CallExpr, arg ast.CallArg) { +fn (mut c Checker) check_unresolved_generic_param(node &ast.CallExpr, arg ast.CallArg) bool { if node.raw_concrete_types.len == 0 && arg.expr is ast.ArrayInit && arg.expr.typ == ast.void_type { c.error('cannot use empty array as generic argument', arg.pos) + return true } + return false } fn (mut c Checker) spawn_expr(mut node ast.SpawnExpr) ast.Type { diff --git a/vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.out b/vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.out new file mode 100644 index 000000000..d675a3ea0 --- /dev/null +++ b/vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.out @@ -0,0 +1,13 @@ +vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.vv:15:11: error: cannot use empty array as generic argument + 13 | + 14 | fn main() { + 15 | sum_like([]) or { panic(err) } + | ~~ + 16 | arrays.sum([]) or { panic(err) } + 17 | } +vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.vv:16:13: error: cannot use empty array as generic argument + 14 | fn main() { + 15 | sum_like([]) or { panic(err) } + 16 | arrays.sum([]) or { panic(err) } + | ~~ + 17 | } diff --git a/vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.vv b/vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.vv new file mode 100644 index 000000000..e7d21a111 --- /dev/null +++ b/vlib/v/checker/tests/empty_arr_to_generic_param_sum_like_err.vv @@ -0,0 +1,17 @@ +import arrays + +fn sum_like[T](array []T) !T { + if array.len == 0 { + return error('Cannot sum up array of nothing.') + } + mut head := array[0] + for e in array[1..] { + head += e + } + return head +} + +fn main() { + sum_like([]) or { panic(err) } + arrays.sum([]) or { panic(err) } +} -- 2.39.5