[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