@@ -1347,6 +1347,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
13471347
13481348 // XTODO document
13491349 if typ != 0 {
1350+ // Only unwrap FnType if we have concrete types (during recheck/instantiation)
13501351 unwrapped_typ := if typ.has_flag (.generic) && c.table.cur_fn != unsafe { nil }
13511352 && c.table.cur_fn.generic_names.len > 0 {
13521353 c.table.unwrap_generic_type (typ, c.table.cur_fn.generic_names, c.table.cur_concrete_types)
@@ -1356,6 +1357,26 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
13561357 generic_vts := c.table.final_sym (unwrapped_typ)
13571358 if generic_vts.info is ast.FnType {
13581359 func = generic_vts.info.func
1360+ // If we're inside a generic function with concrete types, unwrap the function's parameter types
1361+ // This is needed to properly type-check calls like f(1) where f: fn(T) U and T=string
1362+ if c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len > 0
1363+ && c.table.cur_concrete_types.len == c.table.cur_fn.generic_names.len {
1364+ mut unwrapped_func := func
1365+ unwrapped_func.params = unwrapped_func.params.clone ()
1366+ for i, param in func.params {
1367+ if param.typ.has_flag (.generic) {
1368+ unwrapped_func.params[i].typ = c.table.unwrap_generic_type_ex (param.typ,
1369+ c.table.cur_fn.generic_names, c.table.cur_concrete_types,
1370+ true )
1371+ }
1372+ }
1373+ if func.return_type.has_flag (.generic) {
1374+ unwrapped_func.return_type = c.table.unwrap_generic_type_ex (func.return_type,
1375+ c.table.cur_fn.generic_names, c.table.cur_concrete_types,
1376+ true )
1377+ }
1378+ func = unwrapped_func
1379+ }
13591380 found = true
13601381 found_in_args = true
13611382 } else {
@@ -1758,9 +1779,28 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
17581779 c.error ('literal argument cannot be passed as reference parameter `${c.table.type_to_str(param.typ)} `' ,
17591780 call_arg.pos)
17601781 }
1761- c.check_expected_call_arg (arg_typ, c.unwrap_generic (param.typ), node.language,
1782+ // checked by second pass
1783+ if param.typ.has_flag (.generic) && func.generic_names.len > 0 && concrete_types.len == 0 {
1784+ continue
1785+ }
1786+ unwrapped_param_typ := if param.typ.has_flag (.generic) && func.generic_names.len > 0
1787+ && concrete_types.len == func.generic_names.len {
1788+ c.table.unwrap_generic_type_ex (param.typ, func.generic_names, concrete_types,
1789+ true )
1790+ } else {
1791+ c.unwrap_generic (param.typ)
1792+ }
1793+ unwrapped_arg_typ := if arg_typ.has_flag (.generic) && c.table.cur_fn != unsafe { nil }
1794+ && c.table.cur_fn.generic_names.len > 0
1795+ && c.table.cur_concrete_types.len == c.table.cur_fn.generic_names.len {
1796+ c.table.unwrap_generic_type_ex (arg_typ, c.table.cur_fn.generic_names, c.table.cur_concrete_types,
1797+ true )
1798+ } else {
1799+ arg_typ
1800+ }
1801+ c.check_expected_call_arg (unwrapped_arg_typ, unwrapped_param_typ, node.language,
17621802 call_arg) or {
1763- if param.typ .has_flag (.generic) {
1803+ if unwrapped_param_typ .has_flag (.generic) {
17641804 continue
17651805 }
17661806 if param_typ_sym.info is ast.Array && arg_typ_sym.info is ast.Array {
@@ -1939,6 +1979,16 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
19391979 // json.encode param is set voidptr, we should bound the proper type here
19401980 node.expected_arg_types = [node.args[0 ].typ]
19411981 }
1982+ // unwrap before type inference matching
1983+ if c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len > 0
1984+ && c.table.cur_concrete_types.len == c.table.cur_fn.generic_names.len {
1985+ for i, arg in node.args {
1986+ if arg.typ.has_flag (.generic) {
1987+ node.args[i].typ = c.table.unwrap_generic_type_ex (arg.typ, c.table.cur_fn.generic_names,
1988+ c.table.cur_concrete_types, true )
1989+ }
1990+ }
1991+ }
19421992 if func.generic_names.len != node.concrete_types.len {
19431993 // no type arguments given in call, attempt implicit instantiation
19441994 c.infer_fn_generic_types (func, mut node)
0 commit comments