Bug 612 – Associative arrays ignore opEquals, contrary to the spec

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Windows
Creation time
2006-11-27T10:01:00Z
Last change time
2014-02-15T13:20:06Z
Keywords
spec, wrong-code
Assigned to
bugzilla
Creator
smjg
Blocks
677

Comments

Comment #0 by smjg — 2006-11-27T10:01:21Z
"Classes can be used as the KeyType. For this to work, the class definition must override the following member functions of class Object: * hash_t toHash() * int opEquals(Object) * int opCmp(Object)" "Structs or unions can be used as the KeyType. For this to work, the struct or union definition must define the following member functions: * hash_t toHash() * int opEquals(S) or int opEquals(S*) * int opCmp(S) or int opCmp(S*)" It turns out that the current implementation of AAs is just ignoring opEquals. Take this code: ---------- import std.stdio; import std.ctype; struct IChar { char data; bit opEquals(IChar i) { debug writefln("Entered IChar.opEquals(IChar)"); return data == i.data; } int opCmp(IChar i) { debug writefln("Entered IChar.opCmp(IChar)"); return toupper(data) - toupper(i.data); } hash_t toHash() { debug writefln("Entered IChar.toHash()"); return toupper(data); } } void main() { int[IChar] aa; IChar c1, c2; c1.data = 'c'; c2.data = 'C'; aa[c1] = 4; aa[c2] = 7; aa.rehash; writefln("aa[c1]: %d", aa[c1]); writefln("aa[c2]: %d", aa[c2]); } ---------- 7 7 ---------- The output immediately shows that c1 and c2 are treated as being the same key. Compiling with -debug and running will further confirm that IChar.opEquals is never called. The same occurs if a class is used instead of a struct. Two possible solutions: (a) Fix the implementation of AAs so that it uses opEquals to check that the key it's found for which opCmp returns zero does indeed match the key. (b) Remove the existing mentions of opEquals from these sections, and explicitly state: For efficiency of lookups, opEquals is not used to compare keys. Therefore, if a.opCmp(b) == 0, then a and b are the same key even if a != b. Care must be taken to ensure that if a.opCmp(b) == 0 then a.toHash == b.toHash, otherwise undefined behaviour will occur.
Comment #1 by bugzilla — 2006-12-27T01:59:13Z
Fixed DMD 0.178