15 hours ago

On Tuesday, 9 September 2025 at 00:40:31 UTC, Brother Bill wrote:

>

https://tour.dlang.org/tour/en/gems/opdispatch-opapply

This states: "Any unknown member function call to that type is passed to opDispatch, passing the unknown member function's name as a string template parameter."

Specs are often declarative but the compiler(especially walters compiler) and the machine it run on is imperative

It should say "if overload resolution inside a struct is failing, try a hack where an opDispatch is called"

14 hours ago

On Tuesday, 9 September 2025 at 12:04:07 UTC, Brother Bill wrote:

>

When commenting out the callHome() in struct C, it fails.

You can't call a function that doesn't exist. When the function doesn't exist, you can't call it.

>

Obviously if callHome() is explicitly created, it works.

Explicitly created? You can't just call a non-existent function and expect the compiler to generate it for you. You would need to have an opDispatch in struct C in order to do what you seem to be expecting to happen.

11 hours ago

On Tuesday, 9 September 2025 at 00:40:31 UTC, Brother Bill wrote:

>
c:\dev\D\D_templates_tutorial\toy1\source\app.d(8): Error: no property `callHome` for `l` of type `app.CallLogger!(C)`
    l.callHome("foo", "bar");
     ^

You might be expecting opDispatch inside CallLogger to try and build opDispatch!("callHome")("foo", "bar").

The thing is, it does. But when the compiler encounters failures, it means that it assumes opDispatch was not designed to handle that function, and it moves on to other options (UFCS maybe).

This is a long standing issue, and one that is very difficult to fix due to the way name lookup rules are working in the compiler.

In short opDispatch only is valid if it compiles. If it doesn't compile, it's as if it doesn't exist. This limitation is likely with us until someone can rework how the name lookups and IFTI works.

-Steve

10 hours ago

On Tuesday, 9 September 2025 at 19:17:11 UTC, Steven Schveighoffer wrote:

>

In short opDispatch only is valid if it compiles. If it doesn't compile, it's as if it doesn't exist.

Yours still thinking declaratively, that cant be true. The best description of its behavior is that it discards errors.

import std;
enum counter=cast(immutable(void)*)[0].ptr;
auto getcount()=>(*(cast(int*)counter));
auto count()=>(*(cast(int*)counter))++;

struct foo{
    void opDispatch(string s)(){
        enum _=count();
        static assert(0);
    }
}
void bar(foo){}
void foobar(foo){}
unittest{
    foo().bar;
    foo().foobar;
    getcount.writeln;//2
}
9 hours ago

On Tuesday, 9 September 2025 at 20:08:06 UTC, monkyyy wrote:

>

On Tuesday, 9 September 2025 at 19:17:11 UTC, Steven Schveighoffer wrote:

>

In short opDispatch only is valid if it compiles. If it doesn't compile, it's as if it doesn't exist.

Yours still thinking declaratively, that cant be true. The best description of its behavior is that it discards errors.

import std;
enum counter=cast(immutable(void)*)[0].ptr;
auto getcount()=>(*(cast(int*)counter));
auto count()=>(*(cast(int*)counter))++;

struct foo{
    void opDispatch(string s)(){
        enum _=count();
        static assert(0);
    }
}
void bar(foo){}
void foobar(foo){}
unittest{
    foo().bar;
    foo().foobar;
    getcount.writeln;//2
}

This calls the UFCS versions, because the opDispatch version does not compile.

The other thing is just a bug.

-Steve

1 2
Next ›   Last »