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.