Bug 10785 – Interface diamond covariance causes silent breakage

Status
RESOLVED
Resolution
DUPLICATE
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-08-08T17:01:00Z
Last change time
2015-07-18T13:45:30Z
Assigned to
nobody
Creator
default_357-line
Depends on
10806

Comments

Comment #0 by default_357-line — 2013-08-08T17:01:53Z
Consider this code: interface A { A foo(); } interface A1 : A { A1 foo(); } interface A2 : A { A2 foo(); } class C : A1, A2 { override C foo() { return new C; } } void main() { A2 x = new C; A2 y = x.foo(); // y.classinfo.name should be "A2" here; instead, it is "A1". The vtables also don't match up (not that there's significant vtables in this example, but, you know) assert(y.classinfo.name.find("A2") != -1); // fails // Further issues: this should be a no-op, but it isn't. A2 z = cast(A2) cast(A) y; assert(z.classinfo.name == y.classinfo.name); // fails too } The problem seems to be that whatever magic the compiler does to make interface covariance work fails in the case where it has to satisfy the same interface via two covariant child interfaces at once. I suspect this would either require A2.foo to be filled with a stub that does the conversion of C to A2, or a compiletime error.
Comment #1 by lt.infiltrator — 2013-08-11T22:22:22Z
This also affects non-diamond configurations: http://dpaste.dzfl.pl/e9df03f9 ---------------------- import std.stdio; interface A1 { A1 foo(); } interface A2 { A2 foo(); } class C1 : A1, A2 { override C1 foo() { return new C1; } } interface B1 { B1 foo(); } interface B2 { B2 foo(); } class C2 : B2, B1 { override C2 foo() { return new C2; } } void main() { A2 x = new C1; A2 y = x.foo(); writefln("X: %s", x.classinfo); writefln("Y: %s", y.classinfo); B2 a = new C2; B2 b = a.foo(); writefln("A: %s", a.classinfo); writefln("B: %s", b.classinfo); } ----------------------- Application output: X: f230.A2 Y: f230.A1 A: f230.B2 B: f230.B2
Comment #2 by default_357-line — 2013-08-11T22:40:21Z
(In reply to comment #1) > This also affects non-diamond configurations: Thanks, filed as 10806. Not sure whether to mark this as a duplicate. (10806 is the more general bug)
Comment #3 by lt.infiltrator — 2013-08-11T23:02:31Z
I've set #10806 as a blocker for this, as diamond may still break even after non-diamond is fixed. Somebody more knowledgeable in dmd can make the duplicate decision.
Comment #4 by k.hara.pg — 2015-07-18T13:45:30Z
(In reply to FeepingCreature from comment #0) > Consider this code: > > interface A { A foo(); } > > interface A1 : A { A1 foo(); } > interface A2 : A { A2 foo(); } > > class C : A1, A2 { > override C foo() { return new C; } To implement A1.foo, the returned class C reference will be implicitly upcasted to A1. Then the issue 1747 happens. > } *** This issue has been marked as a duplicate of issue 1747 ***