Skip to content

Commit 39f8084

Browse files
authored
checker: check type mismatch in args of generics method calls (fix #13193) (#13196)
1 parent 835484a commit 39f8084

File tree

4 files changed

+45
-5
lines changed

4 files changed

+45
-5
lines changed

vlib/v/checker/fn.v

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,7 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
12121212
}
12131213
exp_arg_sym := c.table.sym(exp_arg_typ)
12141214
c.expected_type = exp_arg_typ
1215-
got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
1215+
mut got_arg_typ := c.check_expr_opt_call(arg.expr, c.expr(arg.expr))
12161216
node.args[i].typ = got_arg_typ
12171217
if no_type_promotion {
12181218
if got_arg_typ != exp_arg_typ {
@@ -1243,10 +1243,29 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
12431243
continue
12441244
}
12451245
if exp_arg_typ.has_flag(.generic) {
1246-
continue
1246+
if concrete_types.len == 0 {
1247+
continue
1248+
}
1249+
1250+
if exp_utyp := c.table.resolve_generic_to_concrete(exp_arg_typ, method.generic_names,
1251+
concrete_types)
1252+
{
1253+
exp_arg_typ = exp_utyp
1254+
} else {
1255+
continue
1256+
}
1257+
1258+
if got_arg_typ.has_flag(.generic) {
1259+
if got_utyp := c.table.resolve_generic_to_concrete(got_arg_typ, method.generic_names,
1260+
concrete_types)
1261+
{
1262+
got_arg_typ = got_utyp
1263+
} else {
1264+
continue
1265+
}
1266+
}
12471267
}
1248-
c.check_expected_call_arg(got_arg_typ, c.unwrap_generic(exp_arg_typ), node.language,
1249-
arg) or {
1268+
c.check_expected_call_arg(got_arg_typ, exp_arg_typ, node.language, arg) or {
12501269
// str method, allow type with str method if fn arg is string
12511270
// Passing an int or a string array produces a c error here
12521271
// Deleting this condition results in propper V error messages
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
vlib/v/checker/tests/generics_method_called_arg_mismatch.vv:3:15: error: cannot use `Foo` as `Bar` in argument 1 to `Obj.set`
2+
1 | fn main() {
3+
2 | mut obj := Obj{}
4+
3 | obj.set<Bar>(Foo{})
5+
| ~~~~~
6+
4 | }
7+
5 |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
fn main() {
2+
mut obj := Obj{}
3+
obj.set<Bar>(Foo{})
4+
}
5+
6+
struct Foo {}
7+
8+
struct Bar {
9+
Foo
10+
}
11+
12+
struct Obj {}
13+
14+
fn (mut o Obj) set<T>(val T) {}

vlib/v/tests/generics_with_nested_generics_fn_test.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn (ng NestedGeneric) nested_test<T>(mut app T) {
1515

1616
fn method_test<T>(mut app T) int {
1717
ng := NestedGeneric{}
18-
ng.nested_test<T>(app)
18+
ng.nested_test<T>(mut app)
1919
return 22
2020
}
2121

0 commit comments

Comments
 (0)