I have a partial fix for issues 8435 and 10118, but it's being blocked by issue 10567. Basically, the problem is that opCmp *must* be declared as:
struct T { int opCmp(ref const T t) const { ... } } Only when it's declared this way, will T's typeinfo.compare pick up the correct custom opCmp. If 'ref' is dropped, typeinfo.compare reverts to the default bitwise opCmp. If opCmp is a template function, typeinfo.compare reverts to the default bitwise opCmp. If any of the const's are dropped, typeinfo.compare reverts to the default bitwise opCmp. This is *in spite* of the fact that == works perfectly fine in all of these cases. This makes it basically impossible to use structs with custom opCmp as AA keys, because AA's use typeinfo.compare for key comparisons. When any of the above conditions happen, == and typeinfo.compare are inconsistent with each other, and the AA will malfunction. So you have bugs like: int[T] aa; auto t = T; auto u = t; assert(t==u); // N.B. t and u are equal assert(typeid(t).getHash(&t) == typeid(u).getHash(&u)); // OK aa[t] = 1; assert(u in aa); // fails aa[u] = 2; assert(aa[t] == 2); // fails assert(std.algorithm.count(aa.keys) == 1); // fails // This is the cause of the problem: assert(typeid(t).compare(&t, &u)==0); // fails :-( Bugzilla: http://d.puremagic.com/issues/show_bug.cgi?id=10567 T -- Customer support: the art of getting your clients to pay for your own incompetence.