The compiler swallows opDispatch errors

Steven Schveighoffer schveiguy at gmail.com
Fri Aug 27 16:08:37 UTC 2021


This bit me again:

```d
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!

```d
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


More information about the Digitalmars-d mailing list