The compiler swallows opDispatch errors

bauss jj_1337 at live.dk
Mon Aug 30 06:13:03 UTC 2021


On Friday, 27 August 2021 at 16:08:37 UTC, Steven Schveighoffer 
wrote:
> 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

I'd argue that opDispatch shouldn't have any constraints on it.

It's a function that's rewritten by the compiler and so any error 
checking should be done solely by the compiler and without any 
attributing such as __traits(compiles)

If an opDispatch is declared that cannot be compiled then 
arguably it should stop the entire compilation as something is 
clearly wrong.

It's almost equivalent to a try/catch without handling an 
exception, but this time in the compiler.


More information about the Digitalmars-d mailing list