alias this

2012-08-30 Thread Carl Sturtivant


Subtyping with 'alias this' is superb and easy; it's a tremendous 
simplifying mechanism, one of D's many ingenious and well 
integrated technical simplifying mechanisms that were a big part 
of getting me on board, spreading the word and moving to D. What 
is the design logic behind


364.d(9): Error: alias this compileme364.number.__anonymous there 
can be only one alias this


--- not a complaint, I'd just like to hear opinion of the basis 
of the above restriction from experts.




Re: alias this

2012-08-30 Thread Steven Schveighoffer

On Thu, 30 Aug 2012 07:48:54 -0400, Carl Sturtivant 
wrote:



Subtyping with 'alias this' is superb and easy; it's a tremendous  
simplifying mechanism, one of D's many ingenious and well integrated  
technical simplifying mechanisms that were a big part of getting me on  
board, spreading the word and moving to D. What is the design logic  
behind


364.d(9): Error: alias this compileme364.number.__anonymous there can be  
only one alias this


--- not a complaint, I'd just like to hear opinion of the basis of the  
above restriction from experts.


This is a limitation in implementation.  According to TDPL, there will be
multiple alias this allowed in the final implementation.

See this bug: http://d.puremagic.com/issues/show_bug.cgi?id=6083

-Steve


Re: alias this

2012-08-30 Thread Carl Sturtivant
On Thursday, 30 August 2012 at 12:58:28 UTC, Steven Schveighoffer 
wrote:
On Thu, 30 Aug 2012 07:48:54 -0400, Carl Sturtivant 


wrote:



Subtyping with 'alias this' is superb and easy; it's a 
tremendous simplifying mechanism, one of D's many ingenious 
and well integrated technical simplifying mechanisms that were 
a big part of getting me on board, spreading the word and 
moving to D. What is the design logic behind


364.d(9): Error: alias this compileme364.number.__anonymous 
there can be only one alias this


--- not a complaint, I'd just like to hear opinion of the 
basis of the above restriction from experts.


This is a limitation in implementation.  According to TDPL, 
there will be

multiple alias this allowed in the final implementation.

See this bug: http://d.puremagic.com/issues/show_bug.cgi?id=6083

-Steve


Ah, thanks. Glad to hear the eventual outcome is broad.




Re: alias this

2012-09-01 Thread Carl Sturtivant

What is the design logic behind

364.d(9): Error: alias this compileme364.number.__anonymous 
there can be only one alias this


--- not a complaint, I'd just like to hear opinion of the 
basis of the above restriction from experts.


This is a limitation in implementation.  According to TDPL, 
there will be

multiple alias this allowed in the final implementation.

See this bug: http://d.puremagic.com/issues/show_bug.cgi?id=6083



Perhaps you can point me at a way to get a short list of features 
like this that we might say are "strategically limited" at the 
moment (perhaps even to the extent of being absent even), but 
definitely intended for complete implementation eventually.




Re: alias this

2012-09-03 Thread Don Clugston

On 01/09/12 15:16, Carl Sturtivant wrote:

What is the design logic behind

364.d(9): Error: alias this compileme364.number.__anonymous there can
be only one alias this

--- not a complaint, I'd just like to hear opinion of the basis of
the above restriction from experts.


This is a limitation in implementation.  According to TDPL, there will be
multiple alias this allowed in the final implementation.

See this bug: http://d.puremagic.com/issues/show_bug.cgi?id=6083



Perhaps you can point me at a way to get a short list of features like
this that we might say are "strategically limited" at the moment
(perhaps even to the extent of being absent even), but definitely
intended for complete implementation eventually.



http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel#Roadmap



alias this question

2011-02-13 Thread Olli Aalto
I encountered a problem with alias this, when the aliased member is 
private. I'm using the latest dmd2. It reports the follwing:

src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?

O.

module AliasThis;

import S;
import K;

void foo(S s)
{
//...
}

void main()
{  
const K k;
foo(k);
}module S;

struct S
{
int x;
}module K;

import S;

struct K
{
 S s;
public alias s this;
}


alias this constructor

2018-03-24 Thread Dave Jones via Digitalmars-d

struct Foo
{
int x;
alias x this;
}

Foo f = 12; // error

Foo foo;
f = 12; // this is OK

any reason why the first cant be allowed?


multiple alias this

2018-07-19 Thread Mr.Bingo via Digitalmars-d

An implementation method:

Single `alias this` already works, this method leverages it to 
create a multiple `alias this`. This method is presented for a 
basic review


1.
alias a,b,... this;

Is this proposed syntax used for assigning multiple sinks for the 
dispatching of access '.' operator. It is also called an `alias 
this` with multiple implicit for the case of one alias.


struct X
{
   int a;
   string s;
   alias a,s this
}
X x;
void foo(T)(T x);

2.

Here the compiler chooses which alias works by inference. foo(x) 
fails because of ambiguity in that it accepts both aliases. The 
proposed rule is that that an `alias this` must resolve to one 
and only one alias. This rule allows the original single `alias 
this` algorithm to work for multiple `alias this` by effectively 
adding a loop in the testing section of the code(we test for each 
alias and if only one is successful then success, else failure)



This rule prevents such things as

struct X
{
   int a;
   int b;
   double c;
   string s;
   alias a,b,c,s this
}


because b and a are the same type and both will resolve the 
inferencing rule giving at least 2 variables rather than the one 
required by the rule.


c and s may or may not fail depending on context.


The simplification here is that no other code anywhere dealing 
with the use of multiple `alias this` needs to be modified such 
as templates, traits, runtime, etc.



If the single alias this code that determines if the alias is 
active is represented by SA!(T,typeof(aliasthis)) which returns 
true if the type of the single `alias this` is T, the parameter 
or object "returned", then multiple `alias this` looks something 
like


int count = 0;
foreach(ma; multiplealiasthislist)
  count += (SA!(T,typeof(aliasthis))) ? 1 : 0;

if (count != 1) error();


when the single `alias this` code would look like

if (!SA!(T,typeof(aliasthis))) error();

For `.` access each type is checked in the loop in a similar 
manner for only one solution.


3. Why this works is because for orthogonal types we'ed expect no 
issues and that generally will be the case. Therefore we simply 
limit multiple `alias this` to the case where all the types are 
orthogonal. (convenient way to solve the problem, but 
orthogonality is easily defined in D)


For non-orthogonal types we just error out and let the programmer 
figure out the proper solution.


D can attempt to check if all the types are orthogonal at compile 
time in two ways. Either at the declaration of the alias this or 
at the resolving point. If it is done at resolution then it 
relaxes orthogonality requirements by allowing some cases to pass 
simply because the context allows it but it could fail the 
resolve when the program has been modified.


4. e.g., for a 2-ply multiple `alias this` we have something like 
X given above.


   x and s are not orthogonal in all cases, specially with 
templates and so either the compiler can fail when parsing X or 
it can wait to test which types work in which circumstances and 
fail only if there is an ambiguity. The last way is the way D 
generally works as it offers a more relaxed error checking which 
allows many cases to work while also allowing for a more slightly 
brittle programming experience(which may not effect most people).



5. Templates are a special problem since they can accept any 
possible type, and a multiple alias this effectively is a 
multiple type. One can instantiate the template on all versions 
and if only one passes then that version is used, but this is 
prone to errors since what the programmer may think is the passed 
alias is not, and some corner cases it would be a difficult bug 
to detect.


6. reflection/traits should allow getting the multiple alias 
types and variable names.

















Multiple Alias This

2009-04-02 Thread dsimcha
Is the limitation that one may only have one alias this per class/struct a
temporary limitation that will be removed once higher-priority stuff is
finished and some ambiguities are resolved, or are things likely to stay this
way?  On the one hand, allowing multiple alias this would cause ambiguities
similar to multiple inheritance.  On the other hand, only being able to define
one implicit cast per class/struct is pretty limiting and allowing only one
alias this seems like a huge cop-out.


Alias this and std.traits.isArray

2013-01-05 Thread David
This code worked with dmd 2.060:

import std.stdio;
import std.traits;

struct OhWhy(S) {
S[] arr;
alias arr this;
}

void main() {
static assert(isArray!(OhWhy!(float)));

}

But fails with dmd 2.061:
ss.d(10): Error: static assert  (isArray!(OhWhy!(float))) is false

(same happens with alias this to static arrays and isArray/isStaticArray)


Is this intended or a regression? If latter, I'll submit a bug-ticket.


Re: alias this question

2011-02-13 Thread Simen kjaeraas

Olli Aalto  wrote:


I encountered a problem with alias this, when the aliased member is
private. I'm using the latest dmd2. It reports the follwing:
src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?


This is intended. alias this (and any other alias) act as simple
rewrites to the aliased symbol, and does not change their protection
level.

I believe there is a bug on this specific issue already, and #4533[1]
certainly does describe it in general.

http://d.puremagic.com/issues/show_bug.cgi?id=4533

--
Simen


Re: alias this question

2011-02-13 Thread Olli Aalto

On 13.2.2011 19:40, Simen kjaeraas wrote:

Olli Aalto  wrote:


I encountered a problem with alias this, when the aliased member is
private. I'm using the latest dmd2. It reports the follwing:
src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?


This is intended. alias this (and any other alias) act as simple
rewrites to the aliased symbol, and does not change their protection
level.



Pity. Would have been nice, now it's just one pretty useless feature at 
the end of a list of features for the language.


O.



Re: alias this question

2011-02-13 Thread spir

On 02/13/2011 05:30 PM, Olli Aalto wrote:

I encountered a problem with alias this, when the aliased member is private.
I'm using the latest dmd2. It reports the follwing:
src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?


Dunno, lets me wonder: what are use cases of alias this on a public member? I 
mean, on a member that /must/ remain private. Then, it's just syntactic sugar, 
which is good, but why wrap it into an object?
In my mind, the typical use case is precisely a wrapper struct around something 
that, so-to-say, "naturally" ends up private.


Denis
--
_
vita es estrany
spir.wikidot.com



Re: alias this question

2011-02-16 Thread Christopher Nicholson-Sauls
On 02/13/11 10:30, Olli Aalto wrote:
> I encountered a problem with alias this, when the aliased member is
> private. I'm using the latest dmd2. It reports the follwing:
> src\main.d(14): Error: struct K.K member s is not accessible
> 
> If I change the private modifier on the s member to public it works.
> 
> Is this as intended, or a bug?
> 
> O.
> 

There is actually an alternative, but I believe I remember it being said
that this would go away.  In the meantime, I think it still works and
maybe it could be saved.

The alternative is to define a method opDot() which returns the entity
to forward the call to.

Check out std.typecons:Unique for an example.

-- Chris N-S


Re: alias this question

2011-02-17 Thread Jacob Carlborg

On 2011-02-16 20:42, Christopher Nicholson-Sauls wrote:

On 02/13/11 10:30, Olli Aalto wrote:

I encountered a problem with alias this, when the aliased member is
private. I'm using the latest dmd2. It reports the follwing:
src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?

