Bug 10971 – assigning derived class to base should not trigger promotion of result
Status
RESOLVED
Resolution
INVALID
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-09-05T06:16:00Z
Last change time
2013-09-05T23:09:25Z
Assigned to
nobody
Creator
monarchdodra
Comments
Comment #0 by monarchdodra — 2013-09-05T06:16:03Z
EG:
//----
class A
{
A next;
}
class B : A
{}
void main()
{
B first = new B;
B last = first;
//foreach(_ ; 0 .. 10)
last = (last.next = new B); [1]
}
//----
[1]: Error: cannot implicitly convert expression (last.next = new B) of type main.A to main.B
When the call the compiler should be able to type the result of "last.next = new B" as a "B" (the type of "new B"), and not an "A" (the type of "last.next").
Other usecase:
//----
class A
{
A next;
}
class B : A
{}
void foo(B){}
void main()
{
A a;
foo(a = new B);
}
//----
Error: function main.foo (B _param_0) is not callable using argument types (A)
The workaround is trivial of course, but I'd have expect the compiler could handle it.
Comment #1 by maxim — 2013-09-05T06:49:10Z
I doubt it will ever be implemented because it breaks static typing of D. In second example type of a is "A" and not "B" and your request would require compiler to accept/reject sometimes arguments depending on context. For example, initializer for a can be not new B, but Object foo() and in such context compiler cannot know whether returned value is trully B or not.
Comment #2 by monarchdodra — 2013-09-05T07:32:08Z
(In reply to comment #1)
> I doubt it will ever be implemented because it breaks static typing of D. In
> second example type of a is "A" and not "B" and your request would require
> compiler to accept/reject sometimes arguments depending on context. For
> example, initializer for a can be not new B, but Object foo() and in such
> context compiler cannot know whether returned value is trully B or not.
Depends on how you see it I guess. I could that I see it that the initializer is "new B", yet *because of context* (assign to "a" while we are at it), it doesn't compile.
But I don't think this has anything to do with context. Just that "a = b" is an operation, and like all operations, it has a return type. I think we could improve what that type is. We could make it "The type A, but implicitly cast-able to B"
That would be "nice to have".
Comment #3 by maxim — 2013-09-05T09:18:04Z
(In reply to comment #2)
> (In reply to comment #1)
> > I doubt it will ever be implemented because it breaks static typing of D. In
> > second example type of a is "A" and not "B" and your request would require
> > compiler to accept/reject sometimes arguments depending on context. For
> > example, initializer for a can be not new B, but Object foo() and in such
> > context compiler cannot know whether returned value is trully B or not.
>
> Depends on how you see it I guess. I could that I see it that the initializer
> is "new B", yet *because of context* (assign to "a" while we are at it), it
> doesn't compile.
>
> But I don't think this has anything to do with context. Just that "a = b" is an
> operation, and like all operations, it has a return type. I think we could
> improve what that type is. We could make it "The type A, but implicitly
> cast-able to B"
>
> That would be "nice to have".
In C in assignment chaining type of expression is defined to be the type of leftmost operand. I don't think you EH is a good reason to break it.
Comment #4 by monarchdodra — 2013-09-05T10:17:41Z
(In reply to comment #3)
> In C in assignment chaining type of expression is defined to be the type of
> leftmost operand. I don't think you EH is a good reason to break it.
C doesn't have inheritance.
And I don't want to change that behavior.
I want the compiler to know that making an implicit downcast would be legal in this situation.
Comment #5 by andrej.mitrovich — 2013-09-05T10:51:22Z
Counterpoint:
-----
class A
{
A next(A newA) { return new A; } // does not return B!
}
class B : A
{}
void main()
{
B first = new B;
B last = first;
last = (last.next = new B);
}
-----
If someone changes a field into a property, your code would break.
Comment #6 by andrej.mitrovich — 2013-09-05T10:52:03Z
(In reply to comment #5)
> If someone changes a field into a property, your code would break.
Although I missed using @property there, but it's the same thing.
Comment #7 by monarchdodra — 2013-09-05T23:09:25Z
(In reply to comment #5)
> Counterpoint:
>
> If someone changes a field into a property, your code would break.
I guess that's good enough of an example to conclude that my proposal is not worth following.
TY for taking the time to rebuke.