@@ -2290,7 +2290,8 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
22902290 c.table.cur_concrete_types)
22912291 param = unwrapped
22922292 }
2293- param.typ = c.resolve_call_arg_param_type (call_arg, param, func.generic_names, concrete_types)
2293+ param.typ = c.resolve_call_arg_param_type (call_arg, param, func.generic_names,
2294+ concrete_types)
22942295 // registers if the arg must be passed by ref to disable auto deref args
22952296 call_arg.should_be_ptr = param.typ.is_ptr () && ! param.is_mut
22962297 if func.is_variadic && call_arg.expr is ast.ArrayDecompose {
@@ -3650,8 +3651,11 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
36503651 }
36513652
36523653 for i, mut arg in node.args {
3654+ mut exp_arg_param := call_arg_param_for_fn (method, i, true )
3655+ variadic_start := variadic_call_arg_start_idx (method, true )
3656+ has_typed_variadic := method.is_variadic && ! method.is_c_variadic
36533657 if i > 0 || exp_arg_typ == ast.no_type {
3654- exp_arg_typ = call_arg_param_for_fn (method, i, true ) .typ
3658+ exp_arg_typ = exp_arg_param .typ
36553659 if ! c.inside_recheck {
36563660 arg.ct_expr = c.comptime.is_comptime (arg.expr)
36573661 }
@@ -3670,7 +3674,8 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
36703674 parent_sym := c.table.sym (parent_type)
36713675 if parent_sym.info is ast.Struct && parent_sym.info.is_generic {
36723676 if f := parent_sym.find_method (method_name) {
3673- exp_arg_typ = call_arg_param_for_fn (f, i, true ).typ
3677+ exp_arg_param = call_arg_param_for_fn (f, i, true )
3678+ exp_arg_typ = exp_arg_param.typ
36743679 }
36753680 }
36763681 }
@@ -3698,8 +3703,19 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
36983703 else {}
36993704 }
37003705 }
3701- exp_arg_typ = c.resolve_short_syntax_call_arg_type (arg, exp_arg_typ,
3702- resolved_method_generic_names, resolved_method_concrete_types)
3706+ exp_arg_typ = if exp_arg_typ == exp_arg_param.typ {
3707+ c.resolve_call_arg_param_type (arg, exp_arg_param, resolved_method_generic_names,
3708+ resolved_method_concrete_types)
3709+ } else {
3710+ c.resolve_short_syntax_call_arg_type (arg, exp_arg_typ, resolved_method_generic_names,
3711+ resolved_method_concrete_types)
3712+ }
3713+ if has_typed_variadic && i > = variadic_start {
3714+ variadic_sym := c.table.sym (exp_arg_typ)
3715+ if variadic_sym.info is ast.Array {
3716+ exp_arg_typ = variadic_sym.info.elem_type
3717+ }
3718+ }
37033719 exp_arg_sym := c.table.sym (exp_arg_typ)
37043720 c.expected_type = exp_arg_typ
37053721
@@ -3712,8 +3728,6 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
37123728 arg.pos)
37133729 }
37143730 }
3715- variadic_start := variadic_call_arg_start_idx (method, true )
3716- has_typed_variadic := method.is_variadic && ! method.is_c_variadic
37173731 if has_typed_variadic && got_arg_typ.has_flag (.variadic) && node.args.len - 1 > i {
37183732 c.error ('when forwarding a variadic variable, it must be the final argument' , arg.pos)
37193733 }
@@ -3951,7 +3965,41 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
39513965 concrete_types = node.concrete_types.map (c.unwrap_generic (it ))
39523966 }
39533967 if method_generic_names_len > 0 && node.concrete_types.len > 0 {
3968+ variadic_start := variadic_call_arg_start_idx (method, true )
3969+ has_typed_variadic := method.is_variadic && ! method.is_c_variadic
39543970 for i, mut arg in node.args {
3971+ param := call_arg_param_for_fn (method, i, true )
3972+ if method_generic_names_len == node.concrete_types.len && param.typ.has_flag (.generic) {
3973+ if unwrap_typ := c.table.convert_generic_param_type (param, method.generic_names,
3974+ concrete_types)
3975+ {
3976+ mut expected_fn_typ := unwrap_typ
3977+ if has_typed_variadic && i > = variadic_start {
3978+ unwrap_sym := c.table.sym (unwrap_typ)
3979+ if unwrap_sym.info is ast.Array {
3980+ expected_fn_typ = unwrap_sym.info.elem_type
3981+ }
3982+ }
3983+ if c.table.final_sym (expected_fn_typ).kind == .function
3984+ && arg.expr ! is ast.LambdaExpr && arg.expr ! is ast.AnonFn {
3985+ if mut arg.expr is ast.Ident {
3986+ if arg.expr.concrete_types.any (it .has_flag (.generic)
3987+ || (it != 0 && c.table.sym (it ).kind == .placeholder))
3988+ {
3989+ arg.expr.concrete_types = []ast.Type{}
3990+ }
3991+ }
3992+ old_expected_type := c.expected_type
3993+ c.expected_type = expected_fn_typ
3994+ arg_typ := c.check_expr_option_or_result_call (arg.expr,
3995+ c.expr (mut arg.expr))
3996+ c.expected_type = old_expected_type
3997+ arg.typ = arg_typ
3998+ node.args[i].typ = arg_typ
3999+ node.args[i].expr = arg.expr
4000+ }
4001+ }
4002+ }
39554003 if mut arg.expr is ast.LambdaExpr {
39564004 c.handle_generic_lambda_arg (node, method.generic_names, mut arg.expr)
39574005 } else if mut arg.expr is ast.AnonFn {
0 commit comments