O.



There is actually an alternative, but I believe I remember it being said
that this would go away.  In the meantime, I think it still works and
maybe it could be saved.

The alternative is to define a method opDot() which returns the entity
to forward the call to.

Check out std.typecons:Unique for an example.

-- Chris N-S


Isn't opDot deprecated in favor of opDispatch?

--
/Jacob Carlborg


Re: alias this question

2011-02-17 Thread spir

On 02/17/2011 11:41 AM, Jacob Carlborg wrote:

On 2011-02-16 20:42, Christopher Nicholson-Sauls wrote:

On 02/13/11 10:30, Olli Aalto wrote:

I encountered a problem with alias this, when the aliased member is
private. I'm using the latest dmd2. It reports the follwing:
src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?

O.



There is actually an alternative, but I believe I remember it being said
that this would go away. In the meantime, I think it still works and
maybe it could be saved.

The alternative is to define a method opDot() which returns the entity
to forward the call to.

Check out std.typecons:Unique for an example.

-- Chris N-S


Isn't opDot deprecated in favor of opDispatch?


I personly need opDot, to customize member access ; not (only) method call.

Denis
--
_
vita es estrany
spir.wikidot.com



Re: alias this question

2011-02-17 Thread Jacob Carlborg

On 2011-02-17 11:54, spir wrote:

On 02/17/2011 11:41 AM, Jacob Carlborg wrote:

On 2011-02-16 20:42, Christopher Nicholson-Sauls wrote:

On 02/13/11 10:30, Olli Aalto wrote:

I encountered a problem with alias this, when the aliased member is
private. I'm using the latest dmd2. It reports the follwing:
src\main.d(14): Error: struct K.K member s is not accessible

If I change the private modifier on the s member to public it works.

Is this as intended, or a bug?

O.



There is actually an alternative, but I believe I remember it being said
that this would go away. In the meantime, I think it still works and
maybe it could be saved.

The alternative is to define a method opDot() which returns the entity
to forward the call to.

Check out std.typecons:Unique for an example.

-- Chris N-S


Isn't opDot deprecated in favor of opDispatch?


I personly need opDot, to customize member access ; not (only) method call.

Denis


I'm pretty sure that you can use the getter/setter syntax with 
opDispatch, anything else is a bug.


--
/Jacob Carlborg


Re: alias this question

2011-02-17 Thread Simen kjaeraas

Jacob Carlborg  wrote:

I'm pretty sure that you can use the getter/setter syntax with  
opDispatch, anything else is a bug.


You can only use one of the two, and yes, the bug is already
filed.

--
Simen


alias 'this' with opCall?

2012-05-17 Thread Mehrdad
Why doesn't opCall() get forwarded by alias this? Is that a bug 
or a feature?


DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


Multiple alias this redux

2015-10-02 Thread Andrei Alexandrescu via Digitalmars-d
Following the approval of his DIP66, Igor Stepanov proceeded with an 
implementation at https://github.com/D-Programming-Language/dmd/pull/3998.


Walter and I objected that the implementation is overly complex. My 
opinion is much weaker than his; I'm not deeply familiar with the dmd 
internals. Iain Buclaw seems to agree with Walter. and Igor has replied 
with additional explanations for the added complexity.


As a result:

* We have no alias this

* The compiler is 2 KLOC smaller/simpler

* The PR has bitrotten

* Igor is probably frustrated

So this is a stalemate that I'd like to see broken. The best solution I 
see with this is a core compiler contributor reviewing Igor's code and 
either:


(a) Assuming Igor is still interested, give concrete, actionable 
guidance to Igor so he can simplify the PR and follow through 
shepherding the PR into dmd;


(b) If Igor is no longer interested, either take over the PR and modify 
it for approval, or implement DIP66 from first principles;


(c) Review the code and discussion, and reach the conclusion the 
proposed implementation is appropriate and no radical simplifications 
are within reach.


Please chime in if you'd like to take this over.


Thanks,

Andrei


UFCS overrides alias this

2015-04-12 Thread Freddy via Digitalmars-d


test.d
struct A{
string b;
alias b this;
}

struct MyRange{

}
char front(MyRange);
void popFront(ref MyRange);
bool empty(MyRange);

void test(A a){
a.empty;
}

$ dmd -o- test
test.d(14): Error: function test.empty (MyRange) is not callable 
using argument types (A)


Is this intended behavior?


Re: alias this constructor

2018-03-24 Thread Jonathan M Davis via Digitalmars-d
On Sunday, March 25, 2018 00:47:20 Dave Jones via Digitalmars-d wrote:
> struct Foo
> {
>  int x;
>  alias x this;
> }
>
> Foo f = 12; // error
>
> Foo foo;
> f = 12; // this is OK
>
> any reason why the first cant be allowed?

Because it was deemed to cause too many problems. C++ code can have quite a
few problems related to all of the implicit conversions it allows with stuff
like constructing objects. Walter decided that D would be better off if it
did not allow such conversions, and as such, D is much pickier about
implicit conversions in general.

Occasionally, the restrictions are annoying, but they also prevent bugs. I
have no idea whether Walter could be convinced at this point to allow some
sort of implicit construction in D or not.

Personally, I tend to think that we'd be better off if we didn't have alias
this at all, because it tends to cause problems in anything outside of
simple use cases (especially with generic code - implicit conversions in
generic code are almost always a terrible idea). Sometimes, it's useful, but
it's often just a recipe for subtle bugs. But at least the fact that D only
allows you to implicitly convert in one direction reduces the problem.

- Jonathan M Davis



Re: alias this constructor

2018-03-24 Thread Adam D. Ruppe via Digitalmars-d

On Sunday, 25 March 2018 at 00:47:20 UTC, Dave Jones wrote:

struct Foo
{
int x;
alias x this;
}

Foo f = 12; // error


You just need to define a constructor that takes an int. alias 
this is all about taking an existing object and substituting a 
member for it - emphasis on *existing* object, so it needs to 
already be constructed.


But you can construct from other types

struct Foo {
   int x;
   this(int x) { this.x = x; }
}

Foo f = 12; // allowed, calls that constructor


Foo foo;
f = 12; // this is OK


Important to note that foo already exists here and is NOT 
reconstructed - the compiler just rewrites that into `f.x = 12;`, 
doing a member assignment.


Re: alias this constructor

2018-03-24 Thread Shachar Shemesh via Digitalmars-d

On 25/03/18 04:51, Jonathan M Davis wrote:

On Sunday, March 25, 2018 00:47:20 Dave Jones via Digitalmars-d wrote:

struct Foo
{
  int x;
  alias x this;
}

Foo f = 12; // error

Foo foo;
f = 12; // this is OK

any reason why the first cant be allowed?


Because it was deemed to cause too many problems. C++ code can have quite a
few problems related to all of the implicit conversions it allows with stuff
like constructing objects. Walter decided that D would be better off if it
did not allow such conversions, and as such, D is much pickier about
implicit conversions in general.


That's a good reason to disallow assignment from int to Foo. I see zero 
sense in allowing assignment and disallowing construction.


*

Technically, I understand the mechanisms at play here. During 
construction, this is a Foo object, and it has no construction from int. 
During assignment, we are allowed to convert a Foo lvalue to a Foo.x 
(int) lvalue, and that gets assigned.


Despite understanding the mechanics, I find the end result surprising 
and unexpected. D makes it damn easy to implicitly expose an inner 
member, and much more difficult to actually do this safely (you have to 
create a property and then alias this that property).


If I'd be building C++ today, I'd replace the "explicit" keyword with 
"implicit" (i.e. - still allow single var constructors to become 
implicit conversion ops, but make that transformation an opt-in rather 
than an opt-out feature). I think that would have been a much better 
approach than what D took.


Shachar


Re: alias this constructor

2018-03-24 Thread Jonathan M Davis via Digitalmars-d
On Sunday, March 25, 2018 06:24:35 Shachar Shemesh via Digitalmars-d wrote:
> On 25/03/18 04:51, Jonathan M Davis wrote:
> > On Sunday, March 25, 2018 00:47:20 Dave Jones via Digitalmars-d wrote:
> >> struct Foo
> >> {
> >>
> >>   int x;
> >>   alias x this;
> >>
> >> }
> >>
> >> Foo f = 12; // error
> >>
> >> Foo foo;
> >> f = 12; // this is OK
> >>
> >> any reason why the first cant be allowed?
> >
> > Because it was deemed to cause too many problems. C++ code can have
> > quite a few problems related to all of the implicit conversions it
> > allows with stuff like constructing objects. Walter decided that D
> > would be better off if it did not allow such conversions, and as such,
> > D is much pickier about implicit conversions in general.
>
> That's a good reason to disallow assignment from int to Foo. I see zero
> sense in allowing assignment and disallowing construction.
>
> *
>
> Technically, I understand the mechanisms at play here. During
> construction, this is a Foo object, and it has no construction from int.
> During assignment, we are allowed to convert a Foo lvalue to a Foo.x
> (int) lvalue, and that gets assigned.
>
> Despite understanding the mechanics, I find the end result surprising
> and unexpected. D makes it damn easy to implicitly expose an inner
> member, and much more difficult to actually do this safely (you have to
> create a property and then alias this that property).

Having something like opImplicitCast would arguably have been better than
alias this.

> If I'd be building C++ today, I'd replace the "explicit" keyword with
> "implicit" (i.e. - still allow single var constructors to become
> implicit conversion ops, but make that transformation an opt-in rather
> than an opt-out feature). I think that would have been a much better
> approach than what D took.

That would be a significant improvement for C++, though over time, I've
increasingly become of the opinion that adding implicit conversions to
user-defined types is more trouble than it's worth. There are certainly
times when it's useful, but it causes enough problems that I'm not at all
convinced that it's ultimately a feature worth having. And with the route
that D went, implicit conversions are arguably crippled anyway. So, we have
a partial solution that isn't really enough to cleanly use implicit
conversions when it might be appropriate, but what we have is still enough
to cause problems.

- Jonathan M Davis



opDispatch and alias this

2018-06-25 Thread Seb via Digitalmars-d
Apparently three years ago it was we decided to ban alias this 
and opDispatch in the same class.

What are your thoughts on this now?
Is anyone depending on using alias this + opDispatch together 
like e.g. in https://github.com/dlang/phobos/pull/6596?


Re: multiple alias this

2018-07-20 Thread Mike Franklin via Digitalmars-d

On Friday, 20 July 2018 at 00:26:43 UTC, Mr.Bingo wrote:

[...]


I didn't read through all of that, but just so you are aware, a 
*multiple alias this* DIP was already approved.  You can find it 
at https://wiki.dlang.org/DIP66


The implementation is already started and you can find it at 
https://github.com/dlang/dmd/pull/8378, but it's a big PR and 
reviewers are going to need time and effort to understand and 
analyze it.  I hope it will be merged this release cycle, but 
that's just my optimism talking.


Mike



alias this on module

