Canonicalize arguments before loading instantiation when dropGenericArgumentLevel...
authorFadi Hanna <fadim@microsoft.com>
Wed, 18 Mar 2020 20:03:29 +0000 (13:03 -0700)
committerFadi Hanna <fadim@microsoft.com>
Thu, 9 Apr 2020 07:49:01 +0000 (00:49 -0700)
src/coreclr/src/vm/siginfo.cpp
src/coreclr/tests/src/GC/Regressions/Github/runtime_32848/runtime_32848.cs [new file with mode: 0644]
src/coreclr/tests/src/GC/Regressions/Github/runtime_32848/runtime_32848.csproj [new file with mode: 0644]

index 58b8d86..dc21a23 100644 (file)
@@ -1356,7 +1356,7 @@ TypeHandle SigPointer::GetTypeHandleThrowing(
                             if (tmpEType == ELEMENT_TYPE_CLASS)
                                 typeHnd = TypeHandle(g_pCanonMethodTableClass);
                         }
-                        else if ((elemType == (CorElementType) ELEMENT_TYPE_CANON_ZAPSIG) ||
+                        else if ((elemType == (CorElementType)ELEMENT_TYPE_CANON_ZAPSIG) ||
                                  (CorTypeInfo::GetGCType_NoThrow(elemType) == TYPE_GC_REF))
                         {
                             typeHnd = TypeHandle(g_pCanonMethodTableClass);
@@ -1389,6 +1389,11 @@ TypeHandle SigPointer::GetTypeHandleThrowing(
                         thisinst = NULL;
                         break;
                     }
+
+                    if (dropGenericArgumentLevel && level == CLASS_LOAD_APPROXPARENTS)
+                    {
+                        typeHnd = ClassLoader::CanonicalizeGenericArg(typeHnd);
+                    }
                 }
                 thisinst[i] = typeHnd;
                 IfFailThrowBF(psig.SkipExactlyOne(), BFA_BAD_SIGNATURE, pOrigModule);
diff --git a/src/coreclr/tests/src/GC/Regressions/Github/runtime_32848/runtime_32848.cs b/src/coreclr/tests/src/GC/Regressions/Github/runtime_32848/runtime_32848.cs
new file mode 100644 (file)
index 0000000..34d0dec
--- /dev/null
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+public struct MyStruct<TRequest, TResponse>
+{
+    int _id;
+    public MyStruct(int id) { _id = id; }
+    public override string ToString() => this.GetType().ToString() + " = " + _id;
+}
+
+public struct GenStruct<T> { }
+
+public sealed class MyStructWrapper<TRequest, TResponse>
+{
+    public MyStruct<TRequest, TResponse> _field;
+
+    public MyStructWrapper(MyStruct<TRequest, TResponse> value)
+    {
+        _field = value;
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public override string ToString() => _field.ToString();
+}
+
+public abstract class BaseStructCreator
+{
+    public abstract MyStructWrapper<TRequest, TResponse> GetMyStructWrapper<TRequest, TResponse>() where TRequest : class;
+}
+
+public class StructCreator : BaseStructCreator
+{
+    public override MyStructWrapper<TRequest, TResponse> GetMyStructWrapper<TRequest, TResponse>()
+    {
+        return new MyStructWrapper<TRequest, TResponse>(CreateCall<TRequest, TResponse>());
+    }
+    protected virtual MyStruct<TRequest, TResponse> CreateCall<TRequest, TResponse>() where TRequest : class
+    {
+        return new MyStruct<TRequest, TResponse>(123);
+    }
+}
+
+class DerivedCreator : StructCreator
+{
+    protected override MyStruct<TRequest, TResponse> CreateCall<TRequest, TResponse>()
+    {
+        return new MyStruct<TRequest, TResponse>(456);
+    }
+}
+
+public class Test
+{
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    static string RunTest()
+    {
+        var creator = new DerivedCreator();
+        var wrapper = creator.GetMyStructWrapper<Exception, GenStruct<string>>();
+        return wrapper.ToString();
+    }
+    public static int Main()
+    {
+        Console.WriteLine("Expected: MyStruct`2[System.Exception,GenStruct`1[System.String]] = 456");
+
+        string result = RunTest();
+        Console.WriteLine("Actual  : " + result);
+        
+        string expected = "MyStruct`2[System.Exception,GenStruct`1[System.String]] = 456";
+        return result == expected ? 100 : -1;
+    }
+}
diff --git a/src/coreclr/tests/src/GC/Regressions/Github/runtime_32848/runtime_32848.csproj b/src/coreclr/tests/src/GC/Regressions/Github/runtime_32848/runtime_32848.csproj
new file mode 100644 (file)
index 0000000..5977363
--- /dev/null
@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <CLRTestKind>BuildAndRun</CLRTestKind>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+  
+  <PropertyGroup>
+    <CLRTestBatchPreCommands><![CDATA[
+$(CLRTestBatchPreCommands)
+set COMPlus_gcServer=1
+set COMPlus_gcStress=7
+]]></CLRTestBatchPreCommands>
+    <BashCLRTestPreCommands><![CDATA[
+$(BashCLRTestPreCommands)
+export COMPlus_gcServer=1
+export COMPlus_gcStress=7
+]]></BashCLRTestPreCommands>
+  </PropertyGroup>
+
+</Project>