This bit me again:
struct S
{
void opDispatch(string s)() {
writeln("you called " ~ s);
}
}
void main()
{
S s;
s.foo();
}
The result?
onlineapp.d(11): Error: no property `foo` for type `onlineapp.S`
onlineapp.d(11): potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message
What? I have to tell the compiler to explicitly instantiate opDispatch in order for it to tell me the actual message?
What I expected is something like:
Error: no symbol writeln
, please import std.stdio
What is happening here is that if opDispatch
doesn't compile for any reason, it's not considered a valid instantiation.
This is not how any other functions templates work. If you call a function or template, and it doesn't compile, it tells you why it didn't compile and gives an error. With opDispatch
, it implicitly is adding one of the worst template constraints if (__traits(compiles, <function body>))
. This hides so much stuff, and makes it really hard to find out why something doesn't work, or results in calling very surprising UFCS functions.
Let's make it even more obscure!
s.get();
onlineapp.d(11): Error: template `object.get` cannot deduce function from argument types `!()(S)`, candidates are:
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3077): `get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)`
/dlang/dmd/linux/bin64/../../src/druntime/import/object.d(3084): `get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)`
Yeah, can we please fix this? opDispatch
should use the same rules as any other function template -- if it matches, compile. No implicit "compilation must succeed" BS.
-Steve