Thread overview
[Issue 20233] opDispatch hides alias this properties
Sep 21, 2019
Lorenzo Cogotti
Sep 21, 2019
Max Samukha
Sep 21, 2019
Lorenzo Cogotti
Sep 22, 2019
Max Samukha
Sep 22, 2019
Max Samukha
Jun 04, 2020
John Hall
Dec 17, 2022
Iain Buclaw
September 21, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

--- Comment #1 from Lorenzo Cogotti <micia@inventati.org> ---
Sorry, there was a typo in my code listing, here is the correct version, producing the same errors:

-----
module main;

struct Point
{
    int[2] coords;

    alias coords this;

    auto opDispatch(string name, A...)(A args)
    {
        return mixin("this.coords." ~ name ~ "(args)");
    }
}

void main()
{
    import std.stdio;

    Point p;
    writeln(p.ptr, p.length);
}

--
September 21, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

Max Samukha <maxsamukha@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxsamukha@gmail.com

--- Comment #2 from Max Samukha <maxsamukha@gmail.com> ---
It fails because you are trying apply a function call to a property. The error message is utterly misleading, though:

void main()
{
    int[2] x;
    x.ptr();
}

test.d(22): Error: no property ptr for type int[2] // wtf?

--
September 21, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

Lorenzo Cogotti <micia@inventati.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement

--- Comment #3 from Lorenzo Cogotti <micia@inventati.org> ---
You are right, looking into the implementation of `std.typecons.Proxy` I have noticed that the process to forward calls/access to an `alias this` from `opDispatch()` is more involved than that.

Thus I am changing the importance of this report to `Enhancement`, since I still stand by the opinion that the error message is quite misleading and might be improved.

Also, probably the `opDispatch()` inner workings would need to be clarified a little bit better in the language reference:

https://dlang.org/spec/operatoroverloading.html#dispatch

Since, by just reading, one can only obtain partial and at times confusing
information.
I had to look into the linked bug report to find out that it has precedence
over `alias this`, and found out by trial and error that it also has precedence
over UFCS.

--
September 22, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

Steven Schveighoffer <schveiguy@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy@yahoo.com

--- Comment #4 from Steven Schveighoffer <schveiguy@yahoo.com> ---
opDispatch should be considered before alias this, but apparently it disables the alias this completely. I thought this would fix the problem but it doesn't:

-------

    auto opDispatch(string name, A...)(A args) if(args.length > 0)
    {
        return mixin("this.coords." ~ name ~ "(args)");
    }

-------

It now simply says there's no property ptr or length for Point. So I think even though the original bug report was fixed, it wasn't fully fixed.

I think the above should work. As of now, the alias this is completely ignored.

--
September 22, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

--- Comment #5 from Max Samukha <maxsamukha@gmail.com> ---
'alias this' is irrelevant. The original test case fails because the array's .ptr property is called as a function. See the example in my previous comment (there was a typo: "apply" -> "to apply").

--
September 22, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

--- Comment #6 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to Max Samukha from comment #5)
> 'alias this' is irrelevant. The original test case fails because the array's .ptr property is called as a function. See the example in my previous comment (there was a typo: "apply" -> "to apply").

Yes, original test case fails for a different reason, but alias this isn't usable if you have opDispatch, which is definitely a bug I would think. It should trickle down to alias this if opDispatch doesn't handle it.

e.g.:

-----

struct S
{
   int length;
}

struct T
{
   S s;
   alias s this;
   int opDispatch(string fn, Args...)(Args args) if(fn != "length")
   {
      return 5;
   }
}

void main()
{
   T t;
   import std.stdio;
   writeln(t.length);
}

-------

Error: no property length for type T

If you comment out opDispatch it works.

--
September 22, 2019
https://issues.dlang.org/show_bug.cgi?id=20233

--- Comment #7 from Max Samukha <maxsamukha@gmail.com> ---
(In reply to Steven Schveighoffer from comment #6)
> (In reply to Max Samukha from comment #5)
> > 'alias this' is irrelevant. The original test case fails because the array's .ptr property is called as a function. See the example in my previous comment (there was a typo: "apply" -> "to apply").
> 
> Yes, original test case fails for a different reason, but alias this isn't usable if you have opDispatch, which is definitely a bug I would think. It should trickle down to alias this if opDispatch doesn't handle it.
> 
> e.g.:
> 

Ahh, got it. That's definitely a bug.

--
June 04, 2020
https://issues.dlang.org/show_bug.cgi?id=20233

John Hall <john.michael.hall@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |john.michael.hall@gmail.com

--- Comment #8 from John Hall <john.michael.hall@gmail.com> ---
Just ran into this.

I have two examples below. The first is with structs and alias this and the second is with classes. The class example compiles without error, but the struct one fails to compile. How classes behave is how I would expect structs to, and I was surprised when they didn't.

Consider also the diamond problem with multiple inheritance. The way classes work in D is that there is only one way to call a member or member function. Thus, opDispatch acts like overriding any base member function calls. alias this works this way most of the time in that a function in the derived struct will override one in the base struct. However, the doesn't hold with opDispatch.

unittest
{
    static struct Foo
    {
        int value;
        int foo() {
            return value + 1;
        }
    }

    static struct Bar
    {
        Foo x;
        alias x this;

        int opDispatch(string op)()
            if (op == "bar")
        {
            return x.foo;
        }
    }

    Bar x = Bar(Foo(1));

    assert(x.bar == 2);
    assert(x.foo == 2);
    assert(x.value == 1);
}


unittest
{
    static class Foo
    {
        int value;
        this(int x) {
            value = x;
        }
        int foo() {
            return value + 1;
        }
    }

    static class Bar : Foo
    {
        this(int x) {
            super(x);
        }

        int opDispatch(string op)()
            if (op == "bar")
        {
            return foo;
        }
    }

    Bar x = new Bar(1);
    assert(x.foo == 2);
    assert(x.bar == 2);
    assert(x.value == 1);
}

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=20233

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P4

--