Bug 10037 – Compiler should not generate opEquals method implicitly

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-05-06T21:12:00Z
Last change time
2013-10-03T00:25:33Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
k.hara.pg
Blocks
3789

Comments

Comment #0 by k.hara.pg — 2013-05-06T21:12:47Z
Currently, dmd sometimes generates opEquals method for struct types implicitly. struct S { bool opEquals(ref const S) { assert(0); } // line 2 } struct T { S s; // Compiler implicitly generates here: // bool opEquals(in S rhs) const { return this.s == rhs.s } } void test1() { T t; static assert(__traits(hasMember, T, "opEquals")); // pass bool x = (t == t); // assertion fails at line 2 in runtime } In above, the field s in T requires calling its opEquals for the objects equality, therefore for the type T compiler implicitly generates opEquals method, which runs member-wise comparison. This behavior is introduced by fixing issue 3433. Doing member-wise comparison itself is not an issue. But implicitly generation of opEquals is not good behavior. For example, if we declare a simple subtype struct, struct Sub(TL...) { TL data; int value; alias value this; } void test2() { Sub!(S) lhs; Sub!(S) rhs; assert(lhs == rhs); // compilation fails! // We expects to be rewritten: // --> lhs.value == rhs.value // But, is unexpectedly rewritten to: // --> lhs.opEquals(rhs) // And it will invoke lhs.data[0] == rhs.data[0], then // assertion fails at T.opEquals in runtime. } In this case, Sub does not define opEquals explicitly, so comparison is expected to be falled back to alias this comparison. But, implicitly generated 'opEquals' will steal the expect. It would make alias this unusable. So, compiler must not opEquals method implicitly. Instead, equality operation s1 == s2 should be rewritten to s1.tupleof == s2.tupleof.
Comment #1 by k.hara.pg — 2013-05-06T21:19:36Z
Essentially in D, equality operation '==' should probide structural equality. For built-in basic types, it is just same as bitwise equality. For array types, '==' provides length and element-wise equality. For AA types, it provides logical AND of contained elements equality. Then, for any struct types which does not have explicit opEquals, D should provide member-wise equality. It has been discussed long time in bug 3789, and I think it should be fixed. But this issue is an obstacle to fix it.
Comment #2 by k.hara.pg — 2013-05-07T07:54:48Z
Comment #3 by github-bugzilla — 2013-05-07T14:00:35Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/ed8f7c697d21c4d8e887f1d2b3809195a29e1e1f fix Issue 10037 - Compiler should not generate opEquals method implicitly https://github.com/D-Programming-Language/dmd/commit/596c1128f4de2b246d339497e1bcec70d93ffd78 Merge pull request #1972 from 9rnsr/fix3789 Issue 3789 and 10037 - [TDPL] Structs members that require non-bitwise comparison not correctly compared
Comment #4 by yebblies — 2013-08-02T21:31:32Z
Fixed?