D casting broke?

Joerg Joergonson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jun 19 16:40:11 PDT 2016


On Sunday, 19 June 2016 at 23:00:03 UTC, ag0aep6g wrote:
> On 06/19/2016 11:19 PM, Joerg Joergonson wrote:
>> On Sunday, 19 June 2016 at 20:21:35 UTC, ag0aep6g wrote:
> [...]
>>> No. B!b is derived from A!b, not from A!a. `b` being derived 
>>> from `a`
>>> does not make A!b derived from A!a.
>>
>> why not? This doesn't seem logical!
>
> Template parameters simply don't work like that. A template can 
> result in completely unrelated types based on template 
> parameters.
>
> For example:
>
>     template C(T)
>     {
>         static if (is(T == A)) class C {}
>         else static if(is(T == B)) alias C = int;
>         else struct C {int x;}
>     }
>
> As you see there can't be any inheritance relation between the 
> different instantiations of the C template here. Having such a 
> relation for different instantiation that result in classes 
> would be a weird special case.
>
> There's probably a really simple and obvious reason why that 
> special would be a bad idea in itself, but I'm not able to 
> point it out. Maybe make a thread in the General group. I think 
> the language people tend to focus their attention there.
>
> Criticism and improvement proposals are also better directed to 
> the General group.
>
>>> Here is the full inheritance tree:
>>>
>>> X
>>> ├─x
>>> │ └─a
>>> │   └─b
>>> ├─A!a
>>> └─A!b
>>>   └─B!b
>>
>>
>> But b is derived from a.
>
> Yeah, that's right there in the middle.
>
>> Your tree completely ignores under A.
>
> Clearly, there's B!b under A!b. That's it. Nothing exists below 
> B!b. B!a doesn't exist either. A!a is on a different branch. I 
> don't think I've missed anything.
>
> [...]
>> Just because D doesn't understand this logical consistency 
>> between
>> inheritance doesn't mean D is right. (Hence, why D's type 
>> system is broke)
>>
>>
>> In fact, the tree should look like this:
>>
>>> X
>>> ├─x
>>> │ └─a
>>> │   └─b
>>> └─A!x
>>      │  \
>>      └─A!a
>>        │  \
>>        └─A!b
>>          │  \
>>          └─B!b
>
> I'm having trouble reading this. A!x isn't valid, as the 
> constraint on A says `T : a`, but x doesn't satisfy that.
>

no, my point was that a is derived from x, b from a, hence we 
have a derivation change x -> a -> b. So, similarly A!x -> A!a -> 
A!b

> I also don't understand what the backslashes mean. They just 
> repeat the other lines, don't they? Or do they connect x, a, 
> and b? That's already expressed in the upper section.

Yes, they connect them. Yes, exactly, But this time they connect 
in terms of A. The compiler doesn't seem to use the fact that x 
-> a -> -> b to infer anything about A!x -> A!a -> A!b, and it 
should.

>
> As for A!b being below A!a, I can only repeat that this 
> inheritance is not implied. You would have to spell it out 
> explicitly for the compiler to pick it up.
>

Maybe so. But that is kinda my point.

>> Basically you are treating A!a and A!b as if a and be have no
>> relationship. BUT THEY DO!
>
> Well, to the compiler they don't.

Yes, exactly.


basically I am doing a cast(A!a)this because all I care about is 
this in terms of A!a. If it's a B!b or B!a or A!b is immaterial 
to me since casting to A!a gets me what I need. (It's no 
different than if I was doing simpler inheritance) D doesn't 
understand this and there is no simple fix that anyone has 
presented.

The casting is the only problem and there is no reason it should 
fail because the object I am casting on can be cast to it's base 
class.

If we assume that I'm wrong or D can't do this because of a bug 
or shortsightedness... the issue remains on how to make it work.

public class Button(T : ButtonItem) : Widget { ... }
public class ButtonItem : Item
{
  void Do() { auto parent = (cast(Button!ButtonItem)this.Parent); }
  ...
}

All this works great! As long as Do is not being called from a 
derived class

public class Slider(T : SliderItem) : Button!T { }
public class SliderItem : ButtonItem { }


The last two classes are truly empty. Now, when I use a Slider 
object, things go to shit because the cast is invalid. 
this.Parent is of type Slider!SliderItem.

SliderItem only sets the array type. So in Slider, I end up with 
a SliderItem[] type then in ButtonItem's Do(which gets called 
since SliderItem doesn't override), it tries to cast that down to 
a ButtonItem. It should work. There is no reason it shouldn't 
logically. There is no up casting.

If I duplicate Do() and put it in SliderItem and change the cast 
to use Slider/SliderItem, it works. The cast is the only problem. 
Not the objects themselves.

If this wasn't a parameterized class, everything would work. If I 
made Slider use ButtonItems everything would work. It's only 
because I derived a new type SldierItem from ButtonItem that 
breaks and only at the cast.


I'm almost 100% sure this should work and haven't seen anyone 
actually show why this would not work(the examples given are 
simply wrong and are not understanding the problem... or there is 
more going than anyone has said).

Again, do we not expect derived types to be able to be down cast? 
Just because they are parameterized on other types doesn't change 
this fact? It just makes it more complicated because we now have 
to have type logic on the parameterized types.


I tried to avoid posting in General but I guess I will have to.




More information about the Digitalmars-d-learn mailing list