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

use core.internal.hash for TypeInfo.getHash #2243

Merged
merged 1 commit into from Jul 23, 2018

Conversation

IgorStepanov
Copy link
Contributor

Use the new core.internal.hash.hashOf in all TypeInfo.getHash instead of the old rt.util.hash.hashOf.
Also make typeid(T).getHash(&val) to get the same result with hashOf(val).

@dlang-bot
Copy link
Contributor

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 verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the annotated coverage diff directly on GitHub with CodeCov's browser extension
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

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 references

Your 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 locally

If 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"

@IgorStepanov
Copy link
Contributor Author

Please, note, tests in another projects, which fails on continuous-integration/jenkins/pr-merge depends on associative array order:
for example, in ae xml build expects result string
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"><text fill="red" x="0" y="15">I love SVG</text></svg>
or
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"><text x="0" y="15" fill="red">I love SVG</text></svg>

After this PR, result string is
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"><text fill="red" y="15" x="0">I love SVG</text></svg>
Obviously this fails is a test issue and doesn't threaten real user code.

@wilzbach
Copy link
Member

wilzbach commented Jul 5, 2018

Please, note, tests in another projects, which fails on continuous-integration/jenkins/pr-merge

FYI before this PR can be merged, the Project Tester needs to be green.
In other words: ae needs to pass on the Project Tester.
CC @CyberShadow

Obviously this fails is a test issue and doesn't threaten real user code.

Yes, but we still want our CIs to be green ;-)

@CyberShadow
Copy link
Member

Yeah, that's a bad test. Fixed & pushed tag.

//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
Copy link
Member

@n8sh n8sh Jul 9, 2018

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?

Copy link
Member

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 with hashOf(val).

else
return hashOf((&key)[0 .. 1], 0);
return .hashOf((&key)[0 .. 1], 0);
Copy link
Member

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.

Copy link
Contributor Author

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);
Copy link
Member

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.

Copy link
Contributor Author

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

@@ -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);
Copy link
Member

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);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -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);
Copy link
Member

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).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -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);
Copy link
Member

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).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -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);
Copy link
Member

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);

Copy link
Contributor Author

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);
Copy link
Member

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));
Copy link
Member

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());
Copy link
Member

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);
Copy link
Member

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.

Copy link
Contributor Author

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.

@@ -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);
Copy link
Member

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).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@wilzbach wilzbach added the 72h no objection -> merge The PR will be merged if there are no objections raised. label Jul 20, 2018
@IgorStepanov
Copy link
Contributor Author

@wilzbach ping

@wilzbach wilzbach merged commit cb5efa9 into dlang:master Jul 23, 2018
@wilzbach
Copy link
Member

I think we should add a small changelog entry stating that the default toHash method has been changed to use hashOf and thus as an resulted e.g. tests which fasly assume that the order of built-in associative arrays is fixed, may fail.

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 changelog folder.
See https://github.com/dlang/druntime/tree/master/changelog

IgorStepanov added a commit to IgorStepanov/druntime that referenced this pull request Jul 28, 2018
IgorStepanov added a commit to IgorStepanov/druntime that referenced this pull request Jul 28, 2018
IgorStepanov added a commit to IgorStepanov/druntime that referenced this pull request Jul 28, 2018
@IgorStepanov
Copy link
Contributor Author

@wilzbach Thanks!

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 changelog folder.

Something like #2256 ?

IgorStepanov added a commit to IgorStepanov/druntime that referenced this pull request Jul 28, 2018
IgorStepanov added a commit to IgorStepanov/druntime that referenced this pull request Jul 28, 2018
dlang-bot added a commit that referenced this pull request Jul 28, 2018
add changelog for PR #2243
merged-on-behalf-of: Jacob Carlborg <jacob-carlborg@users.noreply.github.com>
n8sh added a commit to n8sh/dmd that referenced this pull request Sep 8, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Sep 24, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Oct 25, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Oct 31, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Nov 6, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Nov 6, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Nov 6, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Nov 6, 2018
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Jan 9, 2019
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Jan 9, 2019
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Jan 14, 2019
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
n8sh added a commit to n8sh/dmd that referenced this pull request Jan 14, 2019
dlang/druntime#2243 was intended to make
`typeid(x).getHash(&x)` match `hashOf(x)` but did not account for
structs with auto-generated `__xtoHash`.
@n8sh n8sh mentioned this pull request Aug 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
72h no objection -> merge The PR will be merged if there are no objections raised.
Projects
None yet
5 participants