diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 668963042c..81b5ae872b 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1632,11 +1632,6 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { c.error('expected $nr_args arguments, but got $call_expr.args.len', unexpected_arguments_pos) return method.return_type } - if method.generic_names.len > 0 && method.return_type.has_flag(.generic) { - c.check_return_generics_struct(method.return_type, mut call_expr, concrete_types) - } else { - call_expr.return_type = method.return_type - } mut exp_arg_typ := ast.Type(0) // type of 1st arg for special builtin methods mut param_is_mut := false mut no_type_promotion := false @@ -1761,6 +1756,12 @@ pub fn (mut c Checker) method_call(mut call_expr ast.CallExpr) ast.Type { // no type arguments given in call, attempt implicit instantiation c.infer_fn_generic_types(method, mut call_expr) } + // resolve return generics struct to concrete type + if method.generic_names.len > 0 && method.return_type.has_flag(.generic) { + c.check_return_generics_struct(method.return_type, mut call_expr, call_expr.concrete_types) + } else { + call_expr.return_type = method.return_type + } if call_expr.concrete_types.len > 0 && method.return_type != 0 { if typ := c.table.resolve_generic_to_concrete(method.return_type, method.generic_names, call_expr.concrete_types) @@ -2127,11 +2128,6 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type { call_expr.pos) return func.return_type } - if func.generic_names.len > 0 && func.return_type.has_flag(.generic) { - c.check_return_generics_struct(func.return_type, mut call_expr, concrete_types) - } else { - call_expr.return_type = func.return_type - } if func.return_type == ast.void_type && func.ctdefine.len > 0 && func.ctdefine !in c.pref.compile_defines { call_expr.should_be_skipped = true @@ -2293,6 +2289,12 @@ pub fn (mut c Checker) fn_call(mut call_expr ast.CallExpr) ast.Type { } } } + // resolve return generics struct to concrete type + if func.generic_names.len > 0 && func.return_type.has_flag(.generic) { + c.check_return_generics_struct(func.return_type, mut call_expr, call_expr.concrete_types) + } else { + call_expr.return_type = func.return_type + } if call_expr.concrete_types.len > 0 && func.return_type != 0 { if typ := c.table.resolve_generic_to_concrete(func.return_type, func.generic_names, call_expr.concrete_types) diff --git a/vlib/v/tests/generic_fn_assign_generics_struct_test.v b/vlib/v/tests/generic_fn_assign_generics_struct_test.v new file mode 100644 index 0000000000..87c7b18dd6 --- /dev/null +++ b/vlib/v/tests/generic_fn_assign_generics_struct_test.v @@ -0,0 +1,15 @@ +struct Test { + v T +} + +fn get_test(v T) Test { + return Test{ + v: v + } +} + +fn test_generics_assign_generics_struct() { + x := get_test(1) + println('$x.v') + assert x.v == 1 +}