DIP66 - Multiple alias this

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Fri Oct 10 14:26:49 PDT 2014


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


More information about the Digitalmars-d mailing list