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.