Comment #0 by timothee.cour2 — 2015-02-08T02:18:19Z
dmd -c -o- main.d
main.d(7): Error: function main.foo () is not callable using argument types (A)
----
void foo(){}
struct A{
auto opDispatch(string op)() {
writeln;
}
}
void test(){
A.init.foo();
}
Comment #1 by destructionator — 2015-02-08T02:20:25Z
Not a bug (though a common mistake that the compiler offers zero help with) - you forgot to import std.stdio, so the opDispatch didn't compile and that's why it wasn't considered.
Comment #2 by timothee.cour2 — 2015-02-08T02:30:43Z
I forgot to mention: the naked 'writeln' was intentional in this bug report.
the error occurs when the template body of opDispatch is not compilable (eg as in the example, import std.stdio is missing).
The correct behavior IMO should be to say:
error : could not resolve writeln.
Furthermore to counter your argument saying this is not a bug:
replace 'void fun(){}' by 'void foo(A a){}'
now it compiles whereas is shouldn't.
Comment #3 by destructionator — 2015-02-08T02:43:23Z
Yeah, I agree that would be nice. And actually the docs don't say what should happen when opDispatch fails to compile http://dlang.org/operatoroverloading.html#dispatch
so ok, now I agree with you, but I think it should be retitled to focus on just the opDispatch, the ufcs is unrelated. If it fails to compile it will say "no such property" which has the same root cause and is equally unhelpful.
Comment #4 by timothee.cour2 — 2015-02-08T05:00:22Z
You're right that UFCS is not root cause; i've updated the title.
indeed, if we remove 'void foo' entirely it errors with "Error: no property 'foo' for type 'A'" instead of erroring with what it should:
main.d(13): Error: 'writeln' is not defined, perhaps you need to import std.stdio; ?
main.d(22): Error: template instance main.A.opDispatch!("foo") error instantiating
Comment #5 by simen.kjaras — 2018-05-16T13:14:11Z
*** Issue 12951 has been marked as a duplicate of this issue. ***
Comment #6 by simen.kjaras — 2018-05-16T13:28:25Z
*** Issue 8387 has been marked as a duplicate of this issue. ***
Comment #7 by nick — 2018-05-16T16:38:02Z
*** Issue 18863 has been marked as a duplicate of this issue. ***
Comment #8 by erny.castell — 2019-11-23T23:24:43Z
This issue makes it practically impossible to use opDispatch with decent diagnostics, I think it should be solved as soon as possible.
Would any compiler expert want to take it?
Comment #9 by schveiguy — 2020-09-03T19:18:31Z
Ran into this recently also.
What I have been doing to figure out why it's not working is to explicitly call opDispatch:
A.init.opDispatch!"foo"();
IMO, if no other valid members exist, then opDispatch should be used, even if it doesn't compile (and the subsequent error message printed).
I can see the utility in something like:
struct A
{
T wrapped;
auto opDispatch(string m, Args...)(Args args) {
mixin("return wrapped." ~ m ~ "(args);");
}
}
Without having to use a constraint to ensure the call is possible. But the cost for this is pretty steep (confusing and misleading error messages). Whether opDispatch is *matched* or not should not depend on the body, only the signature and constraints. This is in line with all other function templates.
Comment #10 by hsteoh — 2020-09-03T21:49:21Z
I've also run into this before, and it's nigh impossible to debug if you didn't realize opDispatch was involved, because declining instantiation rather than generating a compile error may cause overload resolution to move to another, unintended overload, which may in turn have some deeply-nested templates which fails in some deeply-nested scope. You'd trace the error all the way back out the entire instantiation chain, then be left scratching your head as to why that template was even chosen in the first place, and it may take a while to realize opDispatch was the intended call target but due to suppression of errors it was silently skipped.
As Steven said, whether opDispatch is chosen should not depend on the body, but only on the declaration and sig constraints. Any errors in the body should be a hard compile error. For method-forwarding templates, it should be easy enough to use __traits(hasMember) in opDispatch's sig constraints to decide whether or not to accept instantiation. Small price for greatly improving error reporting involving opDispatch.
Comment #11 by dlang-bot — 2021-03-19T08:37:46Z
@thewilsonator created dlang/dmd pull request #12288 "Fix issue 14145 - opDispatch not considered when function body doesn'…" fixing this issue:
- Fix issue 14145 - opDispatch not considered when function body doesn't compile
https://github.com/dlang/dmd/pull/12288
Comment #12 by dlang-bot — 2021-03-22T06:30:43Z
dlang/dmd pull request #12288 "Fix issue 14145 - opDispatch not considered when function body doesn'…" was merged into master:
- 7fde6366daf146efc37d81f54d7265de2da8c3ff by Nicholas Lindsay Wilson:
Fix issue 14145 - opDispatch not considered when function body doesn't compile
https://github.com/dlang/dmd/pull/12288
Comment #13 by schveiguy — 2021-08-31T12:30:23Z
Reopening, this is still not "fixed", the PR just changed the error messge.
Comment #14 by destructionator — 2022-02-16T12:55:30Z
Also adding Razvan to this one as it is a perpetually annoying opDispatch error bug Steve and I have had to deal with and complained about on the forum for years now. It used to work much better.
Comment #15 by razvan.nitu1305 — 2022-02-17T11:03:11Z
@RazvanN7 created dlang/dmd pull request #13679 "Fix Issue 14145 - opDispatch not considered when function body doesn't compile" fixing this issue:
- Fix Issue 14145 - opDispatch not considered when function body doesn't compile
https://github.com/dlang/dmd/pull/13679
Comment #17 by robert.schadek — 2024-12-13T18:40:08Z