http://wiki.dlang.org/DIP66

I've applied some changes to it, however there are still some unresolved questions.

Here's my destruction:

* "symbol can be a field or a get-property (method annotated with @property and taking zero parameters)." -> actually:

(a) the @property annotation is not necessary
(b) there may be one ore more parameters so long as they're all defaulted

So the text should be "obj.symbol must be a valid expression".

Done.

* "At the AliasThis declaration semantic stage, the compiler can perform the initial checks and reject the obviously incorrect AliasThis declarations." -> it might be simpler (for the sake of simplifying generic code) to just delay all error checking to the first use.

I disagree with that. Current check is not recursive and prevent you code from a silly errors:

struct X(T, V)
{
   T t;
   V v;
   alias t this;
alias v this; //Error if is(T == V). However this code is fundamentally broken, and this error should be raised as soon as possible.
}

class A : B
{
   B b;
alias b this; //Error: super type (B) always hides "aliasthised" type B because base classes should be processed before alias this types.
}

* I don't think the pseudocode helps a lot. Better let's have a clear and precise specification (I've edited the lookup order into an ordered list).

Done.

* Regarding the lookup, opDispatch shouldn't come before alias this, or should come before base class lookup. Essentially alias this is subtyping so it should enjoy similar privileges to base classes. A different way to look at it is opDispatch is a "last resort" lookup mechanism, just one step above the UFCS lowering.

I agree with this suggestion, however it breaks an existing code.
opDispatch shouldn't come before base type lookup, because it will hide basic methods like toString. opDispatch may come after alias this lookup, however it will fundamentally change program behaviour.

Current (implemented is released compiler) behaviour:
import std.stdio;

struct Base
{
    string foo()
    {
        return "Base.foo";
    }
}

struct Derived
{
    Base b;
    alias b this;

    string opDispatch(string s)()
    {
        return "opDispatch";
    }
}

void main()
{
    Derived d;
    writeln(d.foo()); //prints "opDispatch"
}

After your change this call will write "Base.foo". And I see no way to add third "transitional" state to allow users rewrite those code correctly. This changing will suddenly, without any warning, change a user code. I understand that this case is very rare however it may be.

And, TBH, this issue not relevant with multiple alias this :-)


* The DIP should specify the working of alias this as rewrites/lowerings, not pseudocode. Basically for each kth declaration "alias symbolk this;" the compiler rewrites "obj.xyz" as "obj.symbolk.xyz" and then does the usual lookup on that expression. That means the whole algorithms is applied again etc. If more than one rewrite typechecks, that's an ambiguity error.

Ok. I've removed pseudocode. Is it better now?

* IMPORTANT: The DIP must discuss rvalue vs. lvalue cases. The rewrite approach simplifies that discussion because it's clear what happens by simply reasoning about the rewritten expression. Lvalue vs. rvalue matters a lot practically. Consider:

struct A
{
    private int x;
    alias x this;
}

struct B
{
    private int _x;
    int x() { return x; }
    alias x this;
}

Then x can be passed by reference, modified directly etc. for A but not for B.

Done. I've added corresponding chapter to the DIP and commit to the PR.

Reply via email to