When compiling this invalid program:
void f(void delegate(int) nothrow dlg) {}
void main() {
void g(int x) {}
f((x){ g(x); });
}
The error reported is:
Error: function f (void delegate(int) nothrow dlg) is not callable using argument types (void)
This is wrong, as the argument type is not (void). It is also very difficult to figure out what is wrong with this program from this error (when the code is far more complicated).
A better error would be:
Error: function f expects (void delegate(int) **nothrow** dlg) but was given (void delegate(int))
Comment #1 by razvan.nitu1305 — 2023-05-11T11:51:29Z
This code now compiles because the compiler does inference for function literals.
Comment #2 by eyal — 2023-05-11T11:56:18Z
It is true that this *specific* example now compiles, but if you extract g() to the global scope it shows the problem again:
void f(void delegate(int) nothrow dlg) {}
void g(int x) {}
void main() {
f((x){ g(x); });
}
Error: function `testfuncliteral.f(void delegate(int) nothrow dlg)` is not
callable using argument types `(void)`
cannot pass argument `__lambda1` of type `void` to parameter `void delegate(int) nothrow dlg`
Comment #3 by nick — 2023-08-19T16:02:26Z
> This is wrong, as the argument type is not (void).
The type of a template is void. A lambda without parameter types is a template. When a template lambda doesn't implicitly convert to the expected parameter type, it's not established what the type of the implicitly instantiated lambda is, as it failed to instantiate.
> It is also very difficult to figure out what is wrong with this program from this error (when the code is far more complicated).
The fix for issue #10602 gives:
/home/nick/old/lambdaarg.d(16): Error: function `lambdaarg.f(void delegate(int) nothrow dlg)` is not callable using argument types `(void)`
/home/nick/old/lambdaarg.d(16): cannot implicitly convert expression `__lambda2` of type `void delegate(int x) @system` to `void delegate(int) nothrow`
Note the inferred argument type that the compiler tried on the second line.
Comment #4 by eyal — 2023-08-23T07:14:15Z
With the fix for issue #10602 - it sounds much better, though even then I don't think the error should say:
function `lambdaarg.f(void delegate(int) nothrow dlg)` is not callable using argument types `(void)`
but rather:
function `lambdaarg.f(void delegate(int) nothrow dlg)` is not callable using given template, as it failed to instantiate:
And this is much clearer direction for the programmer to read the actual problem on the next line.
Comment #5 by nick — 2023-08-23T08:38:24Z
In this case, yes. But the first line is supposed to show all the argument types passed to the function. E.g. when there's more than one argument.
Comment #6 by eyal — 2023-08-23T08:41:58Z
Then perhaps instead of "void" it is better to spell out "template instantiation failure, see below" as the type itself.
Verbose, maybe, but clearer how to progress
Comment #7 by robert.schadek — 2024-12-13T18:52:28Z