@@ -43,9 +43,11 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
43
43
{
44
44
alias ElementType = typeof (val[0 ]);
45
45
static if (is (ElementType == interface ) || is (ElementType == class ) ||
46
+ (is (ElementType == struct ) && ! isNonReference! ElementType) ||
46
47
((is (ElementType == struct ) || is (ElementType == union ))
47
48
&& is (typeof (val[0 ].toHash()) == size_t )))
48
49
// class or interface array or struct array with toHash(); CTFE depend on toHash() method
50
+ // also do this for arrays of structs whose hashes would be calculated in a memberwise fashion
49
51
{
50
52
size_t hash = seed;
51
53
foreach (o; val)
@@ -135,7 +137,15 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T ==
135
137
pragma (msg, " Warning: struct " ~ __traits(identifier, T)~ " has method toHash, however it cannot be called with " ~ T.stringof~ " this." );
136
138
}
137
139
138
- static if (is (typeof (toUbyte(val)) == const (ubyte )[]))// CTFE ready for structs without reference fields
140
+ static if (is (T == struct ) && ! isNonReference! T) // Memberwise hashing.
141
+ {
142
+ static foreach (i, F; typeof (val.tupleof))
143
+ {
144
+ seed = hashOf(val.tupleof[i], seed);
145
+ }
146
+ return seed;
147
+ }
148
+ else static if (is (typeof (toUbyte(val)) == const (ubyte )[]))// CTFE ready for structs without reference fields
139
149
{
140
150
return bytesHash (toUbyte(val), seed);
141
151
}
@@ -446,6 +456,16 @@ unittest // issue 15111
446
456
testAlias! (int [8 ]);
447
457
}
448
458
459
+ nothrow pure @system unittest // issue 18918
460
+ {
461
+ static struct S { string array; }
462
+ auto s1 = S(" abc" );
463
+ auto s2 = S(s1.array.idup);
464
+ assert (hashOf(s1) == hashOf(s2));
465
+ enum e = hashOf(S(" abc" ));
466
+ assert (hashOf(s1) == e);
467
+ }
468
+
449
469
// MurmurHash3 was written by Austin Appleby, and is placed in the public
450
470
// domain. The author hereby disclaims copyright to this source code.
451
471
0 commit comments