1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-08 03:27:04 +09:00

[release/9.0] Fix a case in MethodImpl overriding which wasn't handled as expected in ilc.exe for native aot (#107409)

* Fix a case in MethodImpl overriding which wasn't handled as expected in ilc.exe for native aot - This was causing real C# applications to fail to behave correctly on NativeAOT builds - Enable testing for covariant byref returns on nativeaot (split testing up so that the tests do not expect TypeLoadException, which NativeAOT doesn't reliably generate) - Fix implementation of SynthesizedPgoIncompatible project file flag for test script generation - Put copy of attributetesting.il test into the managed type system unit test suite - Add regression test of issue noted in #96175 into managed type system unit test suite - Update workflow documentation to include a better path to finding details on how to run CoreCLR and Libraries tests for Native AOT

Fixes #96175

* Fix test with incorrect IL

* Make the remaining TODO comments follow existing practice in this file for todo comments

* Fix test exclusion for mono llvmaot

* Address nits from code review

---------

Co-authored-by: David Wrighton <davidwr@microsoft.com>
Co-authored-by: Jeff Schwartz <jeffschw@microsoft.com>
This commit is contained in:
github-actions[bot] 2024-09-05 14:37:15 -07:00 committed by GitHub
parent ee46f01b97
commit 24889f9145
Signed by: github
GPG key ID: B5690EEEBB952194
19 changed files with 3923 additions and 649 deletions

View file

@ -78,12 +78,14 @@ Now you know about configurations and how we use them, so now you will want to r
* [Building CoreCLR runtime](/docs/workflow/building/coreclr/README.md)
* [Building Mono runtime](/docs/workflow/building/mono/README.md)
* [Building NativeAOT runtime](/docs/workflow/building/coreclr/nativeaot.md)
* [Building Libraries](/docs/workflow/building/libraries/README.md)
After that, here's information about how to run tests:
* [Testing CoreCLR runtime](/docs/workflow/testing/coreclr/testing.md)
* [Testing Mono runtime](/docs/workflow/testing/mono/testing.md)
* [Testing NativeAOT runtime](/docs/workflow/building/coreclr/nativeaot.md#running-tests)
* [Testing Libraries](/docs/workflow/testing/libraries/testing.md)
And how to measure performance:

View file

@ -87,6 +87,8 @@ If you haven't built the tests yet, run `src\tests\build.cmd nativeaot [Debug|Re
To run all the tests that got built, run `src\tests\run.cmd runnativeaottests [Debug|Release]` on Windows, or `src/tests/run.sh --runnativeaottests [Debug|Release]` on Linux. The `Debug`/`Release` flag should match the flag that was passed to `build.cmd` in the previous step.
To build an individual test, follow the instructions for compiling a individual test project located in [Building an Individual Test](/docs/workflow/testing/coreclr/testing.md#building-an-individual-test), but add `/t:BuildNativeAot /p:TestBuildMode=nativeaot` to the build command.
To run an individual test (after it was built), navigate to the `artifacts\tests\coreclr\[windows|linux|osx[.x64.[Debug|Release]\$path_to_test` directory. `$path_to_test` matches the subtree of `src\tests`. You should see a `[.cmd|.sh]` file there. This file is a script that will compile and launch the individual test for you. Before invoking the script, set the following environment variables:
* CORE_ROOT=$repo_root\artifacts\tests\coreclr\[windows|linux|osx].x64.[Debug|Release]\Tests\Core_Root

View file

@ -461,7 +461,26 @@ namespace Internal.TypeSystem
// Unless the current type has a name/sig match for the group, look to the base type to define the unification group further
if ((nameSigMatchMethod == null) && (baseType != null))
{
// TODO! Consider if we should do this check even if the virtual name/sig match finds something.
// We may want to build up a unification group for the base just to check the further MethodImpl case here.
FindBaseUnificationGroup(baseType, unificationGroup);
// We should check to see if a the DefiningMethod on the base unification group is overriden via MethodImpl
// TODO! check to see if we need to check for MethodImpls affecting other members of the unification group
// other than the defining method
if (unificationGroup.DefiningMethod != null)
{
methodImpl = FindImplFromDeclFromMethodImpls(currentType, unificationGroup.DefiningMethod);
if (methodImpl != null)
{
if (methodImpl.RequiresSlotUnification())
{
unificationGroup.AddMethodRequiringSlotUnification(unificationGroup.DefiningMethod);
unificationGroup.AddMethodRequiringSlotUnification(methodImpl);
}
unificationGroup.SetDefiningMethod(methodImpl);
}
}
}
Debug.Assert(unificationGroup.IsInGroupOrIsDefiningSlot(originalDefiningMethod));

View file

@ -247,11 +247,17 @@ namespace System.Runtime.CompilerServices
public const string ByRefLikeGenerics = nameof(ByRefLikeGenerics);
public const string UnmanagedSignatureCallingConvention = nameof(UnmanagedSignatureCallingConvention);
public const string VirtualStaticsInInterfaces = nameof(VirtualStaticsInInterfaces);
public const string CovariantReturnsOfClasses = "CovariantReturnsOfClasses";
}
internal sealed class IntrinsicAttribute : Attribute
{
}
public sealed partial class PreserveBaseOverridesAttribute : System.Attribute
{
public PreserveBaseOverridesAttribute() { }
}
}
namespace System.Runtime.Intrinsics

View file

@ -60,4 +60,44 @@ namespace VirtualFunctionOverride
public override Type Method(delegate* unmanaged[Stdcall, SuppressGCTransition]<void> p) => null;
public override Type Method(delegate*<void> p) => null;
}
class BaseCovariant
{
public virtual BaseCovariant FromType()
{
return new BaseCovariant();
}
}
class ImplCovariant : BaseCovariant
{
public override ImplCovariant FromType()
{
return new ImplCovariant();
}
}
class SubImplCovariant : ImplCovariant
{
public override SubImplCovariant FromType()
{
return new SubImplCovariant();
}
}
class SubImplCovariant2 : ImplCovariant
{
public override ImplCovariant FromType()
{
return new ImplCovariant();
}
}
class SubSubImplCovariant : SubImplCovariant2
{
public override SubSubImplCovariant FromType()
{
return new SubSubImplCovariant();
}
}
}

View file

@ -19,6 +19,7 @@
<Compile Include="Signature.il" />
<Compile Include="MethodImplOverride1.il" />
<Compile Include="MDArrayFunctionResolution.il" />
<Compile Include="PreserveBaseOverridesAttibuteTesting.il" />
</ItemGroup>
</Project>

View file

