Pass generic context argument for shared instance methods on generic interfaces ...
authorAndon Andonov <anandono@microsoft.com>
Thu, 8 Mar 2018 20:47:19 +0000 (21:47 +0100)
committerJan Kotas <jkotas@microsoft.com>
Thu, 8 Mar 2018 20:47:19 +0000 (12:47 -0800)
* Add checks and regression test

* Uncomment InvokeConsumer tests

* Revert JIT Interface Check

src/vm/method.cpp
tests/src/Regressions/coreclr/15241/genericcontext.il [new file with mode: 0644]
tests/src/Regressions/coreclr/15241/genericcontext.ilproj [new file with mode: 0644]
tests/src/reflection/DefaultInterfaceMethods/InvokeConsumer.cs

index 877874453770bade7365b4862f8f06e081839ea3..9b3080ec6c90a60f4794d26e0381c4968ffdf710 100644 (file)
@@ -1639,7 +1639,7 @@ BOOL MethodDesc::IsSharedByGenericMethodInstantiations()
 //     - there is no this pointer providing generic dictionary info
 // * shared-code instance methods in instantiated generic structs (e.g. void MyValueType<string>::m())
 //     - unboxed 'this' pointer in value-type instance methods don't have MethodTable pointer by definition
-// * default interface method called via interface dispatch (e. g. IFoo<string>.Foo calling into IFoo<object>::Foo())
+// * shared instance and default interface methods called via interface dispatch (e. g. IFoo<string>.Foo calling into IFoo<object>::Foo())
 //     - this pointer is ambiguous as it can implement more than one IFoo<T>
 BOOL MethodDesc::RequiresInstMethodTableArg() 
 {
@@ -1648,7 +1648,8 @@ BOOL MethodDesc::RequiresInstMethodTableArg()
     return
         IsSharedByGenericInstantiations() &&
         !HasMethodInstantiation() &&
-        (IsStatic() || GetMethodTable()->IsValueType() || IsDefaultInterfaceMethod());
+        (IsStatic() || GetMethodTable()->IsValueType() || (GetMethodTable()->IsInterface() && !IsAbstract()));
+
 }
 
 //*******************************************************************************
@@ -1670,7 +1671,7 @@ BOOL MethodDesc::RequiresInstArg()
     LIMITED_METHOD_DAC_CONTRACT;
 
     BOOL fRet = IsSharedByGenericInstantiations() &&
-        (HasMethodInstantiation() || IsStatic() || GetMethodTable()->IsValueType() || IsDefaultInterfaceMethod());
+        (HasMethodInstantiation() || IsStatic() || GetMethodTable()->IsValueType() || (GetMethodTable()->IsInterface() && !IsAbstract()));
 
     _ASSERT(fRet == (RequiresInstMethodTableArg() || RequiresInstMethodDescArg()));
     return fRet;
@@ -1747,7 +1748,7 @@ BOOL MethodDesc::AcquiresInstMethodTableFromThis() {
         !HasMethodInstantiation() &&
         !IsStatic() &&
         !GetMethodTable()->IsValueType() &&
-        !IsDefaultInterfaceMethod();
+        !(GetMethodTable()->IsInterface() && !IsAbstract());
 }
 
 //*******************************************************************************