2017-04-30 Thread Jonathan Marler via Digitalmars-d
Any reason why "alias this" doesn't work at the module level?  If 
I recall correctly, a module is really just a "class" under the 
hood, but when I tried to use it I got:


Error: alias this can only be a member of aggregate, not module 





Alias this and inheritance

2017-06-05 Thread Jacob Carlborg via Digitalmars-d

The following code does not compile:

void foo(string a) {}

class Base
{
alias bar this;

string bar()
{
return "";
}
}

class Sub : Base {}

void main()
{
auto sub = new Sub;
foo(sub);
}

But if the "alias this" is copied/moved to the subclass it works. Is 
this expected behavior?


--
/Jacob Carlborg


alias this and shadowing

2017-06-15 Thread Jonathan Shamir via Digitalmars-d

I think the following example is legitimate code that should work:

struct S1 {
void foo() {
writeln("S1.foo()");
}
void foo(ulong x) {
writefln("S1.foo(%d)", x);
}
}

struct S2 {
S1 s;
alias s this;

void foo(string str) {
writeln("S2.foo(%s)", str);
}
}

void main() {
S2 s;

s.foo("hahaha");
s.foo(100);  // XXX this doesn't compile, since there's no 
S2.foo that accepts an int

}


To quote Andrei, if it looks like it should work, it should. 
(Also something about turtles).


My original code did something a bit different, just to show 
another example of why this behavior looks fundamentally broken 
to me:


struct S2 {
S1 s;
alias s this;
@disable void foo(ulong); // calling foo(ulong) doesn't make 
sense in the context of S2

}

Now, calling S2.foo() won't compile, since S2 only knows one 
prototype for foo which accepts a ulong.


"Multiple alias this" status?

2016-11-08 Thread Picaud Vincent via Digitalmars-d

Hi All,

I just started to learn a little bit of D.

I read this thread
https://github.com/dlang/dmd/pull/3998

about "Multiple alias this".

I think this feature is very handy, but dmd and gcd compilers 
complain that "there must be only one" alias this.


It is not clear to me if this feature is not available yet or if 
there was a change in the language specifications (Andrei 
Alexandrescu book mentions "§6.13 Multiple subtyping") ?


Does anyone has more information concerning that?

Thanks in advance,
Vincent


multiple `alias this` suggestion

2017-04-19 Thread Carl Sturtivant via Digitalmars-d
Currently only one `alias this` declaration is permitted, and the 
documentation https://dlang.org/spec/class.html#AliasThis says 
the following.


"Multiple AliasThis are allowed. For implicit conversions and 
forwarded lookups, all AliasThis declarations are attempted; if 
more than one AliasThis is eligible, the ambiguity is disallowed 
by raising an error. Note: Multiple AliasThis is currently 
unimplemented."


However the effect of multiple `alias this` declarations can be 
approximated in existing D using only single `alias this`, e.g. 
in the following three members each with `alias this` are 
simulated.


//
struct member1
{
int n1, n2, n3;
}

struct member2
{
int n2, n3;
member1 member;
alias member this;
}

struct member3
{
int n3;
member2 member;
alias member this;
}

struct top
{
member3 member;
alias member this;

this(int i, int j, int k)
{
n1 = i; n2 = j; n3 = k;
}
}


void main()
{
auto x = top(1,2,3);
member3 m3 = x.member;
member2 m2 = m3.member;
member1 m1 = m2.member;

import std.stdio;
writefln("%s %s %s", m1.n1, m1.n2, m1.n3);
writefln("%s %s %s", m2.n1, m2.n2, m2.n3);
writefln("%s %s %s", m3.n1, m3.n2, m3.n3);
writefln("%s %s %s", x.n1, x.n2, x.n3);
}
//

Which outputs the following as expected from chaining the effects 
of `alias this`.


1 0 0
1 2 0
1 2 3
1 2 3

Note that this construction provides a natural hierarchy for name 
lookup, unlike the statement above taken from the documentation.


Imagine the existing single `alias this` is extended to provide 
such a heierarchy of lookups. For example,


struct top
{
mem3 m3;
mem2 m2;
mem1 m1;
alias m3, m2, m1 this;
// ...
}

could be interpreted to mean search for a name in m3 if not found 
in top, and in m2 if not found in m3 and in m1 if not found in 
m2. I don't back the syntax, just the notion.


Maybe that's not all that's expected from "multiple alias this" 
but it would be a clean step forward. Issues?





Re: Multiple Alias This

2009-04-02 Thread Andrei Alexandrescu

dsimcha wrote:

Is the limitation that one may only have one alias this per class/struct a
temporary limitation that will be removed once higher-priority stuff is
finished and some ambiguities are resolved, or are things likely to stay this
way?  On the one hand, allowing multiple alias this would cause ambiguities
similar to multiple inheritance.  On the other hand, only being able to define
one implicit cast per class/struct is pretty limiting and allowing only one
alias this seems like a huge cop-out.


Yah, it's a temporary limitation. However, removing it is nontrivial. D 
tries to avoid first-fit rules and best-fit is difficult.


Note that if you have control over the types you can implement a sort of 
a first-fit by distributing the "alias this" declaration to each type. 
(This is very clumsy.)


Andrei


Re: Doubt about alias this

2012-12-06 Thread Phil Lavoie

Hi,

I tested the code you provided and extended it a little and here 
is the result:


struct bar (bool B, N...) {
 int n = 0;
}

struct foo (N...) {
 bar!(true, N) _bar = void;

 bar!(true, N) getN() {
   return _bar;
 }

 alias getN this;

 public this(T) (T other)
   if (is(T unused : int)) {
   n = other;
 }
}

void aFunc( bar!( true, 8 ) zeBar ) {
  //Subtyping compiles.
}

bar!( true, 8 ) aSecondFunc() {
  return bar!( true, 8 )();
}

struct toto{
  size_t payload;
}

toto aThirdFunc() {
  return toto();
}

void main() {
 import std.stdio;
 foo!8 a = 42;
 writeln(a.n); //Prints 0, as it should.
 aFunc( a ); //The alias this correctly allows for subtyping, as 
advertised
 a.getN().n = 3; //Allowing for rvalue manipulation is indeed 
weird, but apparently in a coherent fashion, not just for the 
alias this case.

 writeln(a.n); //Still prints 0, as it should.
 aSecondFunc().n = 4;
 aThirdFunc().payload = 10; //Without alias this, without 
templates, juste plain rvalue. Another coherent example, yet 
questionably permitted.

}

Therefore, your question, I believe, is more related to rvalues 
directly rather than alias this, if I get your meaning right. The 
question is still very relevant and I was surprised to find out 
about the current behaviors of rvalues.


Re: Alias this and std.traits.isArray

2013-01-05 Thread monarch_dodra

On Saturday, 5 January 2013 at 14:43:49 UTC, David wrote:

This code worked with dmd 2.060:

import std.stdio;
import std.traits;

struct OhWhy(S) {
S[] arr;
alias arr this;
}

void main() {
static assert(isArray!(OhWhy!(float)));

}

But fails with dmd 2.061:
ss.d(10): Error: static assert  (isArray!(OhWhy!(float))) is 
false


(same happens with alias this to static arrays and 
isArray/isStaticArray)



Is this intended or a regression? If latter, I'll submit a 
bug-ticket.


All traits in std trait of the type were explicitly changed to 
return true only if *the exact type* meets the traits requirement.


The rationale is simply tha OhWhy isn't an array. It can be 
implicitly cast to array, but it isn't an array.


This is problematic when instanciating template functions with 
automatic type inference: when you write 
"myTemplateFunction(myOhWhy)", then you will instanciate 
"myTemplateFuction!OhWhy" when what you may have wanted was to 
actually call "myTemplateFunction!(S[])".


The new "isArray" definition protects from that.


Re: Alias this and std.traits.isArray

2013-01-05 Thread Jonathan M Davis
On Saturday, January 05, 2013 22:57:51 monarch_dodra wrote:
> On Saturday, 5 January 2013 at 14:43:49 UTC, David wrote:
> > This code worked with dmd 2.060:
> > 
> > import std.stdio;
> > import std.traits;
> > 
> > struct OhWhy(S) {
> > 
> > S[] arr;
> > alias arr this;
> > 
> > }
> > 
> > void main() {
> > 
> > static assert(isArray!(OhWhy!(float)));
> > 
> > }
> > 
> > But fails with dmd 2.061:
> > ss.d(10): Error: static assert  (isArray!(OhWhy!(float))) is
> > false
> > 
> > (same happens with alias this to static arrays and
> > isArray/isStaticArray)
> > 
> > 
> > Is this intended or a regression? If latter, I'll submit a
> > bug-ticket.
> 
> All traits in std trait of the type were explicitly changed to
> return true only if *the exact type* meets the traits requirement.
> 
> The rationale is simply tha OhWhy isn't an array. It can be
> implicitly cast to array, but it isn't an array.
> 
> This is problematic when instanciating template functions with
> automatic type inference: when you write
> "myTemplateFunction(myOhWhy)", then you will instanciate
> "myTemplateFuction!OhWhy" when what you may have wanted was to
> actually call "myTemplateFunction!(S[])".
> 
> The new "isArray" definition protects from that.

Exactly. The std.traits traits are testing for exact types. If you want to 
test for implicit conversion, then use the : operator. e.g.

static assert(is(OhWhy!float : float[]));

- Jonathan M Davis


Re: Alias this and std.traits.isArray

2013-01-06 Thread David
Thanks for your answers, but:

> Exactly. The std.traits traits are testing for exact types. If you want to 
> test for implicit conversion, then use the : operator. e.g.
> 
> static assert(is(OhWhy!float : float[]));

"OyWhy" is a templated struct for a reason, I have no idea which type of
array is "alias this'ed" is there a way I can check if it's implicitly
convertable to any array type with some `is` magic I am not aware of?



Re: Alias this and std.traits.isArray

2013-01-06 Thread Philippe Sigaud
On Sun, Jan 6, 2013 at 1:36 PM, David  wrote:

> Thanks for your answers, but:
>
> > Exactly. The std.traits traits are testing for exact types. If you want
> to
> > test for implicit conversion, then use the : operator. e.g.
> >
> > static assert(is(OhWhy!float : float[]));
>
> "OyWhy" is a templated struct for a reason, I have no idea which type of
> array is "alias this'ed" is there a way I can check if it's implicitly
> convertable to any array type with some `is` magic I am not aware of?
>
>
Like this?

struct MyType(Elem)
{
Elem[] inner;
alias inner this;
}

void main()
{
static assert(is(MyType!float _ : T[], T));
}


Re: Alias this and std.traits.isArray

2013-01-09 Thread David
> Like this?
> 
> struct MyType(Elem)
> {
> Elem[] inner;
> alias inner this;
> }
> 
> void main()
> {
> static assert(is(MyType!float _ : T[], T));
> }
> 

And how does that work for a static array?


Re: Alias this and std.traits.isArray

