From 753d12facef5aa9d7926e3e284bfb40b7197f016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Thu, 11 Aug 2022 17:44:20 +0900 Subject: [PATCH] Ensure methods on different instantiations are reflectable (#73749) --- .../Compiler/UsageBasedMetadataManager.cs | 21 +++++++++++++++++-- .../SmokeTests/Reflection/Reflection.cs | 20 ++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index d4e20f287a9..53b92c2eaae 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -465,9 +465,9 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD // ObjectGetTypeFlowDependencies don't need to be conditional in that case. They'll be added as needed. } - // Ensure fields can be consistently reflection set & get. if (type.HasInstantiation && !type.IsTypeDefinition && !IsReflectionBlocked(type)) { + // Ensure fields can be consistently reflection set & get. foreach (FieldDesc field in type.GetFields()) { // Tiny optimization: no get/set for literal fields since they only exist in metadata @@ -481,7 +481,24 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( factory.ReflectableField(field), factory.ReflectableField(field.GetTypicalFieldDefinition()), - "GetType called on the interface")); + "Fields have same reflectability")); + } + + // Ensure methods can be consistently reflection-accessed + foreach (MethodDesc method in type.GetMethods()) + { + if (IsReflectionBlocked(method)) + continue; + + // Generic methods need to be instantiated over something. + if (method.HasInstantiation) + continue; + + dependencies ??= new CombinedDependencyList(); + dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( + factory.ReflectableMethod(method), + factory.ReflectableMethod(method.GetTypicalMethodDefinition()), + "Methods have same reflectability")); } } } diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 02c66ce7143..14a419e8d9b 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -62,6 +62,7 @@ private static int Main() TestInvokeMethodMetadata.Run(); TestVTableOfNullableUnderlyingTypes.Run(); TestInterfaceLists.Run(); + TestMethodConsistency.Run(); // // Mostly functionality tests @@ -2021,6 +2022,25 @@ public static void Run() } } + class TestMethodConsistency + { + class MyGenericType + { + public static string MyMethod() => typeof(T).Name; + } + + struct Atom { } + + public static void Run() + { + object returned = Grab().Invoke(null, null); + if ((string)returned != nameof(Atom)) + throw new Exception(); + + static MethodInfo Grab() => typeof(MyGenericType).GetMethod(nameof(MyGenericType.MyMethod)); + } + } + #region Helpers private static Type SecretGetType(string testName, string typeName) -- GitLab