Do not check static methods for variance safety rules (#40152)
authorDavid Wrighton <davidwr@microsoft.com>
Thu, 30 Jul 2020 22:34:25 +0000 (15:34 -0700)
committerGitHub <noreply@github.com>
Thu, 30 Jul 2020 22:34:25 +0000 (15:34 -0700)
- There are no variance restrictions on the method signature of static members

This change brings the coreclr runtime into compliance with section 9.7 of Partition II of the ECMA 335 spec.

src/coreclr/src/vm/methodtablebuilder.cpp
src/tests/Loader/classloader/generics/Variance/Interfaces/NoVarianceCheckForStaticMethods.il [new file with mode: 0644]
src/tests/Loader/classloader/generics/Variance/Interfaces/NoVarianceCheckForStaticMethods.ilproj [new file with mode: 0644]

index aa72eb1..c50c02d 100644 (file)
@@ -3026,8 +3026,9 @@ MethodTableBuilder::EnumerateClassMethods()
             }
 
             // Check the appearance of covariant and contravariant in the method signature
-            // Note that variance is only supported for interfaces
-            if (bmtGenerics->pVarianceInfo != NULL)
+            // Note that variance is only supported for interfaces, and these rules are not
+            // checked for static methods as they cannot be called variantly.
+            if ((bmtGenerics->pVarianceInfo != NULL) && !IsMdStatic(dwMemberAttrs))
             {
                 SigPointer sp(pMemberSignature, cMemberSignature);
                 ULONG callConv;
diff --git a/src/tests/Loader/classloader/generics/Variance/Interfaces/NoVarianceCheckForStaticMethods.il b/src/tests/Loader/classloader/generics/Variance/Interfaces/NoVarianceCheckForStaticMethods.il
new file mode 100644 (file)
index 0000000..fdb11f2
--- /dev/null
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// Metadata version: v4.0.30319
+.assembly extern System.Runtime
+{
+  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....:
+  .ver 4:2:2:0
+}
+.assembly extern System.Console
+{
+  .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )                         // .?_....:
+  .ver 4:1:2:0
+}
+.assembly ConsoleApp5
+{
+  .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
+  .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
+                                                                                                                   63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
+
+  // --- The following custom attribute is added automatically, do not uncomment -------
+  //  .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) 
+
+  .hash algorithm 0x00008004
+  .ver 1:0:0:0
+}
+.module ConsoleApp5.dll
+// MVID: {580B623A-FB1A-403C-8F9C-8DB0E42D429C}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003       // WINDOWS_CUI
+.corflags 0x00000001    //  ILONLY
+// Image base: 0x047E0000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class private auto ansi beforefieldinit Program
+       extends [System.Runtime]System.Object
+{
+  .method private hidebysig static int32  Main() cil managed
+  {
+    .entrypoint
+    // Code size       34 (0x22)
+    .maxstack  8
+    IL_0000:  nop
+    IL_0001:  ldstr      "a"
+    IL_0006:  call       !0 class I2`2<string,string>::M1(!0)
+    IL_000b:  call       void [System.Console]System.Console::WriteLine(string)
+    IL_0010:  nop
+    IL_0011:  ldstr      "b"
+    IL_0016:  call       !1 class I2`2<string,string>::M2(!1)
+    IL_001b:  call       void [System.Console]System.Console::WriteLine(string)
+    IL_0020:  ldc.i4     100
+    IL_0021:  ret
+  } // end of method Program::Main
+
+  .method public hidebysig specialname rtspecialname 
+          instance void  .ctor() cil managed
+  {
+    // Code size       8 (0x8)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  call       instance void [System.Runtime]System.Object::.ctor()
+    IL_0006:  nop
+    IL_0007:  ret
+  } // end of method Program::.ctor
+
+} // end of class Program
+
+.class interface private abstract auto ansi I2`2<+ T1,- T2>
+{
+  .method public hidebysig static !T1  M1(!T1 x) cil managed
+  {
+    // Code size       2 (0x2)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } // end of method I2`2::M1
+
+  .method public hidebysig static !T2  M2(!T2 x) cil managed
+  {
+    // Code size       2 (0x2)
+    .maxstack  8
+    IL_0000:  ldarg.0
+    IL_0001:  ret
+  } // end of method I2`2::M2
+
+} // end of class I2`2
+
+
+// =============================================================
+
+// *********** DISASSEMBLY COMPLETE ***********************
\ No newline at end of file
diff --git a/src/tests/Loader/classloader/generics/Variance/Interfaces/NoVarianceCheckForStaticMethods.ilproj b/src/tests/Loader/classloader/generics/Variance/Interfaces/NoVarianceCheckForStaticMethods.ilproj
new file mode 100644 (file)
index 0000000..6e038d3
--- /dev/null
@@ -0,0 +1,10 @@
+<Project Sdk="Microsoft.NET.Sdk.IL">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+    <CLRTestPriority>0</CLRTestPriority>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="NoVarianceCheckForStaticMethods.il" />
+  </ItemGroup>
+</Project>