-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ValueType.GetHashCode not calling overriden method on nested field #98754
Conversation
@@ -164,7 +164,8 @@ private unsafe int RegularGetValueTypeHashCode(ref byte data, int numFields) | |||
var fieldValue = (ValueType)RuntimeImports.RhBox(fieldType, ref fieldData); | |||
if (fieldValue != null) | |||
{ | |||
hashCode = fieldValue.GetHashCodeImpl(); | |||
// call virtual method to handle overriden case | |||
hashCode = fieldValue.GetHashCode(); |
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 think GetHashCodeImpl
can now be inlined into GetHashCode
.
The only reason we had GetHashCodeImpl
was because it was emulating CoreCLR behavior that did not call the GetHashCode
on the field type (even if it had one) but instead used the fallback algorithm.
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.
Is it feasible to use System.HashCode
for NativeAOT here? Will it bring unintended dependency or complexity?
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 think it would be fine to use System.HashCode
. This was mirroring the CoreCLR-JIT logic but now it diverged because that's how forks usually end up.
If we really wanted to, we could probably unify this to the point of sharing a part of this file, maybe with an ifdef or two. From a quick look GetHashCodeStrategy
could be implemented using NativeAOT's __GetFieldHelper
.
src/coreclr/nativeaot/System.Private.CoreLib/src/System/ValueType.cs
Outdated
Show resolved
Hide resolved
@@ -95,21 +95,17 @@ public override unsafe bool Equals([NotNullWhen(true)] object? obj) | |||
|
|||
public override unsafe int GetHashCode() | |||
{ | |||
int hashCode = (int)this.GetMethodTable()->HashCode; | |||
HashCode hashCode = default; | |||
hashCode.Add(this.GetMethodTable()->HashCode); |
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.
hashCode.Add(this.GetMethodTable()->HashCode); | |
hashCode.Add((IntPtr)this.GetMethodTable()); |
to match CoreCLR
@@ -150,7 +137,9 @@ private unsafe int RegularGetValueTypeHashCode(ref byte data, int numFields) | |||
} | |||
else if (fieldType->IsPrimitive) | |||
{ | |||
hashCode = FastGetValueTypeHashCodeHelper(fieldType, ref fieldData); | |||
HashCode hash = default; |
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.
The method should take ref HashCode
argument instead of creating a new instance here.
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 meant change RegularGetValueTypeHashCode
to take ref HashCode
argument and delete HashCode hash = default;
that this comment is attached to.
Noticed that the test case doesn't actually cover this case. It should not match the default comparison/hashcode strategy of nested field. Using manual version of int Abs to avoid introducing any dependency. |
What is the test case that you are talking about?
Nit: Dependencies like this are not a problem in the tests. |
} | ||
|
||
private static unsafe int FastGetValueTypeHashCodeHelper(MethodTable* type, ref byte data) | ||
private static unsafe void AddHashCodeForField(ref HashCode hashCode, MethodTable* type, ref byte data) |
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 method name is a bit misleading. It cannot be used to add hashcode for any field.
I like the Span returning method that you had here before better.
Describing the failing case:
The original reproduction uses |
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.
Thanks
Follow up for #97590 (comment)
This is indeed a bug, since
GetHashCode
can return different result whenEquals
is returningtrue
.