2013-01-09 Thread Philippe Sigaud
On Wed, Jan 9, 2013 at 10:57 PM, David  wrote:
>> Like this?
>>
>> struct MyType(Elem)
>> {
>> Elem[] inner;
>> alias inner this;
>> }
>>
>> void main()
>> {
>> static assert(is(MyType!float _ : T[], T));
>> }
>>
>
> And how does that work for a static array?

For a static array, the generic type is T[n], for some T and a size_t n. So:

static assert(is(MyType!float _ : T[n], T, size_t n));


Behaviour of alias this changed

2012-05-08 Thread H. S. Teoh
I have some code along these lines:

struct S {
short[4] data;
alias this data;

string toString() { ... }
}
...
S s;
writeln(to!string(s));

In dmd 2.059 (I believe) and earlier, this calls S.toString(). However,
in git dmd, this calls data.toString() instead.

I'm just curious about the rationale for this change, and whether
there's a way to override the toString() call so that it always calls
S.toString()?


T

-- 
To err is human; to forgive is not our policy. -- Samuel Adler


Re: alias 'this' with opCall?

2012-05-17 Thread H. S. Teoh
On Thu, May 17, 2012 at 08:06:58PM +0200, Mehrdad wrote:
> Why doesn't opCall() get forwarded by alias this? Is that a bug or a
> feature?

Sounds like a bug.


T

-- 
The peace of mind---from knowing that viruses which exploit Microsoft system 
vulnerabilities cannot touch Linux---is priceless. -- Frustrated system 
administrator.


Re: alias 'this' with opCall?

2012-05-17 Thread Mehrdad

okie.

http://d.puremagic.com/issues/show_bug.cgi?id=8113


alias this and immutable shenanigans

2010-08-12 Thread Yao G.

Consider this code:

---
module test;

struct Foo
{
this( int f ) {
_foo = f;
}

@property int baz() {
return _foo;
}

// alias _foo this;
// alias baz this;  

immutable int _foo;
}

struct Bar
{
this( int f ) {
_foo  = Foo(f);
}

private:
immutable Foo _foo;
}
---

If I uncomment the alias _foo this line, I get the following error message:

% Test.d(22): Error: can only initialize const member _foo inside  
constructor


WTF! I'm initializing it in a constructor! Is this a bug? Or by design you  
cannot alias this to a immutable member of a struct. It seems that there's  
a hidden temp created that wants to initialize the field. Also, I wanted  
to alias the property Foo.baz, but it also caused the following errors:


% Test.d(22): Error: function test.Foo.baz () is not callable using  
argument types (Foo) immutable
% Test.d(22): Error: expected 0 arguments, not 1 for non-variadic function  
type @property int()


It seems that somehow the property is used as a "setter", not as a  
"getter".


So, my questions are:
1. Why is disallowed to alias this an immutable data inside a struct?
2. Why is disallowed to alias this a struct "getter" property?


--
Yao G.


bug? alias this <-> opDispatch interaction

2013-11-09 Thread Luís.Marques
I'm experimenting with several designs and I think I might have 
hit a bug, but I wanted to confirm it. Is this a bug?


class A
{
void opDispatch(string name, T...)(T msg) {}
}

class B : A
{
C obj;
alias obj this;

@disable void opDispatch(string name, T...)(T msg);
}

class C
{
void foo() {}
}

void main()
{
auto b = new B;
b.foo();
}

 Output:

Error: no property 'foo' for type 'B'

Disabling the opDispatch that B inherits from A also seems to 
disable B's alias this to C. The @disable works well in isolation 
-- as does the alias this, of course.


My current workaround:

class B : A
{
C obj;

void opDispatch(string name, T...)(T msg)
{
mixin("obj." ~ name ~ "();");
}
}

(which now makes me wonder what actually are the differences 
between those two...)


BTW, I was asking in the IRC channel (I should have discovered 
that lovely place earlier!) about the following:


1:T[string] foo;
2:foo[""] = new T;
3:foo[null] = new T;

Lines 2 and 3 seem to do the same, apparently. People seemed to 
agree that 3 should not be relied upon (should it?), but if I 
recall/understand it was not totally clear to people why 2 and 3 
*do* do the same thing, so feel free to clarify.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Steven Schveighoffer via Digitalmars-d

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.

Hm... not sure you need a DIP.

From page 231 of TDPL: "A class could introduce any number of alias 
this declarations, thus subtyping any number of types."


-Steve


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d
On Friday, 10 October 2014 at 17:31:23 UTC, Steven Schveighoffer 
wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.

Hm... not sure you need a DIP.

From page 231 of TDPL: "A class could introduce any number of 
alias this declarations, thus subtyping any number of types."


-Steve


TDPL tells that multiple alias this should be allowed, but tell 
nothing about conflict resolving. General idea of this DIP is 
sistematize rules for alias this. Please comment this part. Maybe 
I've forgot some cases, maybe introduce dangerous semantic rule.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Brad Anderson via Digitalmars-d
On Friday, 10 October 2014 at 17:31:23 UTC, Steven Schveighoffer 
wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.

Hm... not sure you need a DIP.

From page 231 of TDPL: "A class could introduce any number of 
alias this declarations, thus subtyping any number of types."


-Steve


Igor was asked to write a DIP for it by Walter and Andrei. Here's 
the context: 
https://github.com/D-Programming-Language/dmd/pull/3998#issuecomment-58286631


Re: DIP66 - Multiple alias this

2014-10-10 Thread Andrei Alexandrescu via Digitalmars-d

On 10/10/14, 10:09 AM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


Thanks, will do. Everybody interested please chime in! -- Andrei


Re: DIP66 - Multiple alias this

2014-10-10 Thread Andrei Alexandrescu via Digitalmars-d

On 10/10/14, 10:31 AM, Steven Schveighoffer wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.

Hm... not sure you need a DIP.

 From page 231 of TDPL: "A class could introduce any number of alias
this declarations, thus subtyping any number of types."


TDPL is not reference. The DIP should cover various corner cases. -- Andrei



Re: DIP66 - Multiple alias this

2014-10-10 Thread Steven Schveighoffer via Digitalmars-d

On 10/10/14 2:17 PM, Andrei Alexandrescu wrote:

On 10/10/14, 10:31 AM, Steven Schveighoffer wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.

Hm... not sure you need a DIP.

 From page 231 of TDPL: "A class could introduce any number of alias
this declarations, thus subtyping any number of types."


TDPL is not reference. The DIP should cover various corner cases. -- Andrei



OK, thanks everyone. I thought DIPs were specifically for proposals that 
had not been already approved.


-Steve


Re: DIP66 - Multiple alias this

2014-10-10 Thread Brian Schott via Digitalmars-d

On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


There is an error in the wiki formatting in the second code 
block. (`{| class="wikitable"` should not be there)


I don't see any problems with the actual content of the DIP.


Re: DIP66 - Multiple alias this

2014-10-10 Thread via Digitalmars-d

On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


I understand that as a first step it was suggested to implement 
the strictest behaviour regarding conflicts, namely to disallow 
them entirely.


However, I think more permissive strategies are useful, like in 
this example:

https://github.com/D-Programming-Language/dmd/pull/3998#issuecomment-58570742

Conflict resolution can work like overload resolution, with 
different levels of matching and partial ordering.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Steven Schveighoffer via Digitalmars-d

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


This part:

void test()
{
C c;
int i = c; //Error: c.a.i vs c.b.i
}

static assert(is(C : int)); //Ok, because C is subtype of int anyway.

I think might be wrong. There is a lot of code out there that says, e.g.:

void foo(T)(T t) if(is(T : U))
{
  U u = t;
  ...
}

Which will now create an error in the wrong place. IMO, the 'is' test 
should also fail.


-Steve


Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 10:09 AM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


Thanks, Igor!


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d


Which will now create an error in the wrong place. IMO, the 
'is' test should also fail.


-Steve


In this case, you will see the real error and will able to fix 
if. For example call foo(c.a); Otherwice, you possible error will 
be fixed without taking into account your opinions.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 20:29:43 UTC, Brian Schott wrote:

On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


There is an error in the wiki formatting in the second code 
block. (`{| class="wikitable"` should not be there)


I don't see any problems with the actual content of the DIP.


Fixed. This is starnge implicit copy-paste of my text editor =/


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d
On Friday, 10 October 2014 at 20:47:45 UTC, Steven Schveighoffer 
wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


This part:

void test()
{
C c;
int i = c; //Error: c.a.i vs c.b.i
}

static assert(is(C : int)); //Ok, because C is subtype of 
int anyway.


I think might be wrong. There is a lot of code out there that 
says, e.g.:


void foo(T)(T t) if(is(T : U))
{
  U u = t;
  ...
}

Which will now create an error in the wrong place. IMO, the 
'is' test should also fail.


-Steve


I thought exactly about this using case.

See:
You have a struct like this in first place:
struct A
{
int i;
alias i this;
}

struct C
{
A a;
string s;
alias a this;
alias s this;
}

And you have a template function in second place:
void foo(T)(T t) if(is(T : int))
{
...
}

void foo(T)(T t) if(is(T : string))
{
...
}


And you have the code it third place:
C c;
foo(c); //Error: what do you mean: foo!(T : string) or foo!(T : 
int)


Now, someone (A developer) changed the A definition:

struct A
{
int i;
alias i this;
}

struct B
{
int i;
alias i this;
}

struct C
{
A a;
B b;
string s;
alias a this;
alias b this;
alias s this;
}

And now, you code mystically start to works.
Attention: Infusing in one place conflict resolves conflict in 
another place.

It is danger, I think.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Steven Schveighoffer via Digitalmars-d

On 10/10/14 5:15 PM, IgorStepanov wrote:

On Friday, 10 October 2014 at 20:47:45 UTC, Steven Schveighoffer wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


This part:

void test()
{
C c;
int i = c; //Error: c.a.i vs c.b.i
}

static assert(is(C : int)); //Ok, because C is subtype of int anyway.

I think might be wrong. There is a lot of code out there that says, e.g.:

void foo(T)(T t) if(is(T : U))
{
  U u = t;
  ...
}

Which will now create an error in the wrong place. IMO, the 'is' test
should also fail.

-Steve


I thought exactly about this using case.

See:
You have a struct like this in first place:
 struct A
 {
 int i;
 alias i this;
 }

 struct C
 {
 A a;
 string s;
 alias a this;
 alias s this;
 }

And you have a template function in second place:
void foo(T)(T t) if(is(T : int))
{
...
}

void foo(T)(T t) if(is(T : string))
{
...
}


And you have the code it third place:
C c;
foo(c); //Error: what do you mean: foo!(T : string) or foo!(T : int)


I agree with all this.


Now, someone (A developer) changed the A definition:

 struct A
 {
 int i;
 alias i this;
 }

 struct B
 {
 int i;
 alias i this;
 }

 struct C
 {
 A a;
 B b;
 string s;
 alias a this;
 alias b this;
 alias s this;
 }

And now, you code mystically start to works.


Why? It's just as confused as before, no?

The way the DIP reads, the call to foo(c) compiles, but the 
instantiation fails. This can cause subtle issues when you want to 
select an instantiation based on what it casts to.