@ -3,10 +3,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Internal.IL;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using Xunit;
using Xunit.Abstractions;
namespace TypeSystemTests
@ -17,9 +21,11 @@ namespace TypeSystemTests
private ModuleDesc _testModule;
private DefType _stringType;
private DefType _voidType;
private ITestOutputHelper _logger;
public VirtualFunctionOverrideTests()
public VirtualFunctionOverrideTests(ITestOutputHelper logger)
{
_logger = logger;
_context = new TestTypeSystemContext(TargetArchitecture.X64);
var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly");
_context.SetSystemModule(systemModule);
@ -289,5 +295,179 @@ namespace TypeSystemTests
Assert.Equal(expectedMethods[0].Signature[0], expectedMethods[1].Signature[0]);
Assert.NotEqual(expectedMethods[0].Signature[0], expectedMethods[3].Signature[0]);
}
[Theory]
// ScenarioA_Test1
[InlineData("ScenarioA_Test1_1", "T3", "A.T3_1", "A.T1", "Func1")]
[InlineData("ScenarioA_Test1_2", "T2", "A.T3_1", "A.T2Exp", "Func2")]
[InlineData("ScenarioA_Test1_3", "T3", "A.T3_1", "A.T3_1", "Func3")]
// ScenarioA_Test2
[InlineData("ScenarioA_Test2_1", "T3", "A.T3_2", "A.T1", "Func1")]
[InlineData("ScenarioA_Test2_2", "T3", "A.T3_2", "A.T2Exp", "Func2")]
[InlineData("ScenarioA_Test2_3", "T3", "A.T3_2", "A.T3_2", "Func3")]
// ScenarioA_Test3
[InlineData("ScenarioA_Test3_1", "T3", "A.T3_3", "A.T1", "Func1")]
[InlineData("ScenarioA_Test3_2", "T2", "A.T3_3", "A.T2Exp", "Func2")]
[InlineData("ScenarioA_Test3_3", "T3", "A.T3_3", "A.T3_3", "Func1")]
// ScenarioA_Test4
[InlineData("ScenarioA_Test4_1", "T3", "A.T3_4", "A.T1", "Func1")]
[InlineData("ScenarioA_Test4_2", "T3", "A.T3_4", "A.T2Exp", "Func2")]
[InlineData("ScenarioA_Test4_3", "T3", "A.T3_4", "A.T3_4", "Func2")]
// ScenarioA_Test5
[InlineData("ScenarioA_Test5_1", "T3", "A.T3_5", "A.T1", "Func1")]
[InlineData("ScenarioA_Test5_2", "T3", "A.T3_5", "A.T2Imp", "Func1")]
[InlineData("ScenarioA_Test5_3", "T3", "A.T3_5", "A.T3_5", "Func3")]
// ScenarioA_Test6
[InlineData("ScenarioA_Test6_1", "T3", "A.T3_6", "A.T1", "Func1")]
[InlineData("ScenarioA_Test6_2", "T3", "A.T3_6", "A.T2Imp", "Func1")]
[InlineData("ScenarioA_Test6_3", "T3", "A.T3_6", "A.T3_6", "Func3")]
// ScenarioA_Test7
[InlineData("ScenarioA_Test7_1", "T3", "A.T3_7", "A.T1", "Func1")]
[InlineData("ScenarioA_Test7_2", "T3", "A.T3_7", "A.T2Imp", "Func1")]
[InlineData("ScenarioA_Test7_3", "T3", "A.T3_7", "A.T3_7", "Func1")]
// ScenarioB_Test1
[InlineData("ScenarioB_Test_1_1", "T3", "B.T3_1", "B.T1", "Func1")]
[InlineData("ScenarioB_Test_1_2", "T2", "B.T3_1", "B.T2", "Func2")]
[InlineData("ScenarioB_Test_1_3", "T3", "B.T3_1", "B.T3_1", "Func3")] // Change from IL
// ScenarioB_Test2
[InlineData("ScenarioB_Test_2_1", "T3", "B.T3_2", "B.T1", "Func1")]
[InlineData("ScenarioB_Test_2_2", "T3", "B.T3_2", "B.T2", "Func2")]
[InlineData("ScenarioB_Test_2_3", "T3", "B.T3_2", "B.T3_2", "Func3")] // Change from IL
// ScenarioB_Test3
[InlineData("ScenarioB_Test_3_1", "T3", "B.T3_3", "B.T1", "Func1")]
[InlineData("ScenarioB_Test_3_2", "T2", "B.T3_3", "B.T2", "Func2")]
[InlineData("ScenarioB_Test_3_3", "T3", "B.T3_3", "B.T3_3", "Func1")]
// ScenarioB_Test4
[InlineData("ScenarioB_Test_4_1", "T3", "B.T3_4", "B.T1", "Func1")]
[InlineData("ScenarioB_Test_4_2", "T3", "B.T3_4", "B.T2", "Func2")]
[InlineData("ScenarioB_Test_4_3", "T3", "B.T3_4", "B.T3_4", "Func2")] // Change from IL
// ScenarioC_Test1
[InlineData("ScenarioC_Test_1_1", "T3", "C.T3_1", "C.T1", "Func1")]
[InlineData("ScenarioC_Test_1_2", "T3", "C.T3_1", "C.T2", "Func2")]
[InlineData("ScenarioC_Test_1_3", "T3", "C.T3_1", "C.T3_1", "Func3")]
// ScenarioC_Test2
[InlineData("ScenarioC_Test_2_1", "T3", "C.T3_2", "C.T1", "Func1")]
[InlineData("ScenarioC_Test_2_2", "T3", "C.T3_2", "C.T2", "Func2")]
[InlineData("ScenarioC_Test_2_3", "T3", "C.T3_2", "C.T3_2", "Func3")] // Change from IL
// ScenarioC_Test3
[InlineData("ScenarioC_Test_3_1", "T3", "C.T3_3", "C.T1", "Func1")]
[InlineData("ScenarioC_Test_3_2", "T2", "C.T3_3", "C.T2", "Func2")]
[InlineData("ScenarioC_Test_3_3", "T3", "C.T3_3", "C.T3_3", "Func1")]
// ScenarioC_Test4
[InlineData("ScenarioC_Test_4_1", "T3", "C.T3_4", "C.T1", "Func1")]
[InlineData("ScenarioC_Test_4_2", "T3", "C.T3_4", "C.T2", "Func2")]
[InlineData("ScenarioC_Test_4_3", "T3", "C.T3_4", "C.T3_4", "Func2")] // Change from IL
[InlineData("ScenarioC_Test_4_4", "T3", "C.T3_4", "C.T3_4", "Func2")]
// ScenarioD_Test1
[InlineData("ScenarioD_Test_1_1", "T3", "D.T3_1", "D.T1", "Func1")]
[InlineData("ScenarioD_Test_1_2", "T3", "D.T3_1", "D.T2", "Func1")]
[InlineData("ScenarioD_Test_1_3", "T3", "D.T3_1", "D.T3_1", "Func3")] // Change from IL
[InlineData("ScenarioD_Test_1_4", "T3", "D.T3_1", "D.T3_1", "Func3")]
// ScenarioD_Test2
[InlineData("ScenarioD_Test_2_1", "T3", "D.T3_2", "D.T1", "Func1")]
[InlineData("ScenarioD_Test_2_2", "T3", "D.T3_2", "D.T2", "Func1")]
[InlineData("ScenarioD_Test_2_3", "T3", "D.T3_2", "D.T3_2", "Func3")] // Change from IL
// DUPLICATE?!?! [InlineData("T3", "D.T3_1", "D.T3_1", "Func3")]
// ScenarioD_Test3
[InlineData("ScenarioD_Test_3_1", "T3", "D.T3_3", "D.T1", "Func1")]
[InlineData("ScenarioD_Test_3_2", "T3", "D.T3_3", "D.T2", "Func1")]
[InlineData("ScenarioD_Test_3_3", "T3", "D.T3_3", "D.T3_3", "Func1")]
// ScenarioE_Test1
[InlineData("ScenarioE_Test_1_1", "T3", "E.T3_1", "E.T1", "Func1")]
[InlineData("ScenarioE_Test_1_2", "T3", "E.T3_1", "E.T2", "Func1")]
[InlineData("ScenarioE_Test_1_3", "T3", "E.T3_1", "E.T3_1", "Func3")]
// ScenarioE_Test2
[InlineData("ScenarioE_Test_2_1", "T3", "E.T3_2", "E.T1", "Func1")]
[InlineData("ScenarioE_Test_2_2", "T3", "E.T3_2", "E.T2", "Func1")]
[InlineData("ScenarioE_Test_2_3", "T3", "E.T3_2", "E.T3_2", "Func3")]
// DUPLICATE?!?!? [InlineData("T3", "E.T3_1", "E.T3_1", "Func3")]
// ScenarioE_Test3
[InlineData("ScenarioE_Test_3_1", "T3", "E.T3_3", "E.T1", "Func1")]
[InlineData("ScenarioE_Test_3_2", "T3", "E.T3_3", "E.T2", "Func1")]
[InlineData("ScenarioE_Test_3_3", "T3", "E.T3_3", "E.T3_3", "Func1")]
public void TestPreserveBaseOverridesBehavior(string exactScenarioName, string stringToExpect, string typeToConstruct, string typeOfMethodToCallOn, string methodName)
{
this._logger.WriteLine(exactScenarioName);
var ilModule = _context.GetModuleForSimpleName("ILTestAssembly");
(string typeToConstructNamespace, string typeToConstructTypeName) = SplitIntoNameAndNamespace(typeToConstruct);
var constructedType = ilModule.GetType(typeToConstructNamespace, typeToConstructTypeName);
(string typeToCallNamespace, string typeToCallTypeName) = SplitIntoNameAndNamespace(typeOfMethodToCallOn);
var typeToCall = ilModule.GetType(typeToCallNamespace, typeToCallTypeName);
MethodDesc callMethod = typeToCall.GetMethod(methodName, null);
Assert.NotNull(callMethod);
MethodDesc resolvedMethod = constructedType.FindVirtualFunctionTargetMethodOnObjectType(callMethod);
var methodIL = Internal.IL.EcmaMethodIL.Create((EcmaMethod)resolvedMethod);
ILReader reader = new ILReader(methodIL.GetILBytes());
Assert.Equal(ILOpcode.ldstr, reader.ReadILOpcode());
int userStringToken = reader.ReadILToken();
string stringLoadedAsFirstILOpcodeInResolvedMethod = (string)methodIL.GetObject(userStringToken);
Assert.Equal(stringToExpect, stringLoadedAsFirstILOpcodeInResolvedMethod);
}
[Theory]
[InlineData("Base", "BaseCovariant")]
[InlineData("Impl", "ImplCovariant")]
[InlineData("SubImpl", "SubImplCovariant")]
[InlineData("SubImpl_OverrideViaNameSig", "SubImplCovariant2")]
[InlineData("SubImpl_OverrideViaNameSig_OverridenViaMethodImpl", "SubSubImplCovariant")]
public void TestSubImplCovariant(string exactScenarioName, string typeToConstruct)
{
this._logger.WriteLine(exactScenarioName);
MetadataType derivedClass = _testModule.GetType("VirtualFunctionOverride", typeToConstruct);
MetadataType baseClass = derivedClass;
while (baseClass != baseClass.Context.GetWellKnownType(WellKnownType.Object))
{
this._logger.WriteLine("-----");
this._logger.WriteLine(baseClass.ToString());
MethodDesc callMethod = baseClass.GetMethod("FromType", null);
this._logger.WriteLine(callMethod.ToString());
Assert.NotNull(callMethod);
MethodDesc resolvedMethod = derivedClass.FindVirtualFunctionTargetMethodOnObjectType(callMethod);
this._logger.WriteLine(resolvedMethod.ToString());
Assert.Equal(typeToConstruct, ((EcmaType)((EcmaMethod)resolvedMethod).OwningType).Name);
baseClass = (MetadataType)baseClass.BaseType;
}
}
private static (string _namespace, string type) SplitIntoNameAndNamespace(string typeName)
{
int namespaceIndextypeName = typeName.LastIndexOf('.');
Assert.True(namespaceIndextypeName > 0);
string typeNameNamespace = typeName.Substring(0, namespaceIndextypeName);
string typeNameTypeName = typeName.Substring(namespaceIndextypeName + 1);
Assert.True(typeNameTypeName.Length > 0);
return (typeNameNamespace, typeNameTypeName);
}
}
}

