Thread overview
[Issue 669] New: (a == b) misuses opCmp and opEquals
Dec 09, 2006
d-bugmail
Dec 10, 2006
d-bugmail
Dec 10, 2006
d-bugmail
Dec 10, 2006
d-bugmail
Dec 27, 2006
d-bugmail
December 09, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=669

           Summary: (a == b) misuses opCmp and opEquals
           Product: D
           Version: 0.175
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: burton-radons@smocky.com


This code:

   class C
   {
       override int opEquals (Object other) { return 0; }
       override int opCmp (Object other) { return 0; }
   }

   void main ()
   {
       auto a = new C, b = new C;
       assert (a != b);
   }

Asserts, because (a == b) is apparently implemented as (a.opEquals (b) ||
!a.opCmp (b)) for classes. If this were the way it should work, then "float.nan
== 0" would be true. It's the "!<>" operator that's defined with this
behaviour.


-- 

December 10, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=669


smjg@iname.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |smjg@iname.com




------- Comment #1 from smjg@iname.com  2006-12-10 12:12 -------
Under DMD 0.177, the code doesn't even compile:

opCmpEquals_2.d(9): semicolon expected following auto declaration, not ','
opCmpEquals_2.d(9): found ',' instead of statement

But having fixed this error, the bug doesn't show at all.  Experimenting shows
that:
== and != use only opEquals
<> and !<> use only opCmp
which is how it should be.

WFM?


-- 

December 10, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=669





------- Comment #2 from burton-radons@smocky.com  2006-12-10 13:43 -------
Grah I'm a stupid. Here's code which actually exhibits the problem:

        class C
        {
                override int opEquals (Object other) { printf ("opEquals\n");
return 0; }
                override int opCmp (Object other) { printf ("opCmp\n"); return
0; }
        }

        void main ()
        {
                auto type = typeid (typeof (C));
                void *data = new C;

                assert (type.equals (&data, &data) == 0);
        }

The fault is TypeInfo_Class in internal.object. It's implemented like this:

        int equals(void *p1, void *p2)
        {
                Object o1 = *cast(Object*)p1;
                Object o2 = *cast(Object*)p2;

                return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
        }

When it should be implemented like this:

        int equals(void *p1, void *p2)
        {
                Object o1 = *cast(Object*)p1;
                Object o2 = *cast(Object*)p2;

                return o1 == o2;
        }

This problem showed itself because I was comparing boxed objects, so I assume it's written the way it is now for associative arrays. If so then associative arrays should have their own slot in a TypeInfo for performing this (unorderedOrEqual), and std.boxer can have a pure form with the correct semantics for ==. Otherwise std.boxer's Box.opEqualsInternal can have a clause for objects.


-- 

December 10, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=669





------- Comment #3 from smjg@iname.com  2006-12-10 16:58 -------
(In reply to comment #2)
> When it should be implemented like this:
> 
>         int equals(void *p1, void *p2)
>         {
>                 Object o1 = *cast(Object*)p1;
>                 Object o2 = *cast(Object*)p2;
> 
>                 return o1 == o2;
>         }

I could've sworn this was fixed once!  Moreover, that's still not quite right. It should be

    int equals(void *p1, void *p2)
    {
        if (p1 == null) return p2 == null;

        Object o1 = *cast(Object*)p1;
        Object o2 = *cast(Object*)p2;

        return o1 == o2;
    }

or some equivalent of this.


-- 

December 27, 2006
http://d.puremagic.com/issues/show_bug.cgi?id=669


bugzilla@digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |FIXED




------- Comment #4 from bugzilla@digitalmars.com  2006-12-27 02:02 -------
Fixed DMD 0.178


--