Bug 22717 – object.TypeInfo_Struct.equals swaps lhs and rhs parameters

Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-01-31T11:19:00Z
Last change time
2022-02-02T13:08:17Z
Keywords
GDC, LDC, pull, spec, wrong-code
Assigned to
No Owner
Creator
Iain Buclaw

Comments

Comment #0 by ibuclaw — 2022-01-31T11:19:00Z
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);`
Comment #1 by ibuclaw — 2022-01-31T11:23:36Z
(In reply to Iain Buclaw from comment #0) > If `opEquals(const ref)` was called properly by druntime, then the above > quoted line should instead be: `(cast()ti).equalsx(cast()s.ti);` As such, fixing this will result in a MAJOR BREAKING CHANGE, and the DMD compiler implementation will require it's buggy `opEquals()` to be fixed using: ``` static if (__VERSION__ >= FIXED_VERSION) // druntime xopEquals called this function as lhs.opEquals(rhs) (cast()ti).equalsx(cast()s.ti); else // druntime xopEquals called this function as rhs.opEquals(lhs) (cast()s.ti).equalsx(cast()ti); ```
Comment #2 by dlang-bot — 2022-01-31T15:28:00Z
@kinke created dlang/druntime pull request #3718 "Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters" fixing this issue: - Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters https://github.com/dlang/druntime/pull/3718
Comment #3 by dlang-bot — 2022-01-31T15:28:49Z
@kinke created dlang/dmd pull request #13593 "Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters" fixing this issue: - Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters Leading to a swapped `rhs.opEquals(lhs)` check *if* the opEquals method took its parameter by ref. https://github.com/dlang/dmd/pull/13593
Comment #4 by dlang-bot — 2022-02-01T09:01:00Z
dlang/druntime pull request #3718 "Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters" was merged into master: - f4470eb794218e2cfda18108392f61bda3d0d470 by Martin Kinkelin: Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters https://github.com/dlang/druntime/pull/3718
Comment #5 by dlang-bot — 2022-02-02T13:08:17Z
dlang/dmd pull request #13593 "Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters" was merged into master: - 58c3cc6b2c273101201854336a30d21b920c7405 by Martin Kinkelin: Fix Issue 22717 - TypeInfo_Struct.equals swaps lhs and rhs parameters Leading to a swapped `rhs.opEquals(lhs)` check *if* the opEquals method took its parameter by ref. https://github.com/dlang/dmd/pull/13593