Enable support for generic methods with IDIC (#90180)
authorAaron Robinson <arobins@microsoft.com>
Wed, 9 Aug 2023 00:45:51 +0000 (17:45 -0700)
committerGitHub <noreply@github.com>
Wed, 9 Aug 2023 00:45:51 +0000 (17:45 -0700)
src/coreclr/vm/methodtable.cpp
src/tests/Interop/IDynamicInterfaceCastable/Program.cs

index df47319..1016a80 100644 (file)
@@ -714,7 +714,6 @@ PTR_MethodTable InterfaceInfo_t::GetApproxMethodTable(Module * pContainingModule
     // we call GetInterfaceImplementation on the object and call GetMethodDescForInterfaceMethod
     // with whatever type it returns.
     if (pServerMT->IsIDynamicInterfaceCastable()
-        && !pItfMD->HasMethodInstantiation()
         && !TypeHandle(pServerMT).CanCastTo(ownerType)) // we need to make sure object doesn't implement this interface in a natural way
     {
         TypeHandle implTypeHandle;
index b1c8d25..b558815 100644 (file)
@@ -30,6 +30,7 @@ namespace IDynamicInterfaceCastableTests
     public interface ITestGeneric<in T, out U>
     {
         U ReturnArg(T t);
+        V DoubleGenericArg<V>(V t);
     }
 
     public interface IDirectlyImplemented
@@ -140,6 +141,23 @@ namespace IDynamicInterfaceCastableTests
 
             return Unsafe.As<T, U>(ref t);
         }
+
+        V ITestGeneric<T, U>.DoubleGenericArg<V>(V v)
+        {
+            if (v is int i)
+            {
+                Assert.True(typeof(V) == typeof(int));
+                i *= 2;
+                return Unsafe.As<int, V>(ref i);
+            }
+            else if (v is string s)
+            {
+                Assert.True(typeof(V) == typeof(string));
+                s += s;
+                return Unsafe.As<string, V>(ref s);
+            }
+            throw new Exception("Unable to double");
+        }
     }
 
     [DynamicInterfaceCastableImplementation]
@@ -149,6 +167,23 @@ namespace IDynamicInterfaceCastableTests
         {
             return i;
         }
+
+        V ITestGeneric<int, int>.DoubleGenericArg<V>(V v)
+        {
+            if (v is int i)
+            {
+                Assert.True(typeof(V) == typeof(int));
+                i *= 2;
+                return Unsafe.As<int, V>(ref i);
+            }
+            else if (v is string s)
+            {
+                Assert.True(typeof(V) == typeof(string));
+                s += s;
+                return Unsafe.As<string, V>(ref s);
+            }
+            throw new Exception("Unable to double");
+        }
     }
 
     [DynamicInterfaceCastableImplementation]
@@ -374,6 +409,14 @@ namespace IDynamicInterfaceCastableTests
             Assert.Equal(expectedStr, testStr.ReturnArg(expectedStr));
             Assert.Equal(expectedStr, testVar.ReturnArg(expectedStr));
 
+            Console.WriteLine(" -- Validate generic method call");
+            Assert.Equal(expectedInt * 2, testInt.DoubleGenericArg<int>(42));
+            Assert.Equal(expectedStr + expectedStr, testInt.DoubleGenericArg<string>("str"));
+            Assert.Equal(expectedInt * 2, testStr.DoubleGenericArg<int>(42));
+            Assert.Equal(expectedStr + expectedStr, testStr.DoubleGenericArg<string>("str"));
+            Assert.Equal(expectedInt * 2, testVar.DoubleGenericArg<int>(42));
+            Assert.Equal(expectedStr + expectedStr, testVar.DoubleGenericArg<string>("str"));
+
             Console.WriteLine(" -- Validate delegate call");
             Func<int, int> funcInt = new Func<int, int>(testInt.ReturnArg);
             Assert.Equal(expectedInt, funcInt(expectedInt));