Andrei Alexandrescu wrote:
Frank Benoit wrote:
Andrei Alexandrescu schrieb:
Frank Benoit wrote:
Andrei Alexandrescu schrieb:
Consider two objects a and b with a of class type. Currently, the
expression a == b is blindly rewritten as a.opEquals(b). I argue it
should be rewritten into a call to an (imaginary/inlined) function
equalObjects(a, b), with the following definition:

bool equalObjects(T, U)(T a, U b) if (is(T == class))
{
    static if (is(U == class))
    {
        if (b is null) return a is null;
        if (a is null) return b is null;
    }
    else
    {
        enforce(a !is null);
    }
    return a.opEquals(b);
}

This hoists the identity test outside the opEquals call and also deals
with null references. What do you think?


Andrei
What about interfaces?
Good question! What do they do now? I ran this:

interface A {}
class Widget : A {}

void main() {
    auto a = cast(A) new Widget;
    A b = null;
    writeln(a == b);
    writeln(b == a);
}

To my surprise, the program printed false twice. If I replace A with
Widget inside main, the program prints false then crashes with the
mythical segfault :o).

So how are interfaces compared?


Andrei

Hm, i would have expected it not to compile, because A does not have
opEquals.

In DWT, I cast always first to Object.
Java> if( intf1.equals(intf2) ){
D1.0> if( ((cast(Object)intf1).opEquals( cast(Object)intf2 )){

I think in D the cast is inserted automatically. Walter?

Andrei

Using the compile-time view of Descent, if I have this code:

---
interface I {
        
}

class C {
        
}

int main(char[][] args) {
        C c = new C();
        I i = null;
        
        auto x = i == c;
        auto y = c == i;
        
        return 0;
}
---

the compiler turns it into:

---
interface I {
}

class C: Object {
}

int main(char[][] args) {
        C c = new C;
        I i = null;
        int x = c.opEquals(cast(Object) i);
        int y = c.opEquals(cast(Object) i);
        return 0;
}
---

That's why it doesn't segfault.

Debugging the code it turns out the logic is very simple, it's just applying operator overloading: (for the first comparison) "opEquals" is searched in "I". Since "opEquals" is not found in it, the compiler checks if "opEquals" is commutative. It is, so it searches "opEquals" in "C", finds it and does the rewrite. (more or less)

Reply via email to