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