Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit ebccd98

Browse files
authored
Merge pull request #2337 from n8sh/issue-19332
hashOf fails to compile for const struct that has non-const toHash & has all fields bitwise-hashable merged-on-behalf-of: Nathan Sashihara <n8sh@users.noreply.github.com>
2 parents 3f50026 + d380bcc commit ebccd98

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/core/internal/hash.d

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
module core.internal.hash;
1111

1212
import core.internal.convert;
13-
import core.internal.traits : allSatisfy;
13+
import core.internal.traits : allSatisfy, Unconst;
1414

1515
// If true ensure that positive zero and negative zero have the same hash.
1616
// Historically typeid(float).getHash did this but hashOf(float) did not.
@@ -506,7 +506,7 @@ private enum _hashOfStruct =
506506
q{
507507
enum bool isChained = is(typeof(seed) : size_t);
508508
static if (!isChained) enum size_t seed = 0;
509-
static if (hasCallableToHash!T) //CTFE depends on toHash()
509+
static if (hasCallableToHash!(typeof(val))) //CTFE depends on toHash()
510510
{
511511
static if (isChained)
512512
return hashOf(cast(size_t) val.toHash(), seed);
@@ -517,7 +517,15 @@ q{
517517
{
518518
static if (__traits(hasMember, T, "toHash") && is(typeof(T.toHash) == function))
519519
{
520-
pragma(msg, "Warning: struct "~__traits(identifier, T)~" has method toHash, however it cannot be called with "~T.stringof~" this.");
520+
// TODO: in the future maybe this should be changed to a static
521+
// assert(0), because if there's a `toHash` the programmer probably
522+
// expected it to be called and a compilation failure here will
523+
// expose a bug in his code.
524+
// In the future we also might want to disallow non-const toHash
525+
// altogether.
526+
pragma(msg, "Warning: struct "~__traits(identifier, T)
527+
~" has method toHash, however it cannot be called with "
528+
~typeof(val).stringof~" this.");
521529
}
522530

523531
static if (T.tupleof.length == 0)
@@ -553,6 +561,7 @@ q{
553561
//struct or union hash
554562
size_t hashOf(T)(scope const auto ref T val, size_t seed = 0)
555563
if (!is(T == enum) && (is(T == struct) || is(T == union))
564+
&& !is(T == const) && !is(T == immutable)
556565
&& canBitwiseHash!T)
557566
{
558567
mixin(_hashOfStruct);
@@ -574,6 +583,15 @@ if (!is(T == enum) && (is(T == struct) || is(T == union))
574583
mixin(_hashOfStruct);
575584
}
576585

586+
//struct or union hash - https://issues.dlang.org/show_bug.cgi?id=19332 (support might be removed in future)
587+
size_t hashOf(T)(scope auto ref T val, size_t seed = 0)
588+
if (!is(T == enum) && (is(T == struct) || is(T == union))
589+
&& (is(T == const) || is(T == immutable))
590+
&& canBitwiseHash!T && !canBitwiseHash!(Unconst!T))
591+
{
592+
mixin(_hashOfStruct);
593+
}
594+
577595
//delegate hash. CTFE unsupported
578596
@trusted @nogc nothrow pure
579597
size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && is(T == delegate))

test/hash/src/test_hash.d

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ void main()
99
issue19204();
1010
issue19262();
1111
issue19282();
12+
issue19332(); // Support might be removed in the future!
1213
testTypeInfoArrayGetHash1();
1314
testTypeInfoArrayGetHash2();
1415
pr2243();
@@ -135,6 +136,20 @@ void issue19282()
135136
h = hashOf(c, h);
136137
}
137138

139+
/// Ensure hashOf works for const struct that has non-const toHash & has all
140+
/// fields bitwise-hashable. (Support might be removed in the future!)
141+
void issue19332()
142+
{
143+
static struct HasNonConstToHash
144+
{
145+
int a;
146+
size_t toHash() { return a; }
147+
}
148+
const HasNonConstToHash val;
149+
size_t h = hashOf(val);
150+
h = hashOf!(const HasNonConstToHash)(val); // Ensure doesn't match more than one overload.
151+
}
152+
138153
/// Tests ensure TypeInfo_Array.getHash uses element hash functions instead
139154
/// of hashing array data.
140155
void testTypeInfoArrayGetHash1()

0 commit comments

Comments
 (0)