An example:

foo(T)(T t) if(is(T : int))
{
   someFuncThatTakesInt(t);
}

foo(T)(T t) if(!is(T : int) && is(T.shadow : int))
{
   someFuncThatTakesInt(t.shadow);
}

struct A
{
   int i;
   alias i this;
}

struct B
{
   int i;
   alias i this;
}

struct C
{
   A a;
   B shadow;
   alias a this;
   alias shadow this;
}

C c;
foo(c); // should compile, but I think your DIP makes it fail due to 
ambiguity


-Steve


Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 10:09 AM, IgorStepanov wrote:

Please, comment it.


> static assert(is(C : int)); //Ok, because C is subtype of int anyway.

Comment should say that C is implicitly convertible to int

struct Test1
{
int a;
int b;
alias a this;
alias b this; //Error: alias b this conflicts with alias a this;
}

DIP says this is "obviously incorrect", but what rule is being applied? I 
suspect the rule here is if typeof(a)==typeof(b), then it is rejected.


What if typeof(a) is implicitly convertible to typeof(b), and vice-versa?

Is alias this resolved before base class search, after base class search, or is 
it an error if both searches are successful?


If 'a' and 'b' both contain overloads for function foo, then it should behave 
like imports do (which is a bit complex).



Essentially, the rules for multiple alias this should be the same as for 
multiple imports and multiple mixin templates. These rules work, and the 
consistency will be expected.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 20:44:11 UTC, Marc Schütz wrote:

On Friday, 10 October 2014 at 17:09:08 UTC, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


I understand that as a first step it was suggested to implement 
the strictest behaviour regarding conflicts, namely to disallow 
them entirely.


However, I think more permissive strategies are useful, like in 
this example:

https://github.com/D-Programming-Language/dmd/pull/3998#issuecomment-58570742

Conflict resolution can work like overload resolution, with 
different levels of matching and partial ordering.


There isn't hard to change resolving strategy. This will need to 
change one function definition.
Thus we able to implement strictest now and after some time of 
new feature using, relax the behaviour. This will not require 
significant efforts.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 21:25:17 UTC, Walter Bright wrote:

On 10/10/2014 10:09 AM, IgorStepanov wrote:

Please, comment it.


> static assert(is(C : int)); //Ok, because C is subtype of int
anyway.

Comment should say that C is implicitly convertible to int


Not really.
int i = C(); //conflict: c.a.i vs c.b.i (thus, C is not 
implicitly convertible to int)



struct Test1
{
int a;
int b;
alias a this;
alias b this; //Error: alias b this conflicts with 
alias a this;

}

DIP says this is "obviously incorrect", but what rule is being 
applied? I suspect the rule here is if typeof(a)==typeof(b), 
then it is rejected.


What if typeof(a) is implicitly convertible to typeof(b), and 
vice-versa?


In current state, if "typeof(a) is implicitly convertible to 
typeof(b), and vice-versa", compiler will accept this alias this 
declaration.

However error may be raised at alias this resolving stage.

Is alias this resolved before base class search, after base 
class search, or is it an error if both searches are successful?


In existing alias this implementation alias this resolved after 
base class search.  This DIP inherits it, thus now I suggest to 
check base classes before alias this. Is it acceptable? Should I 
add this into DIP?


If 'a' and 'b' both contain overloads for function foo, then it 
should behave like imports do (which is a bit complex).


Hmm. Now it works as I wrote it DIP pseudo-code:
struct A
{
void foo(string);
void foo(int);
}

struct B
{
void foo(double);
}

struct C
{
A a;
B b;
alias a this;
alias b this;
}

C.foo("test"); //found only one acceptable foo: C.a.foo(string)
C.foo(5);  //1. Check a: found C.a.foo(int);
   //2. Check b: found C.b.foo(double);
   //3. Raise error: C.a.foo(int) vs C.b.foo(double) 
conflict

C.foo(5.0);//found only one acceptable foo: C.b.foo(double)

Is it Ok?

Essentially, the rules for multiple alias this should be the 
same as for multiple imports and multiple mixin templates. 
These rules work, and the consistency will be expected.


Where can I read about multiple mixin templates?


Re: DIP66 - Multiple alias this

2014-10-10 Thread Timon Gehr via Digitalmars-d

On 10/10/2014 11:25 PM, Walter Bright wrote:


Essentially, the rules for multiple alias this should be the same as for
multiple imports and multiple mixin templates. These rules work, and the
consistency will be expected.


Agreed. Do you suggest to overload alias this against imports and mixin 
templates?


Re: DIP66 - Multiple alias this

2014-10-10 Thread Timon Gehr via Digitalmars-d

On 10/10/2014 07:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


- "C c;
int i = c; //Error: c.a.i vs c.b.i

static assert(is(C : int)); //Ok, because C is subtype of int anyway."

So now we can have 'subtypes' whose instances cannot be stored in 
variables of the 'base type'?


Such behaviour is inconsistent with both the reference implementation 
and the documentation (and the two happen to be mutually inconsistent on 
how 'is(:)' should behave as well. :o) )



- "The following pseudo-code illustrates this: [...] Finally, if 
resultSet contains only one candidate, the compiler will accept it."


This process might very well never terminate but it could terminate in 
more cases if it did something better than the naive brute-force search. 
I.e. either report cycles or don't keep exploring around cycles, but 
just looping indefinitely on cycles like the following is IMO not a good 
course of action:


struct S{
alias get this;
T get(){ return T.init; }
}
struct T{
alias get this;
S get(){ return S.init; }
int x;
alias x this;
}

void main(){
S s;
int x=s;
}

Furthermore, the following code compiles now, but doesn't under the 
approach described in the DIP. Is this an actual regression your pull 
introduces or is there a bug in the pseudocode?:


class A{
alias x this;
int x;
}

class B: A{
alias y this;
int y;
}

void main(){
int x = new B();
}

The same issue also needs to be considered if A and B are structs 
instead and B has an additional alias this to an A (the solution might 
also be part of a fix for the cycle issue).


- "If resultSet contains more then one candidates, the compiler raises 
an error."


Why? The language already has a way to deal with cross-scope overload 
resolution. (Also, what makes candidates different?)





Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d
On Friday, 10 October 2014 at 21:26:49 UTC, Steven Schveighoffer 
wrote:

On 10/10/14 5:15 PM, IgorStepanov wrote:
On Friday, 10 October 2014 at 20:47:45 UTC, Steven 
Schveighoffer wrote:

On 10/10/14 1:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


This part:

void test()
   {
   C c;
   int i = c; //Error: c.a.i vs c.b.i
   }

   static assert(is(C : int)); //Ok, because C is subtype of 
int anyway.


I think might be wrong. There is a lot of code out there that 
says, e.g.:


void foo(T)(T t) if(is(T : U))
{
 U u = t;
 ...
}

Which will now create an error in the wrong place. IMO, the 
'is' test

should also fail.

-Steve


I thought exactly about this using case.

See:
You have a struct like this in first place:
struct A
{
int i;
alias i this;
}

struct C
{
A a;
string s;
alias a this;
alias s this;
}

And you have a template function in second place:
void foo(T)(T t) if(is(T : int))
{
...
}

void foo(T)(T t) if(is(T : string))
{
...
}


And you have the code it third place:
C c;
foo(c); //Error: what do you mean: foo!(T : string) or foo!(T 
: int)


I agree with all this.


Now, someone (A developer) changed the A definition:

struct A
{
int i;
alias i this;
}

struct B
{
int i;
alias i this;
}

struct C
{
A a;
B b;
string s;
alias a this;
alias b this;
alias s this;
}

And now, you code mystically start to works.


Why? It's just as confused as before, no?

The way the DIP reads, the call to foo(c) compiles, but the 
instantiation fails. This can cause subtle issues when you want 
to select an instantiation based on what it casts to.


An example:

foo(T)(T t) if(is(T : int))
{
   someFuncThatTakesInt(t);
}

foo(T)(T t) if(!is(T : int) && is(T.shadow : int))
{
   someFuncThatTakesInt(t.shadow);
}

struct A
{
   int i;
   alias i this;
}

struct B
{
   int i;
   alias i this;
}

struct C
{
   A a;
   B shadow;
   alias a this;
   alias shadow this;
}

C c;
foo(c); // should compile, but I think your DIP makes it fail 
due to ambiguity


-Steve


You can write foo(c.shadow); This isn't hard.
Ok, I understood you, let's listen to what others say


Re: DIP66 - Multiple alias this

2014-10-10 Thread Timon Gehr via Digitalmars-d

On 10/11/2014 12:07 AM, IgorStepanov wrote:

On Friday, 10 October 2014 at 21:25:17 UTC, Walter Bright wrote:


If 'a' and 'b' both contain overloads for function foo, then it should
behave like imports do (which is a bit complex).


Hmm. Now it works as I wrote it DIP pseudo-code:


The pseudo-code doesn't actually specify that the arguments the 
identifier is being called with are considered at all.



struct A
{
 void foo(string);
 void foo(int);
}

struct B
{
 void foo(double);
}

struct C
{
 A a;
 B b;
 alias a this;
 alias b this;
}

C.foo("test"); //found only one acceptable foo: C.a.foo(string)
C.foo(5);  //1. Check a: found C.a.foo(int);
//2. Check b: found C.b.foo(double);
//3. Raise error: C.a.foo(int) vs C.b.foo(double) conflict
C.foo(5.0);//found only one acceptable foo: C.b.foo(double)

Is it Ok?
...


That is the right behaviour. What happens in this case:

struct A{
void foo(int);
void foo(double);
}

struct B
void foo(string);
}

... // (struct C and calls as yours)



Is it correct that the DIP makes imports at aggregate scope shadow alias 
this lookups?


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 22:05:18 UTC, Timon Gehr wrote:

On 10/10/2014 07:09 PM, IgorStepanov wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


- "C c;
int i = c; //Error: c.a.i vs c.b.i

static assert(is(C : int)); //Ok, because C is subtype of int 
anyway."


So now we can have 'subtypes' whose instances cannot be stored 
in variables of the 'base type'?


C++ allowed subtypes, which can not be casted to the base type 
(inheritance of two identical, non-virtual base classes).
Ok, I've wrote my position, understood your and wait the decision 
of the arbitrator:)


Such behaviour is inconsistent with both the reference 
implementation and the documentation (and the two happen to be 
mutually inconsistent on how 'is(:)' should behave as well. :o) 
)



- "The following pseudo-code illustrates this: [...] Finally, 
if resultSet contains only one candidate, the compiler will 
accept it."


This process might very well never terminate but it could 
terminate in more cases if it did something better than the 
naive brute-force search. I.e. either report cycles or don't 
keep exploring around cycles, but just looping indefinitely on 
cycles like the following is IMO not a good course of action:


struct S{
alias get this;
T get(){ return T.init; }
}
struct T{
alias get this;
S get(){ return S.init; }
int x;
alias x this;
}

void main(){
S s;
int x=s;
}


