diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 1f3239e597..d61e93f2aa 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -848,6 +848,7 @@ fn (g Checker) get_generic_array_fixed_element_type(array ast.ArrayFixed) ast.Ty fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) { mut inferred_types := []ast.Type{} + mut arg_inferred := []int{} for gi, gt_name in func.generic_names { // skip known types if gi < node.concrete_types.len { @@ -1027,7 +1028,7 @@ fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) { } } else if arg_sym.kind == .any && c.table.cur_fn.generic_names.len > 0 && c.table.cur_fn.params.len > 0 && func.generic_names.len > 0 - && arg.expr is ast.Ident { + && arg.expr is ast.Ident && arg_i !in arg_inferred { var_name := (arg.expr as ast.Ident).name for k, cur_param in c.table.cur_fn.params { if !cur_param.typ.has_flag(.generic) || k < gi || cur_param.name != var_name { @@ -1045,6 +1046,9 @@ fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) { } } } + if typ != ast.void_type { + arg_inferred << arg_i + } } if typ == ast.void_type { c.error('could not infer generic type `${gt_name}` in call to `${func.name}`', diff --git a/vlib/v/tests/generic_call_mixing_args_test.v b/vlib/v/tests/generic_call_mixing_args_test.v new file mode 100644 index 0000000000..4a410680f6 --- /dev/null +++ b/vlib/v/tests/generic_call_mixing_args_test.v @@ -0,0 +1,21 @@ +struct MyStruct { + text string +} + +struct App {} + +fn pre_send[T, N](app T, params N) { + send(params, app) +} + +fn send[T, N](params T, app N) { // app now is second argument + println(params) +} + +fn test_main() { + params := MyStruct{'hello'} + app := App{} + + pre_send(app, params) + assert true +}