diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 905f1567f3..7b064d8968 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1212,7 +1212,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { } exp_arg_sym := c.table.sym(exp_arg_typ) c.expected_type = exp_arg_typ - got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr)) + mut got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr)) node.args[i].typ = got_arg_typ if no_type_promotion { if got_arg_typ != exp_arg_typ { @@ -1243,10 +1243,29 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type { continue } if exp_arg_typ.has_flag(.generic) { - continue + if concrete_types.len == 0 { + continue + } + + if exp_utyp := c.table.resolve_generic_to_concrete(exp_arg_typ, method.generic_names, + concrete_types) + { + exp_arg_typ = exp_utyp + } else { + continue + } + + if got_arg_typ.has_flag(.generic) { + if got_utyp := c.table.resolve_generic_to_concrete(got_arg_typ, method.generic_names, + concrete_types) + { + got_arg_typ = got_utyp + } else { + continue + } + } } - c.check_expected_call_arg(got_arg_typ, c.unwrap_generic(exp_arg_typ), node.language, - arg) or { + c.check_expected_call_arg(got_arg_typ, exp_arg_typ, node.language, arg) or { // str method, allow type with str method if fn arg is string // Passing an int or a string array produces a c error here // Deleting this condition results in propper V error messages diff --git a/vlib/v/checker/tests/generics_method_called_arg_mismatch.out b/vlib/v/checker/tests/generics_method_called_arg_mismatch.out new file mode 100644 index 0000000000..4d28196eca --- /dev/null +++ b/vlib/v/checker/tests/generics_method_called_arg_mismatch.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generics_method_called_arg_mismatch.vv:3:15: error: cannot use `Foo` as `Bar` in argument 1 to `Obj.set` + 1 | fn main() { + 2 | mut obj := Obj{} + 3 | obj.set(Foo{}) + | ~~~~~ + 4 | } + 5 | diff --git a/vlib/v/checker/tests/generics_method_called_arg_mismatch.vv b/vlib/v/checker/tests/generics_method_called_arg_mismatch.vv new file mode 100644 index 0000000000..4fdd7aa260 --- /dev/null +++ b/vlib/v/checker/tests/generics_method_called_arg_mismatch.vv @@ -0,0 +1,14 @@ +fn main() { + mut obj := Obj{} + obj.set(Foo{}) +} + +struct Foo {} + +struct Bar { + Foo +} + +struct Obj {} + +fn (mut o Obj) set(val T) {} diff --git a/vlib/v/tests/generics_with_nested_generics_fn_test.v b/vlib/v/tests/generics_with_nested_generics_fn_test.v index 879788fe8d..6272134b88 100644 --- a/vlib/v/tests/generics_with_nested_generics_fn_test.v +++ b/vlib/v/tests/generics_with_nested_generics_fn_test.v @@ -15,7 +15,7 @@ fn (ng NestedGeneric) nested_test(mut app T) { fn method_test(mut app T) int { ng := NestedGeneric{} - ng.nested_test(app) + ng.nested_test(mut app) return 22 }