This case described in DIP below.
Recursion tree will be like:
s.get
   s.get.get ->return, because T is already visited
s.x -> win

Furthermore, the following code compiles now, but doesn't under 
the approach described in the DIP. Is this an actual regression 
your pull introduces or is there a bug in the pseudocode?:


class A{
alias x this;
int x;
}

class B: A{
alias y this;
int y;
}

void main(){
int x = new B();
}

The same issue also needs to be considered if A and B are 
structs instead and B has an additional alias this to an A (the 
solution might also be part of a fix for the cycle issue).


- "If resultSet contains more then one candidates, the compiler 
raises an error."


struct A
{
   short s;
   alias s this;
}

struct B
{
   int i;
   alias i this;
}

struct C
{
   A a;
   B b;
   alias a this;
   alias b this;
}

long l = C(); //What do you suggest?


Re: DIP66 - Multiple alias this

2014-10-10 Thread Joseph Rushton Wakeling via Digitalmars-d

On 10/10/14 19:09, IgorStepanov via Digitalmars-d wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


This may be beyond the scope of the DIP, but is there any intention (or any 
need?) to set rules for how alias this should behave in the case of different 
protection levels for the base type and the alias?


I ask because there is a known issue related to this:
https://issues.dlang.org/show_bug.cgi?id=10996

... but also because any rules set for this, might in principle affect the 
desirable priority rules for multiple alias this too.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 3:06 PM, Timon Gehr wrote:

On 10/10/2014 11:25 PM, Walter Bright wrote:


Essentially, the rules for multiple alias this should be the same as for
multiple imports and multiple mixin templates. These rules work, and the
consistency will be expected.


Agreed. Do you suggest to overload alias this against imports and mixin 
templates?


I hadn't thought of that (thanks for bringing it up). My first thought is no. 
Alias this gets searched after those do, because it comes into play only when 
the symbol isn't resolved in the scope.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 22:18:36 UTC, Timon Gehr wrote:

On 10/11/2014 12:07 AM, IgorStepanov wrote:
On Friday, 10 October 2014 at 21:25:17 UTC, Walter Bright 
wrote:


If 'a' and 'b' both contain overloads for function foo, then 
it should

behave like imports do (which is a bit complex).


Hmm. Now it works as I wrote it DIP pseudo-code:


The pseudo-code doesn't actually specify that the arguments the 
identifier is being called with are considered at all.



struct A
{
void foo(string);
void foo(int);
}

struct B
{
void foo(double);
}

struct C
{
A a;
B b;
alias a this;
alias b this;
}

C.foo("test"); //found only one acceptable foo: C.a.foo(string)
C.foo(5);  //1. Check a: found C.a.foo(int);
   //2. Check b: found C.b.foo(double);
   //3. Raise error: C.a.foo(int) vs 
C.b.foo(double) conflict

C.foo(5.0);//found only one acceptable foo: C.b.foo(double)

Is it Ok?
...


That is the right behaviour. What happens in this case:

struct A{
void foo(int);
void foo(double);
}

struct B
void foo(string);
}

... // (struct C and calls as yours)


C.foo("test"); //Ok, C.b.foo(string);
C.foo(5);  //Ok, C.a.foo(int);
C.foo(5.0);//Ok, C.a.foo(double);

Compiler simply tries to forward c.foo(ARG) -> c.a.foo(ARG) and 
c.b.foo(ARG). If only one is correct, compiler will accept it. If 
both is correct, compiler will raise an error.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Timon Gehr via Digitalmars-d

On 10/11/2014 12:29 AM, Walter Bright wrote:

On 10/10/2014 3:06 PM, Timon Gehr wrote:

On 10/10/2014 11:25 PM, Walter Bright wrote:


Essentially, the rules for multiple alias this should be the same as for
multiple imports and multiple mixin templates. These rules work, and the
consistency will be expected.


Agreed. Do you suggest to overload alias this against imports and
mixin templates?


I hadn't thought of that (thanks for bringing it up). My first thought
is no. Alias this gets searched after those do, because it comes into
play only when the symbol isn't resolved in the scope.


This allows for symbol hijacking (this is also the current behaviour):

// ---

module m;
import std.stdio;
// void foo(int x){ writeln("hi from m"); } // uncomment to hijack

// ---

module main;
import std.stdio;

struct T{
import m;
alias s this;
S s;
}


struct S{
void foo(int x){ writeln("hi from S"); }
}

void main(){
T t;
t.foo(1);
}


Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 3:20 PM, IgorStepanov wrote:

The same issue also needs to be considered if A and B are structs instead and
B has an additional alias this to an A (the solution might also be part of a
fix for the cycle issue).

- "If resultSet contains more then one candidates, the compiler raises an 
error."


struct A
{
short s;
alias s this;
}

struct B
{
int i;
alias i this;
}

struct C
{
A a;
B b;
alias a this;
alias b this;
}

long l = C(); //What do you suggest?


The rule would be if:

   long l = C.a();
   long l = C.b();

both compile, then:

   long l = C();

must be an error, even if one of C.a() or C.b() might be a "better" match. This 
is how things work for template mixins and imports.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 3:27 PM, Joseph Rushton Wakeling via Digitalmars-d wrote:

On 10/10/14 19:09, IgorStepanov via Digitalmars-d wrote:

I've created DIP for my pull request.
DIP: http://wiki.dlang.org/DIP66
PR: https://github.com/D-Programming-Language/dmd/pull/3998

Please, comment it.


This may be beyond the scope of the DIP, but is there any intention (or any
need?) to set rules for how alias this should behave in the case of different
protection levels for the base type and the alias?


I like the C++ rule that says that access control is not considered for name 
lookup. I know it makes for some annoying results, but the simplicity of the 
rule makes it much more understandable.




I ask because there is a known issue related to this:
https://issues.dlang.org/show_bug.cgi?id=10996

... but also because any rules set for this, might in principle affect the
desirable priority rules for multiple alias this too.




Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 3:46 PM, Timon Gehr wrote:

On 10/11/2014 12:29 AM, Walter Bright wrote:

On 10/10/2014 3:06 PM, Timon Gehr wrote:

On 10/10/2014 11:25 PM, Walter Bright wrote:


Essentially, the rules for multiple alias this should be the same as for
multiple imports and multiple mixin templates. These rules work, and the
consistency will be expected.


Agreed. Do you suggest to overload alias this against imports and
mixin templates?


I hadn't thought of that (thanks for bringing it up). My first thought
is no. Alias this gets searched after those do, because it comes into
play only when the symbol isn't resolved in the scope.


This allows for symbol hijacking (this is also the current behaviour):

// ---

module m;
import std.stdio;
// void foo(int x){ writeln("hi from m"); } // uncomment to hijack

// ---

module main;
import std.stdio;

struct T{
 import m;
 alias s this;
 S s;
}


struct S{
 void foo(int x){ writeln("hi from S"); }
}

void main(){
 T t;
 t.foo(1);
}


Hmm. Good point. The alias this should be done before imports.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:

On 10/10/2014 3:20 PM, IgorStepanov wrote:
The same issue also needs to be considered if A and B are 
structs instead and
B has an additional alias this to an A (the solution might 
also be part of a

fix for the cycle issue).

- "If resultSet contains more then one candidates, the 
compiler raises an error."


struct A
{
   short s;
   alias s this;
}

struct B
{
   int i;
   alias i this;
}

struct C
{
   A a;
   B b;
   alias a this;
   alias b this;
}

long l = C(); //What do you suggest?


The rule would be if:

   long l = C.a();
   long l = C.b();

both compile, then:

   long l = C();

must be an error, even if one of C.a() or C.b() might be a 
"better" match. This is how things work for template mixins and 
imports.

So it is.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

BTW.

Overloaded functions in PR resolves un-properly (raises error 
even if can be resolved correct function)

However it's easy to fix and I'll do it tomorrow.


Re: DIP66 - Multiple alias this

2014-10-10 Thread IgorStepanov via Digitalmars-d

On Friday, 10 October 2014 at 22:51:34 UTC, Walter Bright wrote:

On 10/10/2014 3:46 PM, Timon Gehr wrote:

On 10/11/2014 12:29 AM, Walter Bright wrote:

On 10/10/2014 3:06 PM, Timon Gehr wrote:

On 10/10/2014 11:25 PM, Walter Bright wrote:


Essentially, the rules for multiple alias this should be 
the same as for
multiple imports and multiple mixin templates. These rules 
work, and the

consistency will be expected.


Agreed. Do you suggest to overload alias this against 
imports and

mixin templates?


I hadn't thought of that (thanks for bringing it up). My 
first thought
is no. Alias this gets searched after those do, because it 
comes into

play only when the symbol isn't resolved in the scope.


This allows for symbol hijacking (this is also the current 
behaviour):


// ---

module m;
import std.stdio;
// void foo(int x){ writeln("hi from m"); } // uncomment to 
hijack


// ---

module main;
import std.stdio;

struct T{
import m;
alias s this;
S s;
}


struct S{
void foo(int x){ writeln("hi from S"); }
}

void main(){
T t;
t.foo(1);
}


Hmm. Good point. The alias this should be done before imports.


Symmetrically. You may use symbol from import, uncomment it in 
aliased type and hijack it.


Re: DIP66 - Multiple alias this

2014-10-10 Thread Walter Bright via Digitalmars-d

On 10/10/2014 4:23 PM, IgorStepanov wrote:

On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:

must be an error, even if one of C.a() or C.b() might be a "better" match.
This is how things work for template mixins and imports.

So it is.


Good!

The same rule applies for overloading.


Re: DIP66 - Multiple alias this

2014-10-11 Thread Jacob Carlborg via Digitalmars-d

On 2014-10-11 00:52, Walter Bright wrote:


I like the C++ rule that says that access control is not considered for
name lookup. I know it makes for some annoying results, but the
simplicity of the rule makes it much more understandable.


I'm not so sure about that. Perhaps it makes it more understandable for 
a language designer. But not for a user. You try to call a function but 
you get a conflict with a private symbol. The user will get frustrated 
thinking: "stupid compiler, of course I want to call the public function".


--
/Jacob Carlborg


Re: DIP66 - Multiple alias this

2014-10-11 Thread IgorStepanov via Digitalmars-d

On Saturday, 11 October 2014 at 00:00:48 UTC, Walter Bright wrote:

On 10/10/2014 4:23 PM, IgorStepanov wrote:
On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright 
wrote:
must be an error, even if one of C.a() or C.b() might be a 
"better" match.

This is how things work for template mixins and imports.

So it is.


Good!

The same rule applies for overloading.


I've implemented overloading:
https://github.com/D-Programming-Language/dmd/pull/3998/files#diff-17b22eae29e74ce6ec29037438b5031cR2136

Please, tell me, what changes should I make to the DIP as a 
result of yesterday's discussions.

And please, tell your opinion about "is" issue:

class A
{
   int i;
   alias i this;
}

class B
{
   int i;
   alias i this;
}

class C
{
   A a;
   B b;
   alias a this;
   alias b this;
}