View file

@ -438,55 +438,6 @@
}
}
// ========================================================================================
// FIFTH LAYER INVALID type: Used to verify we can't override the method using a compatible interface
// if it has been already overridden using a class that implements the interface (i.e. the new
// interface return type won't be compatible with the class return type on the previous override
// ========================================================================================
.class public auto ansi beforefieldinit Invalid1<Q,W> extends class GenMoreDerived<!Q,!W,!Q,!W>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class INonGenThroughGen4 NonGenThroughGenFunc(string& res)
{
.override method instance class IB class GenBaseType<!Q,!W>::NonGenThroughGenFunc(string& res)
ldnull
ret
}
}
// ========================================================================================
// FIFTH LAYER INVALID type: Used to verify we can't override the method using a less derived interface
// than one that has already been used in a previous override
// ========================================================================================
.class public auto ansi beforefieldinit Invalid2<Q,W> extends class GenTestType<!Q,!W,!Q,!W>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class INonGenThroughGen2<object,int32,string> NonGenThroughGenFunc(string& res)
{
.override method instance class IB class GenBaseType<!Q,!W>::NonGenThroughGenFunc(string& res)
ldnull
ret
}
}
.class public auto ansi beforefieldinit Invalid3<Q,W> extends class GenTestType<!Q,!W,!Q,!W>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class IVariant<class Derived2> MultiLevelGenericVariantFunc(string&)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IVariant<class Base<class Derived>> class GenBaseType<!Q,!W>::MultiLevelGenericVariantFunc(string&)
ldnull
ret
}
}
// ========================================================================================
.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object
@ -1110,30 +1061,6 @@
ret
}
// ===================================================================================== //
.method public static void RunTest_Invalid1() noinlining
{
newobj instance void class Invalid1<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunTest_Invalid2() noinlining
{
newobj instance void class Invalid2<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunTest_Invalid3() noinlining
{
newobj instance void class Invalid3<int32,object>::.ctor()
callvirt instance class IVariant<class Derived2> class Invalid3<int32,object>::MultiLevelGenericVariantFunc()
pop
ret
}
// ===================================================================================== //
.method public hidebysig static int32 Main() cil managed
@ -1262,68 +1189,12 @@
MOREDERIVED6:
call bool CMain::RunTest_MoreDerived6()
brtrue.s INVALID1
brtrue.s DONE
ldc.i4.0
stloc.0
// ===================================================================================== //
INVALID1:
.try
{
call void CMain::RunTest_Invalid1()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid1."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID2
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID2
}
INVALID2:
.try
{
call void CMain::RunTest_Invalid2()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid2."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID3
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID3
}
INVALID3:
.try
{
call void CMain::RunTest_Invalid3()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading DerivedClassFail1."
call void [System.Console]System.Console::WriteLine(string)
leave.s DONE
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s DONE
}
// ===================================================================================== //
DONE:
ldloc.0
brtrue.s PASS

View file

@ -0,0 +1,609 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
.assembly extern System.Console { }
.assembly extern xunit.core {}
.assembly extern System.Runtime { }
.assembly extern mscorlib { }
.assembly UnitTest_TypeLoadException { }
// ========================================================================================
// Types that will be used as return types on the various methods
// ========================================================================================
.class interface public auto ansi abstract IUnused1 { }
.class interface public auto ansi abstract IUnused2 { }
.class interface public auto ansi abstract IA implements IUnused1, IUnused2 { }
.class interface public auto ansi abstract IB implements IUnused1, IUnused2, IA { }
.class interface public auto ansi abstract IC implements IUnused1, IUnused2, IB { }
.class interface public auto ansi abstract IGenRetType<X,Y> { }
.class interface public auto ansi abstract IDictionary<KEY,VAL> { }
.class public auto ansi abstract CA {}
.class public auto ansi abstract CB extends CA {}
.class public auto ansi abstract CC extends CB {}
.class interface public auto ansi abstract ICovariant<+ T> { }
.class interface public auto ansi abstract IContravariant<- T> { }
.class interface public auto ansi abstract IGenDerive1<V1,V2> implements IUnused1, IUnused2, class IGenRetType<!V1,!V2> { }
.class interface public auto ansi abstract IGenDerive2<U1,U2,U3> implements IUnused1, IUnused2, class IGenDerive1<!U1, class IDictionary<!U3,!U2>> { }
.class interface public auto ansi abstract IGenDerive3<T1,T2> implements IUnused1, IUnused2, class IGenDerive2<!T1,!T2,string> { }
.class interface public auto ansi abstract INonGenericDerived1<ARG1,ARG2> implements IUnused1, IUnused2, class IGenRetType<!ARG1,!ARG2> { }
.class interface public auto ansi abstract INonGenericDerived2<T> implements IUnused1, IUnused2, class INonGenericDerived1<!T,object> { }
.class interface public auto ansi abstract INonGenericDerived3 implements IUnused1, IUnused2, class INonGenericDerived2<int32> { }
.class interface public auto ansi abstract INonGenericDerived4 implements IUnused1, IUnused2, INonGenericDerived3 { }
.class interface public auto ansi abstract IGenToNonGen1<V1,V2> implements IUnused1, IUnused2, IC { }
.class interface public auto ansi abstract IGenToNonGen2<U1,U2,U3> implements IUnused1, IUnused2, class IGenToNonGen1<!U1, class IDictionary<!U3,!U2>> { }
.class interface public auto ansi abstract IGenToNonGen3<T1,T2> implements IUnused1, IUnused2, class IGenToNonGen2<!T1,!T2,string> { }
.class interface public auto ansi abstract INonGenThroughGen1<V1,V2> implements IUnused1, IUnused2, IC { }
.class interface public auto ansi abstract INonGenThroughGen2<U1,U2,U3> implements IUnused1, IUnused2, class INonGenThroughGen1<!U1, class IDictionary<!U3,!U2>> { }
.class interface public auto ansi abstract INonGenThroughGen3 implements IUnused1, IUnused2, class INonGenThroughGen2<object,int32,string> { }
.class interface public auto ansi abstract INonGenThroughGen4 implements IUnused1, IUnused2, INonGenThroughGen3 { }
// class implementing the interfaces
.class public auto ansi beforefieldinit NonGenThroughGen4 implements IUnused1, IUnused2, INonGenThroughGen4 { }
.class public auto ansi beforefieldinit GenToNonGen3<T1,T2> implements IUnused1, IUnused2, class IGenToNonGen3<!T1,!T2> { }
.class public auto ansi beforefieldinit NonGenericDerived4 implements IUnused1, IUnused2, INonGenericDerived4 { }
.class public auto ansi beforefieldinit GenDerive3<T1,T2> implements IUnused1, IUnused2, class IGenDerive3<!T1,!T2> { }
.class public auto ansi beforefieldinit C implements IUnused1, IUnused2, IC { }
.class public auto ansi beforefieldinit GenRetType<X,Y> implements IUnused1, IUnused2, class IGenRetType<!X,!Y> { }
.class public auto ansi beforefieldinit Base<T> {}
.class public auto ansi beforefieldinit Derived extends class Base<class Derived> {}
.class public auto ansi beforefieldinit Derived2 extends class Base<class Derived2> {}
.class interface public auto ansi abstract IVariant<+ V>
{
.method public hidebysig newslot virtual instance void Test()
{
ret
}
}
// ========================================================================================
// Main base type with various virtual methods that will be overridden later
// ========================================================================================
.class public auto ansi beforefieldinit GenBaseType<A,B>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance object MyFunc(string& res)
{
ldarg.1
ldstr "object GenBaseType.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IB MyFunc(string& res)
{
ldarg.1
ldstr "IB GenBaseType.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class ICovariant<class CB> MyFuncCovariant(string& res)
{
ldarg.1
ldstr "ICovariant<CB> GenBaseType.MyFuncCovariant()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IContravariant<class CB> MyFuncContravariant(string& res)
{
ldarg.1
ldstr "IContravariant<CB> GenBaseType.MyFuncContravariant()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IB GenToNonGen(string& res)
{
ldarg.1
ldstr "IB GenBaseType.GenToNonGen()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IB NonGenThroughGenFunc(string& res)
{
ldarg.1
ldstr "IB GenBaseType.NonGenThroughGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenRetType<int32,object> MyGenFunc(string& res)
{
ldarg.1
ldstr "IGenRetType<int32,object> GenBaseType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenRetType<!A, class IDictionary<string,!B>> MyGenFunc(string& res)
{
ldarg.1
ldstr "IGenRetType<!A, class IDictionary<string,!B>> GenBaseType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IVariant<class Base<class Derived>> MultiLevelGenericVariantFunc(string&)
{
ldarg.1
ldstr "IVariant<class Base<class Derived>> GenBaseType.MultiLevelGenericVariantFunc()"
stind.ref
ldnull
ret
}
}
// ========================================================================================
// SECOND LAYER type: overrides *SOME* virtuals on GenBaseType using MethodImpls with
// covariant return types (more derived return types)
// ========================================================================================
.class public auto ansi beforefieldinit GenMiddleType<U,V> extends class GenBaseType<!V,!U>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class INonGenThroughGen2<object,int32,string> NonGenThroughGenFunc(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IB class GenBaseType<!V,!U>::NonGenThroughGenFunc(string& res)
ldarg.1
ldstr "INonGenThroughGen2<object,int32,string> GenMiddleType.NonGenThroughGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenToNonGen1<!V, class IDictionary<string,object>> GenToNonGen(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IB class GenBaseType<!V,!U>::GenToNonGen(string& res)
ldarg.1
ldstr "IGenToNonGen1<!V, class IDictionary<string,object>> GenMiddleType.GenToNonGen()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class INonGenericDerived1<int32,object> MyGenFunc(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IGenRetType<int32,object> class GenBaseType<!V,!U>::MyGenFunc(string& res)
ldarg.1
ldstr "INonGenericDerived1<int32,object> GenMiddleType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenDerive1<!V, class IDictionary<string,!U>> MyGenFunc(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IGenRetType<!0, class IDictionary<string,!1>> class GenBaseType<!V,!U>::MyGenFunc(string& res)
ldarg.1
ldstr "IGenDerive1<!U, class IDictionary<string,!V>> GenMiddleType.MyGenFunc()"
stind.ref
ldnull
ret
}
}
// ========================================================================================
// THIRD LAYER type: overrides all virtuals from GenBaseType using MethodImpls with
// covariant return types (more derived return types than the ones used in GenMiddleType)
// ========================================================================================
.class public auto ansi beforefieldinit GenTestType<UNUSED1,UNUSED2,U,V> extends class GenMiddleType<!V,!U>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class INonGenThroughGen4 NonGenThroughGenFunc(string& res)
{
.override method instance class IB class GenBaseType<!U,!V>::NonGenThroughGenFunc(string& res)
ldarg.1
ldstr "INonGenThroughGen4 TestType.NonGenThroughGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenToNonGen3<!U,object> GenToNonGen(string& res)
{
.override method instance class IB class GenBaseType<!U,!V>::GenToNonGen(string& res)
ldarg.1
ldstr "IGenToNonGen3<!U,object> TestType.GenToNonGen()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class INonGenericDerived4 MyGenFunc(string& res)
{
.override method instance class IGenRetType<int32,object> class GenBaseType<!U,!V>::MyGenFunc(string& res)
ldarg.1
ldstr "INonGenericDerived4 TestType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenDerive3<!U,!V> MyGenFunc(string& res)
{
.override method instance class IGenRetType<!0, class IDictionary<string,!1>> class GenBaseType<!U,!V>::MyGenFunc(string& res)
ldarg.1
ldstr "IGenDerive3<!U,!V> TestType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IGenRetType<!U,!V> MyFunc(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance object class GenBaseType<!U,!V>::MyFunc(string& res)
ldarg.1
ldstr "IGenRetType<!U,!V> TestType.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IC MyFunc(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IB class GenBaseType<!U,!V>::MyFunc(string& res)
ldarg.1
ldstr "IC TestType.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class ICovariant<class CC> MyFuncCovariant(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class ICovariant<class CB> class GenBaseType<!U,!V>::MyFuncCovariant(string& res)
ldarg.1
ldstr "ICovariant<CC> TestType.MyFuncCovariant()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IContravariant<class CA> MyFuncContravariant(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IContravariant<class CB> class GenBaseType<!U,!V>::MyFuncContravariant(string& res)
ldarg.1
ldstr "IContravariant<CA> TestType.MyFuncContravariant()"
stind.ref
ldnull
ret
}
// ========================================================================================
// Set of implicit overrides that should be ignored given there are explicit overrides from the MethodImpls
// ========================================================================================
.method public hidebysig virtual instance class IB NonGenThroughGenFunc(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance class IB GenToNonGen(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance class IGenRetType<int32,object> MyGenFunc(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance class IGenRetType<!2, class IDictionary<string,!3>> MyGenFunc(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance object MyFunc(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance class IB MyFunc(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance class ICovariant<class CB> MyFuncCovariant(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
.method public hidebysig virtual instance class IContravariant<class CB> MyFuncContravariant(string& res)
{
ldstr "Should never execute this method"
newobj instance void [System.Runtime]System.Exception::.ctor(string)
throw
}
}
// ========================================================================================
// FOURTH LAYER type: overrides all virtuals from GenBaseType using MethodImpls with
// covariant return types (classes that implement the interfaces used as return types)
// ========================================================================================
.class public auto ansi beforefieldinit GenMoreDerived<UNUSED1,UNUSED2,U,V> extends class GenTestType<!UNUSED2,!UNUSED1,!U,!V>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenFunc(string& res)
{
.override method instance class IB class GenBaseType<!U,!V>::NonGenThroughGenFunc(string& res)
ldarg.1
ldstr "class NonGenThroughGen4 GenMoreDerived.NonGenThroughGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenToNonGen3<!U,object> GenToNonGen(string& res)
{
.override method instance class IB class GenBaseType<!U,!V>::GenToNonGen(string& res)
ldarg.1
ldstr "class GenToNonGen3<!U,object> GenMoreDerived.GenToNonGen()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class NonGenericDerived4 MyGenFunc(string& res)
{
.override method instance class IGenRetType<int32,object> class GenBaseType<!U,!V>::MyGenFunc(string& res)
ldarg.1
ldstr "class NonGenericDerived4 GenMoreDerived.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenDerive3<!U,!V> MyGenFunc(string& res)
{
.override method instance class IGenRetType<!0, class IDictionary<string,!1>> class GenBaseType<!U,!V>::MyGenFunc(string& res)
ldarg.1
ldstr "class GenDerive3<!U,!V> GenMoreDerived.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenRetType<!U,!V> MyFunc(string& res)
{
.override method instance object class GenBaseType<!U,!V>::MyFunc(string& res)
ldarg.1
ldstr "class GenRetType<!U,!V> GenMoreDerived.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class C MyFunc(string& res)
{
.override method instance class IB class GenBaseType<!U,!V>::MyFunc(string& res)
ldarg.1
ldstr "class C GenMoreDerived.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class IVariant<class Derived> MultiLevelGenericVariantFunc(string&)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IVariant<class Base<class Derived>> class GenBaseType<!U,!V>::MultiLevelGenericVariantFunc(string&)
ldarg.1
ldstr "class IVariant<class Derived> GenMoreDerived.MultiLevelGenericVariantFunc()"
stind.ref
ldnull
ret
}
}
// ========================================================================================
// FIFTH LAYER INVALID type: Used to verify we can't override the method using a compatible interface
// if it has been already overridden using a class that implements the interface (i.e. the new
// interface return type won't be compatible with the class return type on the previous override
// ========================================================================================
.class public auto ansi beforefieldinit Invalid1<Q,W> extends class GenMoreDerived<!Q,!W,!Q,!W>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class INonGenThroughGen4 NonGenThroughGenFunc(string& res)
{
.override method instance class IB class GenBaseType<!Q,!W>::NonGenThroughGenFunc(string& res)
ldnull
ret
}
}
// ========================================================================================
// FIFTH LAYER INVALID type: Used to verify we can't override the method using a less derived interface
// than one that has already been used in a previous override
// ========================================================================================
.class public auto ansi beforefieldinit Invalid2<Q,W> extends class GenTestType<!Q,!W,!Q,!W>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class INonGenThroughGen2<object,int32,string> NonGenThroughGenFunc(string& res)
{
.override method instance class IB class GenBaseType<!Q,!W>::NonGenThroughGenFunc(string& res)
ldnull
ret
}
}
.class public auto ansi beforefieldinit Invalid3<Q,W> extends class GenTestType<!Q,!W,!Q,!W>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class IVariant<class Derived2> MultiLevelGenericVariantFunc(string&)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class IVariant<class Base<class Derived>> class GenBaseType<!Q,!W>::MultiLevelGenericVariantFunc(string&)
ldnull
ret
}
}
// ===================================================================================== //
.method public static void RunTest_Invalid1() noinlining
{
newobj instance void class Invalid1<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunTest_Invalid2() noinlining
{
newobj instance void class Invalid2<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunTest_Invalid3() noinlining
{
newobj instance void class Invalid3<int32,object>::.ctor()
callvirt instance class IVariant<class Derived2> class Invalid3<int32,object>::MultiLevelGenericVariantFunc()
pop
ret
}
// ===================================================================================== //
.method public hidebysig static int32 Main() cil managed
{
.custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = (
01 00 00 00
)
.entrypoint
.maxstack 2
.locals init ( bool result )
ldc.i4.1
stloc.0
INVALID1:
.try
{
call void CMain::RunTest_Invalid1()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid1."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID2
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID2
}
INVALID2:
.try
{
call void CMain::RunTest_Invalid2()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid2."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID3
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID3
}
INVALID3:
.try
{
call void CMain::RunTest_Invalid3()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading DerivedClassFail1."
call void [System.Console]System.Console::WriteLine(string)
leave.s DONE
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s DONE
}
// ===================================================================================== //
DONE:
ldloc.0
brtrue.s PASS
ldstr "Test FAILED"
call void [System.Console]System.Console::WriteLine(string)
ldc.i4.s 101
ret
PASS:
ldstr "Test PASSED"
call void [System.Console]System.Console::WriteLine(string)
ldc.i4.s 100
ret
ldc.i4.s 100
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<!-- Needed for mechanical merging of all remaining tests, this particular project may not actually need process isolation -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
</PropertyGroup>
<ItemGroup>
<Compile Include="UnitTest.il" />
</ItemGroup>
</Project>

View file

@ -800,7 +800,7 @@
.try
{
call void Main::RunTestC1()
leave.s CC2
leave.s CC3
}
catch [mscorlib]System.TypeLoadException
{
@ -809,45 +809,9 @@
call void [System.Console]System.Console::WriteLine(object)
ldc.i4.0
stloc.0
leave.s CC2
leave.s CC3
}
CC2:
ldstr "C2: override int32[] by IList<int32>"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC2()
ldc.i4.0
stloc.0
leave.s CD2
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CD2
}
CD2:
ldstr "D2: call non-overriding method MD2 when base class of D2 has invalid covariant override"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestD2()
ldc.i4.0
stloc.0
leave.s CC3
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC3
}
CC3:
ldstr "C3: override IList<int32> by int32[]"
call void [System.Console]System.Console::WriteLine(string)
@ -855,7 +819,7 @@ CC3:
.try
{
call void Main::RunTestC3()
leave.s CC4
leave.s CC6
}
catch [mscorlib]System.TypeLoadException
{
@ -864,44 +828,6 @@ CC3:
call void [System.Console]System.Console::WriteLine(object)
ldc.i4.0
stloc.0
leave.s CC4
}
CC4:
ldstr "C4: override int32 by Nullable`1<int32>"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC4()
ldc.i4.0
stloc.0
leave.s CC5
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC5
}
CC5:
ldstr "C5: override Nullable<int32> by int32"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC5()
ldc.i4.0
stloc.0
leave.s CC6
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC6
}
CC6:
@ -947,7 +873,7 @@ CC8:
.try
{
call void Main::RunTestC8()
leave.s CC9
leave.s CC15
}
catch [mscorlib]System.TypeLoadException
{
@ -956,114 +882,6 @@ CC8:
call void [System.Console]System.Console::WriteLine(object)
ldc.i4.0
stloc.0
leave.s CC9
}
CC9:
ldstr "C9: override native int[] by uint64[]"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC9()
ldc.i4.0
stloc.0
leave.s CC10
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC10
}
CC10:
ldstr "C10: override native int[] by uint32[]"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC10()
ldc.i4.0
stloc.0
leave.s CC11
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC11
}
CC11:
ldstr "C11: override Base* by Derived*"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC11()
ldc.i4.0
stloc.0
leave.s CC12
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC12
}
CC12:
ldstr "C12: override void* by int32*"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC12()
ldc.i4.0
stloc.0
leave.s CC13
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC13
}
CC13:
ldstr "C13: override int32 *(class Base) by int32 *(class Derived)"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC13()
ldc.i4.0
stloc.0
leave.s CC14
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC14
}
CC14:
ldstr "C14: override int32 *(class Base) by int32 *(class C1)"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC14()
ldc.i4.0
stloc.0
leave.s CC15
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC15
}
CC15:
@ -1127,7 +945,7 @@ CC18:
.try
{
call void Main::RunTestC18()
leave.s CC19
leave.s CC20
}
catch [mscorlib]System.TypeLoadException
{
@ -1136,24 +954,6 @@ CC18:
call void [System.Console]System.Console::WriteLine(object)
ldc.i4.0
stloc.0
leave.s CC19
}
CC19:
ldstr "C19: override Base& M13() by Derived& M13()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC19()
ldc.i4.0
stloc.0
leave.s CC20
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC20
}
CC20:
@ -1181,7 +981,7 @@ CC21:
.try
{
call void Main::RunTestC21()
leave.s CC22
leave.s DONE
}
catch [mscorlib]System.TypeLoadException
{
@ -1190,150 +990,6 @@ CC21:
call void [System.Console]System.Console::WriteLine(object)
ldc.i4.0
stloc.0
leave.s CC22
}
CC22:
ldstr "C22: override char& M14() by uint8& M14()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC22()
ldc.i4.0
stloc.0
leave.s CC23
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC23
}
CC23:
ldstr "C23: override bool* M15() by uint32* M15()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC23()
ldc.i4.0
stloc.0
leave.s CC24
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC24
}
CC24:
ldstr "C24: override bool* M15() by bool& M15()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC24()
ldc.i4.0
stloc.0
leave.s CC25
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC25
}
CC25:
ldstr "C25: override bool* M15() by int32 *(class Base) M15()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC25()
ldc.i4.0
stloc.0
leave.s CC26
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC26
}
CC26:
ldstr "C26: override char& M14() by char* M14()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC26()
ldc.i4.0
stloc.0
leave.s CC27
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC27
}
CC27:
ldstr "C27: override char& M14() by int32 *(class Base) M14()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC27()
ldc.i4.0
stloc.0
leave.s CC28
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC28
}
CC28:
ldstr "C28: override int32 *(class Base) M9() by int32* M9()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC28()
ldc.i4.0
stloc.0
leave.s CC29
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s CC29
}
CC29:
ldstr "C29: override int32 *(class Base) M9() by int32& M9()"
call void [System.Console]System.Console::WriteLine(string)
.try
{
call void Main::RunTestC29()
ldc.i4.0
stloc.0
leave.s DONE
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s DONE
}
DONE:

View file

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<!-- Needed for SynthesizedPgoIncompatible -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<!-- Synthesized PGO may cause the expected TypeLoadExceptions in this test to appear at unexpected places -->
<SynthesizedPgoIncompatible>true</SynthesizedPgoIncompatible>
</PropertyGroup>
<ItemGroup>
<Compile Include="CompatibleWithTest_TypeLoadException.il" />
</ItemGroup>
</Project>

View file

@ -507,7 +507,7 @@
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
ldloca.s 1
callvirt instance class GenDerive3<!0,!1> class GenTestType<object,int32>::MyGenFunc(string&)
callvirt instance class GenDerive3<!0,!1> class GenTestType<int32,object>::MyGenFunc(string&)
pop
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
@ -535,7 +535,7 @@
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
ldloca.s 1
callvirt instance class NonGenericDerived4 class GenTestType<object,int32>::MyGenFunc(string&)
callvirt instance class NonGenericDerived4 class GenTestType<int32,object>::MyGenFunc(string&)
pop
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
@ -563,7 +563,7 @@
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
ldloca.s 1
callvirt instance class GenToNonGen3<!1,object> class GenTestType<object,int32>::GenToNonGen(string&)
callvirt instance class GenToNonGen3<!1,object> class GenTestType<int32,object>::GenToNonGen(string&)
pop
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
@ -591,7 +591,7 @@
newobj instance void class GenDerivedTestType<int32,object>::.ctor()
ldloca.s 1
callvirt instance class NonGenThroughGen4 class GenTestType<object,int32>::NonGenThroughGenFunc(string&)
callvirt instance class NonGenThroughGen4 class GenTestType<int32,object>::NonGenThroughGenFunc(string&)
pop
newobj instance void class GenDerivedTestType<int32,object>::.ctor()

View file

@ -288,57 +288,6 @@
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
// ========================================================================================
// THIRD LAYER INVALID types: Couple of types that override some method from GenBaseType
// using a return type signature that would be incompatible with the return type used in
// GenMiddle. Loading these types will throw a TypeLoadException.
// ========================================================================================
.class public auto ansi beforefieldinit Invalid1<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid: when comparing 'object' with !!Y in the instantiation of NonGenericDerived1 in the base type chain
.method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenOverride<Y>(string& res)
{
.override method instance class B class GenBaseType<!U,!V>::NonGenThroughGenFunc<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Invalid2<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid: when comparing 'object' with !!Y in the instantiation
.method public hidebysig newslot virtual instance class GenToNonGen3<!V,object> GenToNonGenOverride<Y>(string& res)
{
.override method instance class B class GenBaseType<!U,!V>::GenToNonGen<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Invalid3<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid when comparing !!Y and 'object' in instantiation of GenRetType
.method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1<Y>(string& res)
{
.override method instance class GenRetType<int32,!!0> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Invalid4<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid when comparing !!Y and 'string' in instantiation of Dictionary
.method public hidebysig newslot virtual instance class GenDerive3<!U,!V> NewGenFunc2<Y>(string& res)
{
.override method instance class GenRetType<!0, class Dictionary<!!0,!1>> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
// ========================================================================================
.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object
@ -700,38 +649,6 @@
ret
}
// ============== Test using GenMiddleType ============== //
// These test methods attempt to load the invalid types, and are
// expected to throw a TypeLoadException (caught by Main())
.method public static void RunInvalidTest1() noinlining
{
newobj instance void class Invalid1<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunInvalidTest2() noinlining
{
newobj instance void class Invalid2<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunInvalidTest3() noinlining
{
newobj instance void class Invalid3<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunInvalidTest4() noinlining
{
newobj instance void class Invalid4<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
// ===================================================================================== //
.method public hidebysig static int32 Main() cil managed
{
@ -801,82 +718,10 @@
M4:
call bool CMain::RunTest_Middle4()
brtrue.s INVALID1
brtrue.s DONE
ldc.i4.0
stloc.0
INVALID1:
.try
{
call void CMain::RunInvalidTest1()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid1."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID2
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID2
}
INVALID2:
.try
{
call void CMain::RunInvalidTest2()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid2."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID3
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID3
}
INVALID3:
.try
{
call void CMain::RunInvalidTest3()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid3."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID4
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID4
}
INVALID4:
.try
{
call void CMain::RunInvalidTest4()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid4."
call void [System.Console]System.Console::WriteLine(string)
leave.s DONE
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s DONE
}
DONE:
ldloc.0
brtrue.s PASS

View file

@ -0,0 +1,583 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
.assembly extern System.Console { }
.assembly extern xunit.core {}
.assembly extern System.Runtime { }
.assembly extern mscorlib { }
.assembly UnitTest_GVM_TypeLoadException { }
// ========================================================================================
// Types that will be used as return types on the various methods
// ========================================================================================
.class public auto ansi beforefieldinit A
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit B extends A
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit C extends B
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenRetType<X,Y>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Dictionary<KEY,VAL>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenDerive1<V1,V2> extends class GenRetType<!V1,!V2>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenDerive2<U1,U2,U3> extends class GenDerive1<!U1, class Dictionary<!U3,!U2>>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenDerive3<T1,T2> extends class GenDerive2<!T1,!T2,string>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenericDerived1<ARG1,ARG2> extends class GenRetType<!ARG1,!ARG2>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenericDerived2<T> extends class NonGenericDerived1<!T,object>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2<int32>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenericDerived5<T> extends class NonGenericDerived1<int32,!T>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenToNonGen1<V1,V2> extends C
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenToNonGen2<U1,U2,U3> extends class GenToNonGen1<!U1, class Dictionary<!U3,!U2>>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit GenToNonGen3<T1,T2> extends class GenToNonGen2<!T1,!T2,string>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenThroughGen1<V1,V2> extends C
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenThroughGen2<U1,U2,U3> extends class NonGenThroughGen1<!U1, class Dictionary<!U3,!U2>>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2<object,int32,string>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit NonGenThroughGen5<T> extends class NonGenThroughGen2<object,int32,!T>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
// ========================================================================================
// Main base type with various virtual methods that will be overridden later
// ========================================================================================
.class public auto ansi beforefieldinit GenBaseType<A,B>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance object MyFunc<Z>(string& res)
{
ldarg.1
ldstr "object GenBaseType.MyFunc()"
stind.ref
newobj instance void A::.ctor()
ret
}
.method public hidebysig newslot virtual instance class B MyFunc<Z>(string& res)
{
ldarg.1
ldstr "B GenBaseType.MyFunc()"
stind.ref
newobj instance void B::.ctor()
ret
}
.method public hidebysig newslot virtual instance class B GenToNonGen<Z>(string& res)
{
ldarg.1
ldstr "B GenBaseType.GenToNonGen()"
stind.ref
newobj instance void B::.ctor()
ret
}
.method public hidebysig newslot virtual instance class B NonGenThroughGenFunc<Z>(string& res)
{
ldarg.1
ldstr "B GenBaseType.NonGenThroughGenFunc()"
stind.ref
newobj instance void B::.ctor()
ret
}
.method public hidebysig newslot virtual instance class GenRetType<int32,!!Z> MyGenFunc<Z>(string& res)
{
ldarg.1
ldstr "GenRetType<int32,!!Y> GenBaseType.MyGenFunc()"
stind.ref
newobj instance void class GenRetType<int32,!!Z>::.ctor()
ret
}
.method public hidebysig newslot virtual instance class GenRetType<!A, class Dictionary<!!Z,!B>> MyGenFunc<Z>(string& res)
{
ldarg.1
ldstr "GenRetType<!A, class Dictionary<!!Y,!B>> GenBaseType.MyGenFunc()"
stind.ref
newobj instance void class GenRetType<!A, class Dictionary<!!Z,!B>>::.ctor()
ret
}
}
// ========================================================================================
// SECOND LAYER type: overrides *SOME* virtuals on GenBaseType using MethodImpls with
// covariant return types (more derived return types)
// ========================================================================================
.class public auto ansi beforefieldinit GenMiddleType<U,V> extends class GenBaseType<!U,!V>
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
.method public hidebysig newslot virtual instance class NonGenThroughGen2<object,int32,!!Y> NonGenThroughGenFunc<Y>(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class B class GenBaseType<!U,!V>::NonGenThroughGenFunc<[1]>(string& res)
ldarg.1
ldstr "NonGenThroughGen2<object,int32,!!Y> GenMiddleType.NonGenThroughGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenToNonGen1<!V, class Dictionary<string,!!Y>> GenToNonGen<Y>(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class B class GenBaseType<!U,!V>::GenToNonGen<[1]>(string& res)
ldarg.1
ldstr "GenToNonGen1<!V, class Dictionary<string,!!Y>> GenMiddleType.GenToNonGen()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class NonGenericDerived1<int32,!!Y> MyGenFunc<Y>(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class GenRetType<int32,!!0> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldarg.1
ldstr "NonGenericDerived1<int32,!!Y> GenMiddleType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenDerive1<!U, class Dictionary<!!Y,!V>> MyGenFunc<Y>(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class GenRetType<!0, class Dictionary<!!0,!1>> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldarg.1
ldstr "GenDerive1<!U, class Dictionary<!!Y,!V>> GenMiddleType.MyGenFunc()"
stind.ref
ldnull
ret
}
}
// ========================================================================================
// THIRD LAYER type: overrides all virtuals from GenBaseType using MethodImpls with
// covariant return types (more derived return types than the ones used in GenMiddleType)
// ========================================================================================
.class public auto ansi beforefieldinit GenTestType<U,V> extends class GenMiddleType<!U,!V>
{
.method public hidebysig newslot virtual instance class NonGenThroughGen5<!!Y> NonGenThroughGenFunc<Y>(string& res)
{
.override method instance class B class GenBaseType<!U,!V>::NonGenThroughGenFunc<[1]>(string& res)
ldarg.1
ldstr "NonGenThroughGen5<!!Y> TestType.NonGenThroughGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenToNonGen3<!V,!!Y> GenToNonGen<Y>(string& res)
{
.override method instance class B class GenBaseType<!U,!V>::GenToNonGen<[1]>(string& res)
ldarg.1
ldstr "GenToNonGen3<!V,!!Y> TestType.GenToNonGen()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class NonGenericDerived5<!!Y> MyGenFunc<Y>(string& res)
{
.override method instance class GenRetType<int32,!!0> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldarg.1
ldstr "NonGenericDerived5<!!Y> TestType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenDerive2<!U,!V,!!Y> MyGenFunc<Y>(string& res)
{
.override method instance class GenRetType<!0, class Dictionary<!!0,!1>> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldarg.1
ldstr "GenDerive2<!U,!V,!!Y> TestType.MyGenFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class GenRetType<!U,!V> MyFunc<Y>(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance object class GenBaseType<!U,!V>::MyFunc<[1]>(string& res)
ldarg.1
ldstr "GenRetType<!U,!V> TestType.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig newslot virtual instance class C MyFunc<Y>(string& res)
{
.custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00)
.override method instance class B class GenBaseType<!U,!V>::MyFunc<[1]>(string& res)
ldarg.1
ldstr "C TestType.MyFunc()"
stind.ref
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
// ========================================================================================
// THIRD LAYER INVALID types: Couple of types that override some method from GenBaseType
// using a return type signature that would be incompatible with the return type used in
// GenMiddle. Loading these types will throw a TypeLoadException.
// ========================================================================================
.class public auto ansi beforefieldinit Invalid1<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid: when comparing 'object' with !!Y in the instantiation of NonGenericDerived1 in the base type chain
.method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenOverride<Y>(string& res)
{
.override method instance class B class GenBaseType<!U,!V>::NonGenThroughGenFunc<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Invalid2<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid: when comparing 'object' with !!Y in the instantiation
.method public hidebysig newslot virtual instance class GenToNonGen3<!V,object> GenToNonGenOverride<Y>(string& res)
{
.override method instance class B class GenBaseType<!U,!V>::GenToNonGen<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Invalid3<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid when comparing !!Y and 'object' in instantiation of GenRetType
.method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1<Y>(string& res)
{
.override method instance class GenRetType<int32,!!0> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
.class public auto ansi beforefieldinit Invalid4<U,V> extends class GenMiddleType<!U,!V>
{
// Invalid when comparing !!Y and 'string' in instantiation of Dictionary
.method public hidebysig newslot virtual instance class GenDerive3<!U,!V> NewGenFunc2<Y>(string& res)
{
.override method instance class GenRetType<!0, class Dictionary<!!0,!1>> class GenBaseType<!U,!V>::MyGenFunc<[1]>(string& res)
ldnull
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret }
}
// ========================================================================================
.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object
{
.method private hidebysig static bool CheckResults (
string expected,
string a,
[opt] string b,
[opt] string c,
[opt] string d) cil managed
{
.param [3] = nullref
.param [4] = nullref
.param [5] = nullref
// Method begins at RVA 0x20a0
// Code size 164 (0xa4)
.maxstack 2
.locals /* 11000002 */ init (
[0] bool
)
IL_0000: ldarg.1
IL_0001: ldarg.0
IL_0002: call bool [System.Runtime]System.String::op_Equality(string, string) /* 0A000012 */
IL_0007: stloc.0
IL_0008: ldstr "EXPECTED: " /* 70000001 */
IL_000d: ldarg.0
IL_000e: call string [System.Runtime]System.String::Concat(string, string) /* 0A000013 */
IL_0013: call void [System.Console]System.Console::WriteLine(string) /* 0A000014 */
IL_0018: ldstr "ACTUAL1 : " /* 70000017 */
IL_001d: ldarg.1
IL_001e: call string [System.Runtime]System.String::Concat(string, string) /* 0A000013 */
IL_0023: call void [System.Console]System.Console::WriteLine(string) /* 0A000014 */
IL_0028: ldarg.2
IL_0029: call bool [System.Runtime]System.String::IsNullOrEmpty(string) /* 0A000015 */
IL_002e: brtrue.s IL_004e
IL_0030: ldstr "ACTUAL2 : " /* 7000002D */
IL_0035: ldarg.2
IL_0036: call string [System.Runtime]System.String::Concat(string, string) /* 0A000013 */
IL_003b: call void [System.Console]System.Console::WriteLine(string) /* 0A000014 */
IL_0040: ldloc.0
IL_0041: brfalse.s IL_004c
IL_0043: ldarg.2
IL_0044: ldarg.0
IL_0045: call bool [System.Runtime]System.String::op_Equality(string, string) /* 0A000012 */
IL_004a: br.s IL_004d
IL_004c: ldc.i4.0
IL_004d: stloc.0
IL_004e: ldarg.3
IL_004f: call bool [System.Runtime]System.String::IsNullOrEmpty(string) /* 0A000015 */
IL_0054: brtrue.s IL_0074
IL_0056: ldstr "ACTUAL3 : " /* 70000043 */
IL_005b: ldarg.3
IL_005c: call string [System.Runtime]System.String::Concat(string, string) /* 0A000013 */
IL_0061: call void [System.Console]System.Console::WriteLine(string) /* 0A000014 */
IL_0066: ldloc.0
IL_0067: brfalse.s IL_0072
IL_0069: ldarg.3
IL_006a: ldarg.0
IL_006b: call bool [System.Runtime]System.String::op_Equality(string, string) /* 0A000012 */
IL_0070: br.s IL_0073
IL_0072: ldc.i4.0
IL_0073: stloc.0
IL_0074: ldarg.s d
IL_0076: call bool [System.Runtime]System.String::IsNullOrEmpty(string) /* 0A000015 */
IL_007b: brtrue.s IL_009d
IL_007d: ldstr "ACTUAL4 : " /* 70000059 */
IL_0082: ldarg.s d
IL_0084: call string [System.Runtime]System.String::Concat(string, string) /* 0A000013 */
IL_0089: call void [System.Console]System.Console::WriteLine(string) /* 0A000014 */
IL_008e: ldloc.0
IL_008f: brfalse.s IL_009b
IL_0091: ldarg.s d
IL_0093: ldarg.0
IL_0094: call bool [System.Runtime]System.String::op_Equality(string, string) /* 0A000012 */
IL_0099: br.s IL_009c
IL_009b: ldc.i4.0
IL_009c: stloc.0
IL_009d: call void [System.Console]System.Console::WriteLine() /* 0A000016 */
IL_00a2: ldloc.0
IL_00a3: ret
} // end of method Program::CheckResults
// ============== Test using GenMiddleType ============== //
// These test methods attempt to load the invalid types, and are
// expected to throw a TypeLoadException (caught by Main())
.method public static void RunInvalidTest1() noinlining
{
newobj instance void class Invalid1<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunInvalidTest2() noinlining
{
newobj instance void class Invalid2<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunInvalidTest3() noinlining
{
newobj instance void class Invalid3<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
.method public static void RunInvalidTest4() noinlining
{
newobj instance void class Invalid4<int32,object>::.ctor()
call void [System.Console]System.Console::WriteLine(object)
ret
}
// ===================================================================================== //
.method public hidebysig static int32 Main() cil managed
{
.custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = (
01 00 00 00
)
.entrypoint
.maxstack 2
.locals init ( bool result )
ldc.i4.1
stloc.0
INVALID1:
.try
{
call void CMain::RunInvalidTest1()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid1."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID2
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID2
}
INVALID2:
.try
{
call void CMain::RunInvalidTest2()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid2."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID3
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID3
}
INVALID3:
.try
{
call void CMain::RunInvalidTest3()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid3."
call void [System.Console]System.Console::WriteLine(string)
leave.s INVALID4
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s INVALID4
}
INVALID4:
.try
{
call void CMain::RunInvalidTest4()
ldc.i4.0
stloc.0
ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid4."
call void [System.Console]System.Console::WriteLine(string)
leave.s DONE
}
catch [mscorlib]System.TypeLoadException
{
ldstr "Caught expected TypeLoadException:"
call void [System.Console]System.Console::WriteLine(string)
call void [System.Console]System.Console::WriteLine(object)
leave.s DONE
}
DONE:
ldloc.0
brtrue.s PASS
ldstr "Test FAILED"
call void [System.Console]System.Console::WriteLine(string)
ldc.i4.s 101
ret
PASS:
ldstr "Test PASSED"
call void [System.Console]System.Console::WriteLine(string)
ldc.i4.s 100
ret
ldc.i4.s 100
ret
}
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<!-- Needed for mechanical merging of all remaining tests, this particular project may not actually need process isolation -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
</PropertyGroup>
<ItemGroup>
<Compile Include="UnitTest_GVM_TypeLoadException.il" />
</ItemGroup>
</Project>

View file

@ -1160,19 +1160,16 @@
<ExcludeList Include="$(XunitTestBinBase)/JIT/Regression/CLR-x86-JIT/V1-M12-Beta2/b59899/b59899/*" />
<!-- Covariant returns -->
<!-- https://github.com/dotnet/runtimelab/issues/205 -->
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\Interfaces\UnitTest\*" />
<!-- Tests that expect TypeLoadException -->
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\Interfaces\UnitTest_TypeLoadException\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\Interfaces\UnsupportedScenario1\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\Interfaces\UnsupportedScenario2\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\Interfaces\UnsupportedScenario3\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\ReturnTypeValidation\ImplicitOverrideSameSigAsDecl\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\ReturnTypeValidation\OverrideSameSigAsDecl\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\Structs\IncompatibleOverride\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\AttributeTesting\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\CompatibleWithTest\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\UnitTest\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\UnitTest_GVM\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\OverrideMoreDerivedReturn\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\CompatibleWithTest_TypeLoadException\*" />
<ExcludeList Include="$(XunitTestBinBase)/Loader\classloader\MethodImpl\CovariantReturns\UnitTest\UnitTest_GVM_TypeLoadException\*" />
<!-- Requires Debug build -->
<ExcludeList Include="$(XunitTestBinBase)/JIT\Directed\debugging\poisoning\poison\*" />
@ -1304,6 +1301,9 @@
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest/**">
<Issue>Doesn't pass after LLVM AOT compilation.</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest_TypeLoadException/**">
<Issue>Doesn't pass after LLVM AOT compilation.</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/TypeInitialization/CctorsWithSideEffects/CctorThrowMethodAccess/**">
<Issue>Doesn't pass after LLVM AOT compilation.</Issue>
</ExcludeList>