Delete invalid GVM analysis optimization (#71803)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Fri, 8 Jul 2022 04:49:43 +0000 (13:49 +0900)
committerGitHub <noreply@github.com>
Fri, 8 Jul 2022 04:49:43 +0000 (13:49 +0900)
There was an optimization that was trying to prevent the compiler from doing unnecessary work when analyzing generic virtual methods. The optimization is invalid.

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMDependenciesNode.cs
src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs

index f78bc2e..e13378f 100644 (file)
@@ -117,11 +117,6 @@ namespace ILCompiler.DependencyAnalysis
                     potentialOverrideType.ConvertToCanonForm(CanonicalFormKind.Specific) != potentialOverrideType)
                     continue;
 
-                // Similarly, if the type is canonical but this method instantiation isn't, don't mix them.
-                if (!methodIsShared &&
-                    potentialOverrideType.IsCanonicalSubtype(CanonicalFormKind.Any))
-                    continue;
-
                 // If this is an interface gvm, look for types that implement the interface
                 // and other instantantiations that have the same canonical form.
                 // This ensure the various slot numbers remain equivalent across all types where there is an equivalence
index 4d8289e..85af640 100644 (file)
@@ -27,6 +27,7 @@ class Generics
         TestGvmDelegates.Run();
         TestGvmDependencies.Run();
         TestGvmLookups.Run();
+        TestSharedAndUnsharedGvmAnalysisRegression.Run();
         TestInterfaceVTableTracking.Run();
         TestClassVTableTracking.Run();
         TestReflectionInvoke.Run();
@@ -1664,6 +1665,36 @@ class Generics
         }
     }
 
+    class TestSharedAndUnsharedGvmAnalysisRegression
+    {
+        interface IAtom { }
+        interface IPhantom { }
+        class Atom : IAtom, IPhantom { }
+
+        class Lol<TLeft> where TLeft : IAtom, IPhantom
+        {
+            public static void Run() => ((IPartitionedStreamRecipient<int>)new RightChildResultsRecipient<TLeft, int>()).ReceivePackage<int>();
+        }
+
+        interface IPartitionedStreamRecipient<T>
+        {
+            void ReceivePackage<U>();
+        }
+
+        sealed class RightChildResultsRecipient<TLeftInput, TRightInput> : IPartitionedStreamRecipient<TRightInput>
+        {
+            public void ReceivePackage<U>() => Console.WriteLine("Accepted");
+        }
+
+        static Type s_atom = typeof(Atom);
+
+        public static void Run()
+        {
+            // Make sure the compiler never saw anything more concrete than Lol<__Canon>.
+            typeof(Lol<>).MakeGenericType(s_atom).GetMethod("Run").Invoke(null, Array.Empty<object>());
+        }
+    }
+
     class TestFieldAccess
     {
         class ClassType { }