use core.internal.hash for TypeInfo.getHash #2243
Conversation
Thanks for your pull request and interest in making D better, @IgorStepanov! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub fetch digger
dub run digger -- build "master + druntime#2243" |
e592ba2
to
1821686
Compare
Please, note, tests in another projects, which fails on After this PR, result string is |
FYI before this PR can be merged, the Project Tester needs to be green.
Yes, but we still want our CIs to be green ;-) |
Yeah, that's a bad test. Fixed & pushed tag. |
05917ea
to
7aac1c1
Compare
src/core/internal/hash.d
Outdated
//class or interface array or struct array with toHash(); CTFE depend on toHash() method | ||
//also do this for arrays of structs whose hashes would be calculated in a memberwise fashion | ||
{ | ||
size_t hash = seed; | ||
foreach (o; val) | ||
{ | ||
hash = hashOf(o, hash); | ||
hash = hashOf(hashOf(o), hash); //double hashing because TypeInfo.getHash doesn't allow to pass seed value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please explain why this is necessary. Does this patch make hashOf(o, hash)
not compile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah nevermind, I see
Also make
typeid(T).getHash(&val)
to get the same result withhashOf(val)
.
else | ||
return hashOf((&key)[0 .. 1], 0); | ||
return .hashOf((&key)[0 .. 1], 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes the meaning! Is that intentional? The old version was hashing the key as bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use object.hashOf
instead of rt.util.hash : hashOf
, because rt.util.hash
has been removed.
I may force use object.hashOf(void[])
if we strongly want bytes hash, but I think it is not needed.
@@ -672,25 +672,28 @@ extern (C) int _aaEqual(in TypeInfo tiRaw, in AA aa1, in AA aa2) | |||
extern (C) hash_t _aaGetHash(in AA* aa, in TypeInfo tiRaw) nothrow | |||
{ | |||
if (aa.empty) | |||
return 0; | |||
return hashOf(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: revert this to return 0
and change core.internal.hash
to match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core.internal.hash.hashOf
may use seed value.
The current function looks like
size_t hashOf(T)(T aa, size_t seed = 0) if (!is(T == enum) && __traits(isAssociativeArray, T))
{
if (!aa.length) return hashOf(0, seed);
}
If I rewrite it as...
size_t hashOf(T)(T aa, size_t seed = 0) if (!is(T == enum) && __traits(isAssociativeArray, T))
{
if (!aa.length) return seed;
}
... we will disable way to chain several hashes:
a = hashOf(cast(int[int])null, hashOf(cast(int[int])null));
b = hashOf(cast(int[int])null, hashOf(cast(int[int])null, hashOf(cast(int[int])null)));
// a == b but a should differs b
as result:
hashes of two arrays with different count of null AA will be same:
auto arr = [int[int].init, int[int].init];
auto arr2 = [int[int].init, int[int].init, int[int].init];
assert(hashOf(arr) != hashOf(arr2)); // will be failed
src/rt/typeinfo/ti_cent.d
Outdated
@@ -30,7 +28,7 @@ class TypeInfo_zi : TypeInfo | |||
|
|||
override size_t getHash(scope const void* p) | |||
{ | |||
return rt.util.hash.hashOf(p[0 .. cent.sizeof], 0); | |||
return hashOf(p[0 .. cent.sizeof], 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To match what's in core.internal.hash
you should instead write:
return hashOf(*cast(const ucent*) p);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/rt/typeinfo/ti_delegate.d
Outdated
@@ -28,7 +27,7 @@ class TypeInfo_D : TypeInfo | |||
|
|||
override size_t getHash(scope const void* p) | |||
{ | |||
return rt.util.hash.hashOf(p[0 .. dg.sizeof], 0); | |||
return hashOf(*cast(dg*)p, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for 0
second argument. Currently it will be inferred, and in the future an explicit chaining argument might result in different behavior (#2246).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/rt/typeinfo/ti_long.d
Outdated
@@ -28,7 +26,7 @@ class TypeInfo_l : TypeInfo | |||
|
|||
override size_t getHash(scope const void* p) | |||
{ | |||
return rt.util.hash.hashOf(p[0 .. long.sizeof], 0); | |||
return hashOf(*cast(long*)p, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for 0
second argument. Currently it will be inferred, and in the future an explicit chaining argument might result in different behavior (#2246).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/rt/typeinfo/ti_ucent.d
Outdated
@@ -30,7 +28,7 @@ class TypeInfo_zk : TypeInfo | |||
|
|||
override size_t getHash(scope const void* p) | |||
{ | |||
return rt.util.hash.hashOf(p[0 .. ucent.sizeof], 0); | |||
return hashOf(p[0 .. ucent.sizeof], 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To match what's in core.internal.hash
you should instead write:
return hashOf(*cast(const ucent*) p);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -1703,7 +1703,7 @@ class TypeInfo_Class : TypeInfo | |||
override size_t getHash(scope const void* p) @trusted const | |||
{ | |||
auto o = *cast(Object*)p; | |||
return o ? o.toHash() : 0; | |||
return hashOf(o ? o.toHash() : 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If #2246 is accepted you will be able to revert this to o ? o.toHash() : 0
.
@@ -1930,14 +1934,11 @@ class TypeInfo_Struct : TypeInfo | |||
assert(p); | |||
if (xtoHash) | |||
{ | |||
return (*xtoHash)(p); | |||
return hashOf((*xtoHash)(p)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If #2246 is accepted you will be able to revert this to return (*xtoHash)(p);
Interface* pi = **cast(Interface ***)*cast(void**)p; | ||
Object o = cast(Object)(*cast(void**)p - pi.offset); | ||
assert(o); | ||
return o.toHash(); | ||
return hashOf(o.toHash()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If #2246 is accepted you will be able to revert this to return o.toHash();
@@ -21,7 +21,7 @@ class TypeInfo_n : TypeInfo | |||
|
|||
override size_t getHash(scope const void* p) const | |||
{ | |||
return 0; | |||
return hashOf(cast(void*)null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Post #2246 this should be the same as return 0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same above:
hashOf([null, null])
and hashOf([null, null, null])
should have different values, thus we need chaining by seed, thus we need to rehash seed 0 each time.
src/rt/typeinfo/ti_ulong.d
Outdated
@@ -28,7 +27,7 @@ class TypeInfo_m : TypeInfo | |||
|
|||
override size_t getHash(scope const void* p) | |||
{ | |||
return rt.util.hash.hashOf(p[0 .. ulong.sizeof], 0); | |||
return hashOf(*cast(ulong*)p, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for 0
second argument. Currently it will be inferred, and in the future an explicit chaining argument might result in different behavior (#2246).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
a5b15c1
to
939b8aa
Compare
@wilzbach ping |
Would be nice to still have this as this should raise awareness in case someone runs into similar issues. It's simple about adding a file to the |
add changelog for PR #2243 merged-on-behalf-of: Jacob Carlborg <jacob-carlborg@users.noreply.github.com>
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
dlang/druntime#2243 was intended to make `typeid(x).getHash(&x)` match `hashOf(x)` but did not account for structs with auto-generated `__xtoHash`.
Use the new
core.internal.hash.hashOf
in allTypeInfo.getHash
instead of the oldrt.util.hash.hashOf
.Also make
typeid(T).getHash(&val)
to get the same result withhashOf(val)
.