diff --git a/tests/src/Regressions/coreclr/15241/genericcontext.il b/tests/src/Regressions/coreclr/15241/genericcontext.il
new file mode 100644 (file)
index 0000000..1529016
--- /dev/null
@@ -0,0 +1,74 @@
+.assembly extern mscorlib { }
+
+.assembly extern System.Runtime {  }
+
+.assembly genericcontext { }
+
+.class interface private abstract auto ansi IFoo`1<T>
+{
+  .method public hidebysig newslot virtual instance bool IsInst(valuetype [mscorlib]System.RuntimeTypeHandle a) cil managed
+  {
+    ldarg.0 
+    ldarg.1 
+    call instance bool class IFoo`1<!T>::IsInstImpl(valuetype [mscorlib]System.RuntimeTypeHandle)
+
+    ret
+  }
+
+  .method private hidebysig instance bool IsInstImpl(valuetype [mscorlib]System.RuntimeTypeHandle a) cil managed
+  {
+    ldarga 1 
+    ldtoken !T 
+    call instance bool valuetype [mscorlib]System.RuntimeTypeHandle::Equals(valuetype [mscorlib]System.RuntimeTypeHandle) 
+    ret
+  }
+}
+
+.class private auto ansi beforefieldinit Gen`1<T>
+       extends [mscorlib]System.Object
+{ }
+
+.class private auto ansi beforefieldinit Fooer`1<T>
+       extends [mscorlib]System.Object
+       implements class IFoo`1<class Gen`1<!T>>
+{
+  .method public hidebysig specialname rtspecialname 
+          instance void .ctor() cil managed
+  {
+    ldarg.0
+    call instance void [mscorlib]System.Object::.ctor()
+    ret
+  }
+}
+
+.method public hidebysig static int32  RunTest() cil managed
+{
+  newobj instance void class Fooer`1<object>::.ctor() 
+  ldtoken class Gen`1<class [mscorlib]System.Object> 
+  callvirt instance bool class IFoo`1<class Gen`1<object>>::IsInst(valuetype [mscorlib]System.RuntimeTypeHandle) 
+  
+  // If IFoo::IsInst returns true, return 100 else 0
+  brtrue.s   PASS
+  ldc.i4 0
+  br.s       FAIL
+  PASS:  ldc.i4 100
+  FAIL:  nop
+  ret
+}
+
+.method public hidebysig static int32 Main() cil managed
+{
+  .entrypoint
+
+  ldstr "DefaultImplementationsOfInterfaces"
+  call bool [System.Runtime]System.Runtime.CompilerServices.RuntimeFeature::IsSupported(string)
+
+  // If default interfaces are not supported, consider the test successful.
+  brtrue DoRunTest
+  ldc.i4 100
+  ret
+
+DoRunTest:
+  call int32 RunTest()
+  ret
+}
diff --git a/tests/src/Regressions/coreclr/15241/genericcontext.ilproj b/tests/src/Regressions/coreclr/15241/genericcontext.ilproj
new file mode 100644 (file)
index 0000000..ea2fd35
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <AssemblyName>genericcontext</AssemblyName>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{85DFC527-4DB1-595E-A7D7-E94EE1F8140D}</ProjectGuid>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+    <CLRTestPriority>0</CLRTestPriority>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Include="genericcontext.il" />
+  </ItemGroup>
+
+
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
index 742fd244e570d9e7fdcf5119e08ed6faa3c13d05..4ac82f9a1b84b602459ab7945566e98acc7559d6 100644 (file)
@@ -23,9 +23,8 @@ class Program
         if (!((RuntimeTypeHandle)typeof(IFoo<Fooer>).GetMethod("DefaultMethod").Invoke(new Fooer(), new object[] { })).Equals(typeof(Fooer).TypeHandle))
             return 12;
 
-        // Likely failing due to https://github.com/dotnet/coreclr/issues/15241
-        //if (!((RuntimeTypeHandle)typeof(IFoo<Fooer>).GetMethod("InstanceMethod").Invoke(new Fooer(), new object[] { })).Equals(typeof(Fooer[]).TypeHandle))
-        //    return 13;
+        if (!((RuntimeTypeHandle)typeof(IFoo<Fooer>).GetMethod("InstanceMethod").Invoke(new Fooer(), new object[] { })).Equals(typeof(Fooer[]).TypeHandle))
+            return 13;
 
         if ((int)typeof(IFoo).GetMethod("DefaultMethod").Invoke(new ValueFooer(), new object[] { 1 }) != 51)
             return 22;
@@ -36,9 +35,8 @@ class Program
         if (!((RuntimeTypeHandle)typeof(IFoo<Fooer>).GetMethod("DefaultMethod").Invoke(new ValueFooer(), new object[] { })).Equals(typeof(Fooer).TypeHandle))
             return 32;
 
-        // Likely failing due to https://github.com/dotnet/coreclr/issues/15241
-        //if (!((RuntimeTypeHandle)typeof(IFoo<Fooer>).GetMethod("InstanceMethod").Invoke(new ValueFooer(), new object[] { })).Equals(typeof(Fooer[]).TypeHandle))
-        //    return 33;
+        if (!((RuntimeTypeHandle)typeof(IFoo<Fooer>).GetMethod("InstanceMethod").Invoke(new ValueFooer(), new object[] { })).Equals(typeof(Fooer[]).TypeHandle))
+            return 33;
 
         return 100;
     }