From 45b7fb12ce5a37c7b9cfe2c248991401719b4cf9 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Fri, 11 Nov 2022 13:24:05 -0800 Subject: [PATCH 1/2] Fix Equals in hot reload scenario --- .../src/System/Reflection/MdFieldInfo.cs | 6 +++- .../src/System/Reflection/RtFieldInfo.cs | 5 ++- .../src/System/Reflection/RuntimeEventInfo.cs | 6 +++- .../System/Reflection/RuntimePropertyInfo.cs | 5 ++- .../System/Reflection/ReflectionCacheTests.cs | 35 ++++++++++++++++++- 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs index 8f241f4d8b6b3..eba04c404f479 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs @@ -46,7 +46,11 @@ o is MdFieldInfo m && public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && + obj is MdFieldInfo fi && + fi.m_tkField == m_tkField && + ReferenceEquals(fi.m_declaringType, m_declaringType) && + ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_tkField.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs index 8ff2878596daf..58de30a1976c3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs @@ -118,7 +118,10 @@ internal override RuntimeModule GetRuntimeModule() public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && + obj is RtFieldInfo fi && + fi.m_fieldHandle == m_fieldHandle && + ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_fieldHandle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs index 09adb05fc289c..943c4d6ccd050 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs @@ -71,7 +71,11 @@ public override string ToString() public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && + obj is RuntimeEventInfo ei && + ei.m_token == m_token && + ReferenceEquals(ei.m_declaringType, m_declaringType) && + ReferenceEquals(ei.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs index b844b6eaa0d75..a6b97f36353b8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -182,7 +182,10 @@ public override IList GetCustomAttributesData() public override bool Equals(object? obj) => ReferenceEquals(this, obj) || - (MetadataUpdater.IsSupported && CacheEquals(obj)); + (MetadataUpdater.IsSupported && obj is RuntimePropertyInfo rpi && + rpi.m_token == m_token && + ReferenceEquals(rpi.m_declaringType, m_declaringType) && + ReferenceEquals(rpi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType())); public override int GetHashCode() => HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode()); diff --git a/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs index 40ce236003222..bb2c388ab9d11 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs @@ -7,8 +7,18 @@ namespace System.Reflection.Tests { + public class A + { + public string P { get; set; } + public int F; +#pragma warning disable CS0067 + public event EventHandler E; +#pragma warning restore CS0067 + public void M() { } + } + [Collection(nameof(DisableParallelization))] - public class ReflectionCacheTests + public class ReflectionCacheTests : A { private static bool IsMetadataUpdateAndRemoteExecutorSupported => PlatformDetection.IsMetadataUpdateSupported && RemoteExecutor.IsSupported; @@ -47,6 +57,10 @@ public void GetMembers_MultipleCalls_SameObjects() AssertSameEqualAndHashCodeEqual(fi1, fi2); AssertSameEqualAndHashCodeEqual(ei1, ei2); AssertSameEqualAndHashCodeEqual(ci1, ci2); + + PropertyInfo parentProperty = typeof(A).GetProperty("P"); + PropertyInfo childProperty = s_type.GetProperty("P"); + Assert.NotEqual(parentProperty, childProperty); } void AssertSameEqualAndHashCodeEqual(object o1, object o2) @@ -87,6 +101,20 @@ public void GetMembers_MultipleCalls_ClearCache_ReflectionCacheTestsType() EventInfo ei1 = s_type.GetEvent(nameof(Event1)); ConstructorInfo ci1 = s_type.GetConstructor(Type.EmptyTypes); + PropertyInfo parentProperty = typeof(A).GetProperty("P"); + PropertyInfo childProperty = s_type.GetProperty("P"); + FieldInfo parentField = typeof(A).GetField("F"); + FieldInfo childField = s_type.GetField("F"); + MethodInfo parentMethod = typeof(A).GetMethod("M"); + MethodInfo childMethod = s_type.GetMethod("M"); + EventInfo parentEvent = typeof(A).GetEvent("E"); + EventInfo childEvent = s_type.GetEvent("E"); + + Assert.NotEqual(parentProperty, childProperty); + Assert.NotEqual(parentField, childField); + Assert.NotEqual(parentMethod, childMethod); + Assert.NotEqual(parentEvent, childEvent); + clearCache(new[] { typeof(ReflectionCacheTests) }); MethodInfo mi2 = s_type.GetMethod(nameof(Method)); @@ -95,6 +123,11 @@ public void GetMembers_MultipleCalls_ClearCache_ReflectionCacheTestsType() EventInfo ei2 = s_type.GetEvent(nameof(Event1)); ConstructorInfo ci2 = s_type.GetConstructor(Type.EmptyTypes); + Assert.NotEqual(parentProperty, childProperty); + Assert.NotEqual(parentField, childField); + Assert.NotEqual(parentMethod, childMethod); + Assert.NotEqual(parentEvent, childEvent); + AssertNotSameSameButEqualAndHashCodeEqual(mi1, mi2); AssertNotSameSameButEqualAndHashCodeEqual(pi1, pi2); AssertNotSameSameButEqualAndHashCodeEqual(fi1, fi2); From bc62c385b60b925c116104c525984f79b9036b05 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Fri, 11 Nov 2022 15:08:15 -0800 Subject: [PATCH 2/2] Update src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs Co-authored-by: Steve Harter --- .../tests/System/Reflection/ReflectionCacheTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs index bb2c388ab9d11..a5922112c1d98 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/ReflectionCacheTests.cs @@ -60,6 +60,8 @@ public void GetMembers_MultipleCalls_SameObjects() PropertyInfo parentProperty = typeof(A).GetProperty("P"); PropertyInfo childProperty = s_type.GetProperty("P"); + Assert.NotNull(parentProperty); + Assert.NotNull(childProperty); Assert.NotEqual(parentProperty, childProperty); }