void foo(T)(T arg) if(is(T : int))
{
   ...
}

foo(C()); //Should it pass or not?


Re: DIP66 - Multiple alias this

2014-10-11 Thread Walter Bright via Digitalmars-d

On 10/11/2014 3:42 AM, Jacob Carlborg wrote:

On 2014-10-11 00:52, Walter Bright wrote:


I like the C++ rule that says that access control is not considered for
name lookup. I know it makes for some annoying results, but the
simplicity of the rule makes it much more understandable.


I'm not so sure about that. Perhaps it makes it more understandable for a
language designer. But not for a user. You try to call a function but you get a
conflict with a private symbol. The user will get frustrated thinking: "stupid
compiler, of course I want to call the public function".


The theory is that simpler rules are better than complex rules, even if the 
simpler rules aren't always ideal.




Re: DIP66 - Multiple alias this

2014-10-11 Thread Walter Bright via Digitalmars-d

On 10/11/2014 7:23 AM, IgorStepanov wrote:

On Saturday, 11 October 2014 at 00:00:48 UTC, Walter Bright wrote:

On 10/10/2014 4:23 PM, IgorStepanov wrote:

On Friday, 10 October 2014 at 22:50:25 UTC, Walter Bright wrote:

must be an error, even if one of C.a() or C.b() might be a "better" match.
This is how things work for template mixins and imports.

So it is.


Good!

The same rule applies for overloading.


I've implemented overloading:
https://github.com/D-Programming-Language/dmd/pull/3998/files#diff-17b22eae29e74ce6ec29037438b5031cR2136


Please, tell me, what changes should I make to the DIP as a result of
yesterday's discussions.


At the very least, it should say it resolves ambiguities the same way that 
imports and template mixins do.




And please, tell your opinion about "is" issue:

class A
{
int i;
alias i this;
}

class B
{
int i;
alias i this;
}

class C
{
A a;
B b;
alias a this;
alias b this;
}

void foo(T)(T arg) if(is(T : int))
{
...
}

foo(C()); //Should it pass or not?


There's a rule with imports that if the same symbol is reachable via multiple 
paths through the imports, that it is not an ambiguity error. Here, the same 
type is reachable through multiple alias this paths, so by analogy it shouldn't 
be an error.


Re: DIP66 - Multiple alias this

2014-10-12 Thread via Digitalmars-d

On Sunday, 12 October 2014 at 04:31:22 UTC, Walter Bright wrote:

On 10/11/2014 7:23 AM, IgorStepanov wrote:

class A
{
   int i;
   alias i this;
}

class B
{
   int i;
   alias i this;
}

class C
{
   A a;
   B b;
   alias a this;
   alias b this;
}

void foo(T)(T arg) if(is(T : int))
{
   ...
}

foo(C()); //Should it pass or not?


There's a rule with imports that if the same symbol is 
reachable via multiple paths through the imports, that it is 
not an ambiguity error. Here, the same type is reachable 
through multiple alias this paths, so by analogy it shouldn't 
be an error.


