www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 22717] New: object.TypeInfo_Struct.equals swaps lhs and rhs

https://issues.dlang.org/show_bug.cgi?id=22717

          Issue ID: 22717
           Summary: object.TypeInfo_Struct.equals swaps lhs and rhs
                    parameters
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: critical
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: ibuclaw gdcproject.org

Related to issue 1622 and issue 5854.

---
void main()
{
    static struct S
    {
        int value;

        version (XopEquals)
        {
            bool opEquals(const S rhs) const
            {
                assert(this.value == 42);
                return true;
            }
        }
        else
        {
            bool opEquals(const ref S rhs) const
            {
                assert(this.value == 42);
                return true;
            }
        }
    }

    auto a = S(42);
    auto b = S(24);
    auto ti = typeid(S);
    assert(ti.equals(&a, &b));
}
---

Unfortunately this requires a coordinated fix in both druntime and dmd
(Monorepo, anyone?).

1. Swap `(p1, p2)` around:
https://github.com/dlang/druntime/blob/e390ba7e0a1f80f15e72ca773fca7252057ba4c5/src/object.d#L1887

2. Generate `return (q == p)`:
https://github.com/dlang/dmd/blob/5436d4d167e41f59b799071d8136bb051c87ae56/src/dmd/clone.d#L579-L581

Existing code in the wild already relies on this buggy behavior.  For instance,
in the DMD compiler itself:
https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d#L7810

If `opEquals(const ref)` was called properly by druntime, then the above quoted
line should instead be: `(cast()ti).equalsx(cast()s.ti);`

--
Jan 31 2022