[Bug] Wrong error message with normal args behind varargs
When creating a macro or function (same behaviour) with varargs and then a normal argument, the compiler gives an error from where the function is called, instead of on the declaration of the function.
Example:
import std::io;
macro void print(int... nums, String test) { }
fn void main() {
print(1, 2, 3, "numbers");
}
Error message:
3: fn void print(int... nums, String test) { }
4:
5: fn void main() {
6: print(1, 2, 3, "numbers");
^^^^^^^^^
Error: You cannot cast 'String' to 'int'.
This seems not the expected behaviour.
It even gets stranger when the types do match:
import std::io;
fn void print(int... nums, int num) { }
fn void main() {
print(1, 2, 3);
}
Error message:
3: fn void print(int... nums, int num) { }
4:
5: fn void main() {
6: print(1, 2, 3);
^
Error: Expected 'num: ...' after this argument.
1: import std::io;
2:
3: fn void print(int... nums, int num) { }
^^^^^
Note: The definition was here.
This is actually correct!
So you imply that a function with those arguments is correct? Why? And how would you call it?
You always need to call those trailing arguments with a named parameter. This is because otherwise default parameters would not make sense:
fn void print(int... nums, int num = 1) { }
In the above, given print(1, 2, 3) how would you know what would be assigned to num? So the rule is that any parameters after a vaarg must be named.
We can consider a better example. Let's say we want this:
fn void do_something(int x, Context context = default_context) { ... }
As long as we have non-vaargs, this is straightforward: do_something(1) or do_something(1, the_context). However, if we want vaargs it becomes a problem:
fn void do_something2(int... y, Context context = default_context) { ... }
So in order to make all uses consistent, we require that named parameter. We then have:
do_something(1);
do_something2(1, 2, 3);
do_something(4, context: my_context);
do_something2(1, 2, 3, 4, 5, context: my_context);
// There is do_something(4, my_context); available
// but the programmer could avoid that for consistency
Ok, that makes sense. I'm not convinced that the shown error message is the best one possible though. Can it hint at using named arguments?
What heuristic should be used?
What heuristic should be used?
Maybe if after varargs exist any args then add to error message: "Perhabs, patameter name after ... was not mentioned?" (or something like that).