First, AAs should use equals instead of compare. At the moment, it uses compare(a, b) == 0, which should be equivalent to equals. Also note that some structs may be able to compare via equality, but not ordered.
Second, I believe only struct keys which satisfy one of the following two conditions should be allowed:
1. Neither opCmp nor opEquals are defined.
Rationale: If neither opCmp nor opEquals are defined, then equals(a, b) is guaranteed to be equivalent to compare(a, b) == 0, since the compiler generated the functions. Note that this applies recursively in the case of member structs if the compiler is generating the function.
2. Both opEquals and toHash are defined.
Rationale: if opEquals is specially defined, then toHash must also be specially defined. If opEquals only examines part of the object, then toHash would have to be modified to only examine part of the object as well.
All other structs should be disallowed as keys.
Rationale: Only opEquals will be used for comparison. If one defines opCmp but not opEquals, then the builtin opEquals may not be equivalent to opCmp() == 0, and the AA will not use the correct comparison tool.
Comment #2 by dlang-bugzilla — 2014-02-26T22:07:45Z
*** Issue 12267 has been marked as a duplicate of this issue. ***
Comment #3 by dlang-bugzilla — 2014-02-27T12:51:39Z
From issue 12267:
This program no longer compiles:
struct S {}
int[S] aa;
However, it will compile if you add this to the top of the file:
struct T { int opCmp() { return 2; } }
It looks like an opCmp in ANY struct will unbreak compilation (as long as it comes before the AA).
Comment #4 by verylonglogin.reg — 2014-06-13T07:54:05Z
(In reply to Vladimir Panteleev from comment #3)
> It looks like an opCmp in ANY struct will unbreak compilation (as long as it
> comes before the AA).
Filed Issue 12905.
Comment #6 by bearophile_hugs — 2014-07-04T17:29:21Z
(In reply to Kenji Hara from comment #5)
> https://github.com/D-Programming-Language/dmd/pull/3711
Currently:
auto s1 = "he";
auto s2 = "llo";
void main() {
import std.stdio, std.typecons;
alias Foo = Tuple!string;
int[Foo] aa;
auto f1 = Foo("hello");
auto f2 = Foo(s1 ~ s2);
aa[f1] = 1;
aa[f2] = 2;
aa.writeln;
}
Gives:
[Tuple!string("hello"):2, Tuple!string("hello"):1]
Is this patch going to help fix that?
Comment #7 by k.hara.pg — 2014-07-04T17:50:37Z
(In reply to bearophile_hugs from comment #6)
[snip]
> Gives:
>
> [Tuple!string("hello"):2, Tuple!string("hello"):1]
>
> Is this patch going to help fix that?
Will change it to:
[Tuple!string("hello"):2]
Comment #8 by github-bugzilla — 2014-07-06T21:22:45Z