It's the same type, but different symbols; actual accesses would 
be ambiguous. `is(T : int)` shouldn't evaluate to true if `int a 
= T.init;` would fail.


Re: DIP66 - Multiple alias this

2014-10-12 Thread Joseph Rushton Wakeling via Digitalmars-d

On 11/10/14 00:52, Walter Bright via Digitalmars-d wrote:

I like the C++ rule that says that access control is not considered for name
lookup. I know it makes for some annoying results, but the simplicity of the
rule makes it much more understandable.


That's fine.  I just wanted to be sure that there wasn't a risk of multiple 
alias this breaking in unpleasant ways, if/when 
https://issues.dlang.org/show_bug.cgi?id=10996 is fixed.




Re: DIP66 - Multiple alias this

2014-10-12 Thread IgorStepanov via Digitalmars-d

On Sunday, 12 October 2014 at 08:36:05 UTC, Marc Schütz wrote:

On Sunday, 12 October 2014 at 04:31:22 UTC, Walter Bright wrote:

On 10/11/2014 7:23 AM, IgorStepanov wrote:

class A
{
  int i;
  alias i this;
}

class B
{
  int i;
  alias i this;
}

class C
{
  A a;
  B b;
  alias a this;
  alias b this;
}

void foo(T)(T arg) if(is(T : int))
{
  ...
}

foo(C()); //Should it pass or not?


There's a rule with imports that if the same symbol is 
reachable via multiple paths through the imports, that it is 
not an ambiguity error. Here, the same type is reachable 
through multiple alias this paths, so by analogy it shouldn't 
be an error.


It's the same type, but different symbols; actual accesses 
would be ambiguous. `is(T : int)` shouldn't evaluate to true if 
`int a = T.init;` would fail.


I found an example of a situation that is bothering me.
Let we have a persistence framework, which provides a storing D 
object in some persistence storage: DB, file et c.


In introduces paired functions store/load and special type 
PersistenceObject.


If stored type is subtype of PersistenceObject it converts to 
PersistenceObject and PersistenceObject.load(stream) called for 
loading object (and PersistenceObject.store(stream) for storing).
Otherwice if object can't be converted to PersistenceObject it 
should be serialized via "serialize" function (or deserialized 
via "deserialize").


struct PersistenceFramework
{
   void store(T)(T arg) if (is(T : PersistenceObject))
   {
   PersistenceObject po = arg;
   arg.store(stream);
   }

   void store(T)(T arg) if (!is(T : PersistenceObject))
   {
   PersistenceObject po = arg;
   store(serialize(arg));
   }

   void load(T)(ref T arg) if (is(T : PersistenceObject))
   {
   PersistenceObject po = arg;
   arg.load(stream);
   }

   void load(T)(ref T arg) if (!is(T : PersistenceObject))
   {
   PersistenceObject po = arg;
   load(serialize(arg));
   }

   Stream stream;
}

/
And we have the next types which we want to store and load
*/

struct Role
{
...
}

struct User
{
   Role role;
   PersistenceObject po;
   //...
   alias role this;
   alias po this;
}

/*/

User u;
persistenceFramework.load(u)
//...
persistenceFramework.store(u);


/**/
Role is not subtype of PersistenceObject thus all works ok.
We can store User via User.po and load it again;

Some time later, Role designer decided that Role should be 
subtype of PersistenceObject and changed Role definition:


struct Role
{
...
PersistenceObject po;
alias po this;
}

Now, User can not be converted to PersistenceObject because there 
are two path to convert: User.po and User.role.po;
Storing code after this change will be copiled successfully (if 
we follow your "is" rule), however object will be tried to load 
via "void load(T)(ref T arg) if (!is(T : PersistenceObject))".
Because object was saved via "void store(T)(T arg) if (is(T : 
PersistenceObject))" at the previous program run, user will not 
be loaded succesfully. Moreover, you will get an strange 
unexpected program behaviour and will be hard to find real error 
cause.


/*/
And finally, if you want to check, if you Type _really_ can be 
converted to AnotherType, you can use the next check:


void foo(Type)(Type arg) if (is(typeof({AnotherType x = 
Type.init;})))

{

}



Re: DIP66 - Multiple alias this

2014-10-12 Thread Timon Gehr via Digitalmars-d

On 10/12/2014 06:28 AM, Walter Bright wrote:

On 10/11/2014 3:42 AM, Jacob Carlborg wrote:

On 2014-10-11 00:52, Walter Bright wrote:


I like the C++ rule that says that access control is not considered for
name lookup. I know it makes for some annoying results, but the
simplicity of the rule makes it much more understandable.


I'm not so sure about that. Perhaps it makes it more understandable for a
language designer. But not for a user. You try to call a function but
you get a
conflict with a private symbol. The user will get frustrated thinking:
"stupid
compiler, of course I want to call the public function".


The theory is that simpler rules are better than complex rules, even if
the simpler rules aren't always ideal.



Public symbols conflicting with private symbols are not just not ideal, 
they are a major PITA. The procedure for resolving ambiguities using 
alias introduces new private symbols itself!


Re: DIP66 - Multiple alias this

2014-10-12 Thread Steven Schveighoffer via Digitalmars-d

On 10/10/14 6:10 PM, IgorStepanov wrote:

On Friday, 10 October 2014 at 21:26:49 UTC, Steven Schveighoffer wrote:



An example:

foo(T)(T t) if(is(T : int))
{
   someFuncThatTakesInt(t);
}

foo(T)(T t) if(!is(T : int) && is(T.shadow : int))
{
   someFuncThatTakesInt(t.shadow);
}

struct A
{
   int i;
   alias i this;
}

struct B
{
   int i;
   alias i this;
}

struct C
{
   A a;
   B shadow;
   alias a this;
   alias shadow this;
}

C c;
foo(c); // should compile, but I think your DIP makes it fail due to
ambiguity



You can write foo(c.shadow); This isn't hard.
Ok, I understood you, let's listen to what others say


Right, you can get around it.

But the issue here is, that I feel like is(T: U) means (from dlang.org):

is ( Type : TypeSpecialization )
The condition is satisfied if Type is semantically correct and it is the 
same as or can be implicitly converted to TypeSpecialization.


This means is(C : int) should indicate that C can implicitly convert to 
int. But in your DIP, it does not. I think this is incorrect.


-Steve


Re: DIP66 - Multiple alias this

2014-10-12 Thread IgorStepanov via Digitalmars-d
On Sunday, 12 October 2014 at 23:02:13 UTC, Steven Schveighoffer 
wrote:

On 10/10/14 6:10 PM, IgorStepanov wrote:
On Friday, 10 October 2014 at 21:26:49 UTC, Steven 
Schveighoffer wrote:



An example:

foo(T)(T t) if(is(T : int))
{
  someFuncThatTakesInt(t);
}

foo(T)(T t) if(!is(T : int) && is(T.shadow : int))
{
  someFuncThatTakesInt(t.shadow);
}

struct A
{
  int i;
  alias i this;
}

struct B
{
  int i;
  alias i this;
}

struct C
{
  A a;
  B shadow;
  alias a this;
  alias shadow this;
}

C c;
foo(c); // should compile, but I think your DIP makes it fail 
due to

ambiguity



You can write foo(c.shadow); This isn't hard.
Ok, I understood you, let's listen to what others say


Right, you can get around it.

But the issue here is, that I feel like is(T: U) means (from 
dlang.org):


is ( Type : TypeSpecialization )
The condition is satisfied if Type is semantically correct and 
it is the same as or can be implicitly converted to 
TypeSpecialization.


This means is(C : int) should indicate that C can implicitly 
convert to int. But in your DIP, it does not. I think this is 
incorrect.


-Steve


Hmm. I've written case (my previous post), when returning false 
from is(T: S), where T has many pathes to S is dangerous. However 
your words also contain the truth. I don't know what we need to 
do. Maybe we should raise error during "is" semantic? Please, 
read my example and say your opinion.


Re: DIP66 - Multiple alias this

2014-10-12 Thread IgorStepanov via Digitalmars-d
Advantage of ky way is a more strictness then your way: if 
function with if(is(T: S)) will be called, error will be raised 
at the first trying of convert T to S. And we don't give the 
opportunity of possible error to spread away from the place of 
origin.


Re: DIP66 - Multiple alias this

2014-10-12 Thread Steven Schveighoffer via Digitalmars-d

On 10/12/14 7:16 PM, IgorStepanov wrote:

On Sunday, 12 October 2014 at 23:02:13 UTC, Steven Schveighoffer wrote:

On 10/10/14 6:10 PM, IgorStepanov wrote:



You can write foo(c.shadow); This isn't hard.
Ok, I understood you, let's listen to what others say


Right, you can get around it.

But the issue here is, that I feel like is(T: U) means (from dlang.org):

is ( Type : TypeSpecialization )
The condition is satisfied if Type is semantically correct and it is
the same as or can be implicitly converted to TypeSpecialization.

This means is(C : int) should indicate that C can implicitly convert
to int. But in your DIP, it does not. I think this is incorrect.




Hmm. I've written case (my previous post), when returning false from
is(T: S), where T has many pathes to S is dangerous.


OK, I didn't understand your case before, but I just got it.

I understand what you mean, but this isn't anything new -- one can cause 
weird problems by creating diamond-pattern interfaces also. I do not 
actually think it is dangerous, because one would not leave an error 
call in their code. So for a future change to a library to "mystically" 
make a function start working is not a danger, because said code wasn't 
sitting there broken in the first place.


I will note, that for diamond problem interfaces, the compiler seems to 
take a different track than your DIP:


interface A {}
interface B : A {}
interface C : A {}

class X : B, C {}

static assert(is(X : A));

void main()
{
A a = new C; // works, not sure if it's B.A or C.A
}

I know this is a different problem -- we aren't pointing at two 
different concrete implementations.


-Steve


Re: DIP66 - Multiple alias this

2014-10-13 Thread IgorStepanov via Digitalmars-d
On Monday, 13 October 2014 at 00:54:13 UTC, Steven Schveighoffer 
wrote:

On 10/12/14 7:16 PM, IgorStepanov wrote:
On Sunday, 12 October 2014 at 23:02:13 UTC, Steven 
Schveighoffer wrote:

On 10/10/14 6:10 PM, IgorStepanov wrote:



You can write foo(c.shadow); This isn't hard.
Ok, I understood you, let's listen to what others say


Right, you can get around it.

But the issue here is, that I feel like is(T: U) means (from 
dlang.org):


is ( Type : TypeSpecialization )
The condition is satisfied if Type is semantically correct 
and it is
the same as or can be implicitly converted to 
TypeSpecialization.


This means is(C : int) should indicate that C can implicitly 
convert
to int. But in your DIP, it does not. I think this is 
incorrect.




Hmm. I've written case (my previous post), when returning 
false from

is(T: S), where T has many pathes to S is dangerous.


OK, I didn't understand your case before, but I just got it.

I understand what you mean, but this isn't anything new -- one 
can cause weird problems by creating diamond-pattern interfaces 
also. I do not actually think it is dangerous, because one 
would not leave an error call in their code. So for a future 
change to a library to "mystically" make a function start 
working is not a danger, because said code wasn't sitting there 
broken in the first place.


I will note, that for diamond problem interfaces, the compiler 
seems to take a different track than your DIP:


interface A {}
interface B : A {}
interface C : A {}

class X : B, C {}

static assert(is(X : A));

void main()
{
A a = new C; // works, not sure if it's B.A or C.A
}

I know this is a different problem -- we aren't pointing at two 
different concrete implementations.


-Steve


This is fundamentally different situation: interfaces haven't a 
state, thus don't care what interface will be getted: B.C or C.C. 
Moreover, we can think that we have only one base C (like virtual 
inherited class in C++).

Alias this case requires a completely different approach.


Re: DIP66 - Multiple alias this

2014-10-13 Thread Daniel N via Digitalmars-d

On 10/11/2014 7:23 AM, IgorStepanov wrote:

class A
{
 int i;
 alias i this;
}

class B
{
 int i;
 alias i this;
}

class C
{
 A a;
 B b;
 alias a this;
 alias b this;
}


My preferred solution would be to reject the 2nd alias 
declaration outright.


I don't see any value in intentionally creating the above 
pattern, _if_ it occurs then it's most likely due to an 
unintentional side-effect of a re-factoring, thus it should error 
out as close as possible to the real error.




Re: DIP66 - Multiple alias this

2014-10-14 Thread IgorStepanov via Digitalmars-d

On Monday, 13 October 2014 at 15:21:32 UTC, Daniel N wrote:

On 10/11/2014 7:23 AM, IgorStepanov wrote:

class A
{
int i;
alias i this;
}

class B
{
int i;
alias i this;
}

class C
{
A a;
B b;
alias a this;
alias b this;
}


My preferred solution would be to reject the 2nd alias 
declaration outright.


I don't see any value in intentionally creating the above 
pattern, _if_ it occurs then it's most likely due to an 
unintentional side-effect of a re-factoring, thus it should 
error out as close as possible to the real error.


This code tell that C is subtype of A and C is subtype of B.
User can use this fact in his code:
void foo(B);

C c = new C;
foo(c); //Ok.
Of course, we shouldn't allow user to cast c to int:
int i = c; //wrong
However, user can explicitly cast c to his subtype, which is 
convertable to int:

int i = cast(B)c; //Ok
Summarizing, I disagree with suggestion disallow this code at 
type semantic stage.


Re: DIP66 - Multiple alias this

2014-10-14 Thread Dicebot via Digitalmars-d

On Tuesday, 14 October 2014 at 12:33:50 UTC, IgorStepanov wrote:

This code tell that C is subtype of A and C is subtype of B.
User can use this fact in his code:
void foo(B);

C c = new C;
foo(c); //Ok.
Of course, we shouldn't allow user to cast c to int:
int i = c; //wrong
However, user can explicitly cast c to his subtype, which is 
convertable to int:

int i = cast(B)c; //Ok
Summarizing, I disagree with suggestion disallow this code at 
type semantic stage.


I agree. It will also make possible to break already working 
disambugation of `foo(c)` kind but adding new `alias this` to one 
of subtypes independently. That sounds annoying.


Re: DIP66 - Multiple alias this

2014-10-14 Thread Daniel N via Digitalmars-d

On Wednesday, 15 October 2014 at 02:46:05 UTC, Dicebot wrote:

On Tuesday, 14 October 2014 at 12:33:50 UTC, IgorStepanov wrote:

This code tell that C is subtype of A and C is subtype of B.
User can use this fact in his code:
void foo(B);

C c = new C;
foo(c); //Ok.
Of course, we shouldn't allow user to cast c to int:
int i = c; //wrong
However, user can explicitly cast c to his subtype, which is 
convertable to int:

int i = cast(B)c; //Ok
Summarizing, I disagree with suggestion disallow this code at 
type semantic stage.


I agree. It will also make possible to break already working 
disambugation of `foo(c)` kind but adding new `alias this` to 
one of subtypes independently. That sounds annoying.


I guess the best part of D is, you have the means to fix anything 
you disagree with yourself... I can add a static assert to my 
class and be happy.


I have another idea, we could define that the shortest conversion 
chain wins, analogous to type promotions, that makes it possible 
to contain the issue inside C.


class C
{
  A a;
  B b;

  int disambiguate_int()
  {
return a;
  }
  alias a this;
  alias b this;
  alias disambiguate_int this;
  static assert(__traits(compiles, {int _ = C.init;}), "Ambiguous 
alias this");

}

i.e. this assert should pass.


Re: DIP66 - Multiple alias this

2014-10-15 Thread IgorStepanov via Digitalmars-d

On Wednesday, 15 October 2014 at 03:49:41 UTC, Daniel N wrote:

On Wednesday, 15 October 2014 at 02:46:05 UTC, Dicebot wrote:
On Tuesday, 14 October 2014 at 12:33:50 UTC, IgorStepanov 
wrote:

This code tell that C is subtype of A and C is subtype of B.
User can use this fact in his code:
void foo(B);

C c = new C;
foo(c); //Ok.
Of course, we shouldn't allow user to cast c to int:
int i = c; //wrong
However, user can explicitly cast c to his subtype, which is 
convertable to int:

int i = cast(B)c; //Ok
Summarizing, I disagree with suggestion disallow this code at 
type semantic stage.


I agree. It will also make possible to break already working 
disambugation of `foo(c)` kind but adding new `alias this` to 
one of subtypes independently. That sounds annoying.


I guess the best part of D is, you have the means to fix 
anything you disagree with yourself... I can add a static 
assert to my class and be happy.


I have another idea, we could define that the shortest 
conversion chain wins, analogous to type promotions, that makes 
it possible to contain the issue inside C.


class C
{
  A a;
  B b;

  int disambiguate_int()
  {
return a;
  }
  alias a this;
  alias b this;
  alias disambiguate_int this;
  static assert(__traits(compiles, {int _ = C.init;}), 
"Ambiguous alias this");

}

i.e. this assert should pass.


In first edition I've implemented rule, when if type defines 
alias this directly, this alias hides all indirect aliases with 
the same type. However Andrey said that we should implement the 
strictest rules as possible and maybe relax them later.
Thus I implemented current rules, but saved the old implemetation 
of search. After some time we will able to return to first rule. 
It's not hard.


Re: DIP66 - Multiple alias this

2014-10-19 Thread IgorStepanov via Digitalmars-d

Bump.


Re: DIP66 - Multiple alias this

2014-10-19 Thread Daniel N via Digitalmars-d

On Wednesday, 15 October 2014 at 09:50:17 UTC, IgorStepanov wrote:
In first edition I've implemented rule, when if type defines 
alias this directly, this alias hides all indirect aliases with 
the same type. However Andrey said that we should implement the 
strictest rules as possible and maybe relax them later.
Thus I implemented current rules, but saved the old 
implemetation of search. After some time we will able to return 
to first rule. It's not hard.


I see, in order to prevent any accidental shadowing, maybe one 
can consider "override alias this", if we decide to make a 
relaxed version in the future?


Re: DIP66 - Multiple alias this

2014-10-19 Thread IgorStepanov via Digitalmars-d

On Monday, 20 October 2014 at 00:23:46 UTC, Daniel N wrote:
On Wednesday, 15 October 2014 at 09:50:17 UTC, IgorStepanov 
wrote:
In first edition I've implemented rule, when if type defines 
alias this directly, this alias hides all indirect aliases 
with the same type. However Andrey said that we should 
implement the strictest rules as possible and maybe relax them 
later.
Thus I implemented current rules, but saved the old 
implemetation of search. After some time we will able to 
return to first rule. It's not hard.


I see, in order to prevent any accidental shadowing, maybe one 
can consider "override alias this", if we decide to make a 
relaxed version in the future?


Make sense. I think we should postpone but not forgotten this 
feature.
When main part will be merged, we will able to start discussion 
about override alias this.


What about the other features?


  1   2   3   4   5   >