[Bug 179] New: Covariance screws up when overriding two interfaces or a class and an interface
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Wed Jun 7 05:06:08 PDT 2006
http://d.puremagic.com/bugzilla/show_bug.cgi?id=179
Summary: Covariance screws up when overriding two interfaces or a
class and an interface
Product: D
Version: 0.160
Platform: PC
OS/Version: Windows
Status: NEW
Keywords: wrong-code
Severity: normal
Priority: P2
Component: DMD
AssignedTo: bugzilla at digitalmars.com
ReportedBy: smjg at iname.com
If a class derives from two interfaces, or a class and an interface, and they
have different expectations for the return type of some method, then covariance
screws up.
----------
import std.stdio;
interface Father {
Father test();
void showData();
}
class Mother {
int data;
this(int d) { data = d; }
Mother test() {
return new Child(102);
}
void showData() {
writefln("Mother: %d", data);
}
}
class Child : Mother, Father {
this(int d) { super(d); }
Child test() {
return new Child(69);
}
void showData() {
writefln("Child: %d", data);
}
}
void main() {
Child aChild = new Child(42);
aChild.showData();
Mother childsMum = aChild;
childsMum.showData();
Father childsDad = aChild;
childsDad.showData();
writefln("entering childsMum.test.showData");
childsMum.test.showData();
writefln("exited childsMum.test.showData");
Father dadTest = childsDad.test;
writefln("entering dadTest.showData");
dadTest.showData();
writefln("entering (cast(Child) dadTest).showData");
(cast(Child) dadTest).showData();
}
----------
Output:
Child: 42
Child: 42
Child: 42
entering childsMum.test.showData
exited childsMum.test.showData
entering dadTest.showData
entering (cast(Child) dadTest).showData
Error: Access Violation
So the penultimate showData call does nothing, and the final one throws the AV.
The same happens if I switch the return types around. A similar example, in
which both Father and Mother are interfaces, shows the same problem.
I can see that this would be more complicated to get to work, as Father expects
a Father interface reference and Mother expects an object reference for the
same function - and Child.test cannot be directly compatible with both at the
same time.
A possible solution is for the compiler to generate two versions of Child.test.
First it will generate one that returns an object reference as written, which
will be used by the vtbls for Mother and Child. Then, it will generate a
wrapper that converts the return from Child.test to a Father reference, which
will be used in Father's vtbl.
More generally, if the compiler detects a scenario like this, it would generate
the function to return in the locally declared return type, and a wrapper for
each interface that it needs to convert to.
--
More information about the Digitalmars-d-bugs
mailing list