Skip to content

Commit fc72044

Browse files
authored
checker: improve fn argument mismatch error (#22370)
1 parent 81b9fd8 commit fc72044

12 files changed

+62
-82
lines changed

vlib/v/checker/fn.v

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module checker
22

3+
import strings
34
import v.ast
45
import v.util
56
import v.token
@@ -2863,7 +2864,8 @@ struct HaveWantParams {
28632864
}
28642865

28652866
fn (mut c Checker) fn_call_error_have_want(p HaveWantParams) {
2866-
mut have_want := '\n\thave ('
2867+
mut sb := strings.new_builder(20)
2868+
sb.write_string('have (')
28672869
// Fetch arg types, they are always 0 at this point
28682870
// Duplicate logic, but we don't care, since this is an error, so no perf cost
28692871
mut arg_types := []ast.Type{len: p.args.len}
@@ -2876,30 +2878,32 @@ fn (mut c Checker) fn_call_error_have_want(p HaveWantParams) {
28762878
if arg_types[i] == 0 { // arg.typ == 0 {
28772879
// Arguments can have an unknown (invalid) type
28782880
// This should never happen.
2879-
have_want += '?'
2881+
sb.write_string('?')
28802882
} else {
2881-
have_want += c.table.type_to_str(arg_types[i]) // arg.typ)
2883+
sb.write_string(c.table.type_to_str(arg_types[i])) // arg.typ
28822884
}
28832885
if i < p.args.len - 1 {
2884-
have_want += ', '
2886+
sb.write_string(', ')
28852887
}
28862888
}
2889+
sb.write_string(')')
2890+
c.add_error_detail(sb.str())
28872891
// Actual parameters we expect
2888-
have_want += ')\n\twant ('
2892+
sb.write_string(' want (')
28892893
for i, param in p.params {
28902894
if i == 0 && p.nr_params == p.params.len - 1 {
28912895
// Skip receiver
28922896
continue
28932897
}
2894-
have_want += c.table.type_to_str(param.typ)
2898+
sb.write_string(c.table.type_to_str(param.typ))
28952899
if i < p.params.len - 1 {
2896-
have_want += ', '
2900+
sb.write_string(', ')
28972901
}
28982902
}
2899-
have_want += ')\n'
2903+
sb.write_string(')')
2904+
c.add_error_detail(sb.str())
29002905
args_plural := if p.nr_params == 1 { 'argument' } else { 'arguments' }
2901-
c.error('expected ${p.nr_params} ${args_plural}, but got ${p.nr_args}${have_want}',
2902-
p.pos)
2906+
c.error('expected ${p.nr_params} ${args_plural}, but got ${p.nr_args}', p.pos)
29032907
}
29042908

29052909
fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast.CallExpr) {

vlib/v/checker/tests/ambiguous_function_call.out

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ vlib/v/checker/tests/ambiguous_function_call.vv:7:2: error: ambiguous call to: `
1212
8 | }
1313
9 |
1414
vlib/v/checker/tests/ambiguous_function_call.vv:7:7: error: expected 0 arguments, but got 1
15-
have (int)
16-
want ()
17-
1815
5 | fn foo2() {
1916
6 | foo2 := 1
2017
7 | foo2(foo2)
2118
| ~~~~
2219
8 | }
2320
9 |
21+
Details: have (int)
22+
want ()
Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,39 @@
11
vlib/v/checker/tests/c_fn_surplus_args.vv:6:7: error: expected 0 arguments, but got 1
2-
have (int literal)
3-
want ()
4-
52
4 |
63
5 | fn main() {
74
6 | C.no(1) // allowed
85
| ^
96
7 | C.y1()
107
8 | C.y1(1) // ok
8+
Details: have (int literal)
9+
want ()
1110
vlib/v/checker/tests/c_fn_surplus_args.vv:7:4: error: expected 1 argument, but got 0
12-
have ()
13-
want (int)
14-
1511
5 | fn main() {
1612
6 | C.no(1) // allowed
1713
7 | C.y1()
1814
| ~~~~
1915
8 | C.y1(1) // ok
2016
9 | C.y1(1, 2)
17+
Details: have ()
18+
want (int)
2119
vlib/v/checker/tests/c_fn_surplus_args.vv:9:10: error: expected 1 argument, but got 2
22-
have (int literal, int literal)
23-
want (int)
24-
2520
7 | C.y1()
2621
8 | C.y1(1) // ok
2722
9 | C.y1(1, 2)
2823
| ^
2924
10 | C.ret() // ok
3025
11 | C.ret(1)
26+
Details: have (int literal, int literal)
27+
want (int)
3128
vlib/v/checker/tests/c_fn_surplus_args.vv:11:8: error: expected 0 arguments, but got 1
32-
have (int literal)
33-
want ()
34-
3529
9 | C.y1(1, 2)
3630
10 | C.ret() // ok
3731
11 | C.ret(1)
3832
| ^
3933
12 | // avoid cgen whilst warning, later above should error
4034
13 | main()
35+
Details: have (int literal)
36+
want ()
4137
vlib/v/checker/tests/c_fn_surplus_args.vv:13:2: error: the `main` function cannot be called in the program
4238
11 | C.ret(1)
4339
12 | // avoid cgen whilst warning, later above should error
@@ -46,12 +42,11 @@ vlib/v/checker/tests/c_fn_surplus_args.vv:13:2: error: the `main` function canno
4642
14 | C.af() // ok
4743
15 | C.af(3)
4844
vlib/v/checker/tests/c_fn_surplus_args.vv:15:7: error: expected 0 arguments, but got 1
49-
have (int literal)
50-
want ()
51-
5245
13 | main()
5346
14 | C.af() // ok
5447
15 | C.af(3)
5548
| ^
5649
16 | }
5750
17 |
51+
Details: have (int literal)
52+
want ()
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
vlib/v/checker/tests/error_fn_with_0_args.vv:2:9: error: expected 1 argument, but got 0
2-
have ()
3-
want (string)
4-
52
1 | fn abc() ! {
63
2 | return error()
74
| ~~~~~~~
85
3 | }
6+
Details: have ()
7+
want (string)

vlib/v/checker/tests/fn_array_decompose_arg_mismatch_err_c.out

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ vlib/v/checker/tests/fn_array_decompose_arg_mismatch_err_c.vv:2:9: error: decomp
1111
3 | }
1212
4 |
1313
vlib/v/checker/tests/fn_array_decompose_arg_mismatch_err_c.vv:2:6: error: expected 0 arguments, but got 1
14-
have (void)
15-
want ()
16-
1714
1 | fn main() {
1815
2 | foo(...args)
1916
| ~~~~~~~
2017
3 | }
2118
4 |
19+
Details: have (void)
20+
want ()

vlib/v/checker/tests/fn_call_with_extra_parenthesis.out

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
vlib/v/checker/tests/fn_call_with_extra_parenthesis.vv:5:2: error: expected 1 argument, but got 0
2-
have ()
3-
want (int)
4-
52
3 |
63
4 | fn main() {
74
5 | doit()(1)
85
| ~~~~~~
96
6 | }
7+
Details: have ()
8+
want (int)
109
vlib/v/checker/tests/fn_call_with_extra_parenthesis.vv:5:9: error: unknown function:
1110
3 |
1211
4 | fn main() {
Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,35 @@
11
vlib/v/checker/tests/function_count_of_args_mismatch_err.vv:8:13: error: expected 1 argument, but got 3
2-
have (bool, bool, int literal)
3-
want (bool)
4-
52
6 |
63
7 | fn main() {
74
8 | test(true, false, 1)
85
| ~~~~~~~~
96
9 | test()
107
10 | test2(true, false, 1)
8+
Details: have (bool, bool, int literal)
9+
want (bool)
1110
vlib/v/checker/tests/function_count_of_args_mismatch_err.vv:9:2: error: expected 1 argument, but got 0
12-
have ()
13-
want (bool)
14-
1511
7 | fn main() {
1612
8 | test(true, false, 1)
1713
9 | test()
1814
| ~~~~~~
1915
10 | test2(true, false, 1)
2016
11 | test2(true)
17+
Details: have ()
18+
want (bool)
2119
vlib/v/checker/tests/function_count_of_args_mismatch_err.vv:10:21: error: expected 2 arguments, but got 3
22-
have (bool, bool, int literal)
23-
want (bool, T)
24-
2520
8 | test(true, false, 1)
2621
9 | test()
2722
10 | test2(true, false, 1)
2823
| ^
2924
11 | test2(true)
3025
12 | }
26+
Details: have (bool, bool, int literal)
27+
want (bool, T)
3128
vlib/v/checker/tests/function_count_of_args_mismatch_err.vv:11:2: error: expected 2 arguments, but got 1
32-
have (bool)
33-
want (bool, T)
34-
3529
9 | test()
3630
10 | test2(true, false, 1)
3731
11 | test2(true)
3832
| ~~~~~~~~~~~
3933
12 | }
34+
Details: have (bool)
35+
want (bool, T)

vlib/v/checker/tests/generics_fn_arguments_count_err.out

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@ vlib/v/checker/tests/generics_fn_arguments_count_err.vv:15:18: error: expected 2
1313
16 | println(ret2)
1414
17 |
1515
vlib/v/checker/tests/generics_fn_arguments_count_err.vv:15:45: error: expected 2 arguments, but got 3
16-
have (int literal, int literal, string)
17-
want (A, B)
18-
1916
13 | println(ret1)
2017
14 |
2118
15 | ret2 := get_name[int, int, string](11, 22, 'hello')
2219
| ~~~~~~~
2320
16 | println(ret2)
2421
17 |
22+
Details: have (int literal, int literal, string)
23+
want (A, B)
2524
vlib/v/checker/tests/generics_fn_arguments_count_err.vv:19:22: error: expected 2 generic parameters, got 1
2625
17 |
2726
18 | foo := Foo{}
@@ -37,15 +36,14 @@ vlib/v/checker/tests/generics_fn_arguments_count_err.vv:22:22: error: expected 2
3736
23 | println(ret4)
3837
24 | }
3938
vlib/v/checker/tests/generics_fn_arguments_count_err.vv:22:49: error: expected 2 arguments, but got 3
40-
have (int literal, int literal, string)
41-
want (A, B)
42-
4339
20 | println(ret3)
4440
21 |
4541
22 | ret4 := foo.get_name[int, int, string](11, 22, 'hello')
4642
| ~~~~~~~
4743
23 | println(ret4)
4844
24 | }
45+
Details: have (int literal, int literal, string)
46+
want (A, B)
4947
vlib/v/checker/tests/generics_fn_arguments_count_err.vv:2:12: error: no known default format for type `A`
5048
1 | fn get_name[A, B](a A, b B) string {
5149
2 | return '${a}, ${b}'

vlib/v/checker/tests/generics_struct_field_fn_args_err.out

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,39 @@
11
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:21:20: error: expected 0 arguments, but got 1
2-
have (int literal)
3-
want ()
4-
52
19 | }
63
20 | println(fun0.call())
74
21 | println(fun0.call(1234))
85
| ~~~~
96
22 | println(fun0.call(1234, 5678))
107
23 |
8+
Details: have (int literal)
9+
want ()
1110
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:22:20: error: expected 0 arguments, but got 2
12-
have (int literal, int literal)
13-
want ()
14-
1511
20 | println(fun0.call())
1612
21 | println(fun0.call(1234))
1713
22 | println(fun0.call(1234, 5678))
1814
| ~~~~~~~~~~
1915
23 |
2016
24 | fun1 := Fun[fn (int) int]{
17+
Details: have (int literal, int literal)
18+
want ()
2119
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:29:15: error: expected 1 argument, but got 0
22-
have ()
23-
want (int)
24-
2520
27 |
2621
28 | println(fun1.call(42))
2722
29 | println(fun1.call())
2823
| ~~~~~~
2924
30 | println(fun1.call(42, 43))
3025
31 |
26+
Details: have ()
27+
want (int)
3128
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:30:24: error: expected 1 argument, but got 2
32-
have (int literal, int literal)
33-
want (int)
34-
3529
28 | println(fun1.call(42))
3630
29 | println(fun1.call())
3731
30 | println(fun1.call(42, 43))
3832
| ~~
3933
31 |
4034
32 | println(fun1.call(true))
35+
Details: have (int literal, int literal)
36+
want (int)
4137
vlib/v/checker/tests/generics_struct_field_fn_args_err.vv:32:20: error: cannot use `bool` as `int` in argument 1 to `Fun[fn (int) int].call`
4238
30 | println(fun1.call(42, 43))
4339
31 |

vlib/v/checker/tests/multi_return_err.out

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,32 @@ vlib/v/checker/tests/multi_return_err.vv:18:10: error: cannot use `f64` as `int`
66
19 | my_func3(my_func2(), 'foo')
77
20 | my_func4('foo', my_func2())
88
vlib/v/checker/tests/multi_return_err.vv:19:2: error: expected 3 arguments, but got 2
9-
have ((int, f64), string)
10-
want (int, int, string)
11-
129
17 | fn main() {
1310
18 | my_func(my_func2())
1411
19 | my_func3(my_func2(), 'foo')
1512
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1613
20 | my_func4('foo', my_func2())
1714
21 | my_func(my_func5())
15+
Details: have ((int, f64), string)
16+
want (int, int, string)
1817
vlib/v/checker/tests/multi_return_err.vv:20:2: error: expected 3 arguments, but got 2
19-
have (string, (int, f64))
20-
want (string, int, int)
21-
2218
18 | my_func(my_func2())
2319
19 | my_func3(my_func2(), 'foo')
2420
20 | my_func4('foo', my_func2())
2521
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
2622
21 | my_func(my_func5())
2723
22 | my_func(my_func6())
24+
Details: have (string, (int, f64))
25+
want (string, int, int)
2826
vlib/v/checker/tests/multi_return_err.vv:21:2: error: expected 2 arguments, but got 1
29-
have (void)
30-
want (int, int)
31-
3227
19 | my_func3(my_func2(), 'foo')
3328
20 | my_func4('foo', my_func2())
3429
21 | my_func(my_func5())
3530
| ~~~~~~~~~~~~~~~~~~~
3631
22 | my_func(my_func6())
3732
23 | }
33+
Details: have (void)
34+
want (int, int)
3835
vlib/v/checker/tests/multi_return_err.vv:22:10: error: expected 2 arguments, but got 3 from multi-return (int, int, int)
3936
20 | my_func4('foo', my_func2())
4037
21 | my_func(my_func5())
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
vlib/v/checker/tests/no_interface_instantiation_b.vv:6:2: error: expected 1 argument, but got 0
2-
have ()
3-
want (Speaker)
4-
52
4 |
63
5 | fn main() {
74
6 | my_fn()
85
| ~~~~~~~
96
7 | }
7+
Details: have ()
8+
want (main.Speaker)
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
vlib/v/checker/tests/no_main_println_err.vv:1:1: error: expected 1 argument, but got 0
2-
have ()
3-
want (string)
4-
52
1 | println()
63
| ~~~~~~~~~
4+
Details: have ()
5+
want (string)

0 commit comments

Comments
 (0)