diff --git a/docs/design/features/covariant-return-methods.md b/docs/design/features/covariant-return-methods.md new file mode 100644 index 00000000000000..3c9ac8c4db890c --- /dev/null +++ b/docs/design/features/covariant-return-methods.md @@ -0,0 +1,98 @@ +# Covariant Return Methods + +Covariant return methods is a runtime feature designed to support the [covariant return types](https://github.com/dotnet/csharplang/blob/master/proposals/covariant-returns.md) and [records](https://github.com/dotnet/csharplang/blob/master/proposals/records.md) C# language features posed for C# 9.0. + +This feature allows an overriding method to have a return type that is different than the one on the method it overrides, but compatible with it. The type compability rules are defined in ECMA I.8.7.1. Example: using a more derived return type. + +Covariant return methods can only be described through MethodImpl records, and as an initial implementation will only be applicable to methods on reference types. Methods on interfaces and value types will not be supported (may be supported later in the future). + +MethodImpl checking will allow a return type to vary as long as the override is compatible with the return type of the method overriden (ECMA I.8.7.1). + +If a language wishes for the override to be semantically visible such that users of the more derived type may rely on the covariant return type it shall make the override a newslot method with appropriate visibility AND name to be used outside of the class. + +For virtual method slot MethodImpl overrides, each slot shall be checked for compatible signature on type load. (Implementation note: This behavior can be triggered only if the type has a covariant return type override in its hierarchy, so as to make this pay for play.) + +A new `PreserveBaseOverridesAttribute` shall be added. The presence of this attribute is to require the type loader to ensure that the MethodImpl records specified on the method have not lost their slot unifying behavior due to other actions. This is used to allow the C# language to require that overrides have the consistent behaviors expected. The expectation is that C# would place this attribute on covariant override methods in classes. + +## Implementation Notes + +### Return Type Checking + +During enumeration of MethodImpls on a type (`MethodTableBuilder::EnumerateMethodImpls()`), if the signatures of the MethodImpl and the MethodDecl do not match: +1. We repeat the signature comparison a second time, but skip the comparison of the return type signatures. If the signatures for the rest of the method arguments match, we will conditionally treat that MethodImpl as a valid one, but flag it for a closer examination of the return type compatibility at a later stage of type loading (end of `CLASS_LOAD_EXACTPARENTS` stage). +2. At the end of the `CLASS_LOAD_EXACTPARENTS` type loading stage, examing each virtual method on the type, and if it has been flagged for further return type checking: + + Load the `TypeHandle` of the return type of the method on base type. + + Load the `TypeHandle` of the return type of the method on the current type being validated. + + Verify that the second `TypeHandle` is compatible with the first `TypeHandle` using the `MethodTable::CanCastTo()` API. If they are not compatible, a TypeLoadException is thrown. + +The only exception where `CanCastTo()` will return true for an incompatible type according to the ECMA rules is for structs implementing interfaces, so we explicitly check for that case and throw a TypeLoadException if we hit it. + +Once a method is flagged for return type checking, every time the vtable slot containing that method gets overridden on a derived type, the new override will also be checked for compatiblity. This is to ensure that no derived type can implicitly override some virtual method that has already been overridden by some MethodImpl with a covariant return type. + +### VTable Slot Unification + +If a MethodImpl has the `PreserveBaseOverridesAttribute` attribute, it needs to propagate all applicable vtable slots on the type. This is to ensure that if we use the signature of one of the base type methods to call the overriding method, we still execute the overriding method. + +Consider this case: +``` C# + class A { + RetType VirtualFunction() { } + } + class B : A { + [PreserveBaseOverrides] + DerivedRetType VirtualFunction() { .override A.VirtualFuncion } + } + class C : B { + [PreserveBaseOverrides] + MoreDerivedRetType VirtualFunction() { .override A.VirtualFunction } + } +``` + +Given an object of type `C`, the attribute will ensure that: +``` C# + callvirt RetType A::VirtualFunc() -> executes the MethodImpl on C + callvirt DerivedRetType B::VirtualFunc() -> executes the MethodImpl on C + callvirt MoreDerivedRetType C::VirtualFunc() -> executes the MethodImpl on C +``` + +Without the attribute, the second callvirt would normally execute the MethodImpl on `B` (the MethodImpl on `C` does not override the vtable slot of `B`'s MethodImpl, but only overrides the declaring method's vtable slot. + +This slot unification step will also take place during the last step of type loading (end of `CLASS_LOAD_EXACTPARENTS` stage). + +### [Future] Interface Support + +An interface method may be both non-final and have a MethodImpl that declares that it overrides another interface method. If it does, NO other interface method may .override it. Instead further overrides must override the method that it overrode. Also the overriding method may only override 1 method. + +The default interface method resolution algorithm shall change from: + +``` console +Given interface method M and type T. +Let MSearch = M +Let MFound = Most specific implementation within the interfaces for MSearch within type T. If multiple implementations are found, throw Ambiguous match exception. +Return MFound +``` + +To: + +``` console +Given interface method M and type T. +Let MSearch = M + +If (MSearch overrides another method MBase) + Let MSearch = MBase + +Let MFound = Most specific implementation within the interfaces for MSearch within type T. If multiple implementations are found, throw Ambiguous match exception. +Let M Code = NULL + +If ((MFound != Msearch) and (MFound is not final)) + Let M ClassVirtual = ResolveInterfaceMethod for MFound to virtual override on class T without using Default interface method implementation or return NULL if not found. + If (M ClassVirtual != NULL) + Let M Code= ResolveVirtualMethod for MFound on class T to implementation method + +If (M Code != NULL) + Let M Code = MFound + +Check M Code For signature interface method M. + +Return M Code +``` diff --git a/src/coreclr/src/dlls/mscorrc/mscorrc.rc b/src/coreclr/src/dlls/mscorrc/mscorrc.rc index 8a7410ef25b2d5..9337b473d7aac6 100644 --- a/src/coreclr/src/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/src/dlls/mscorrc/mscorrc.rc @@ -421,6 +421,7 @@ BEGIN IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH "Signature of the body and declaration in a method implementation do not match. Type: '%1'. Assembly: '%2'." IDS_CLASSLOAD_MI_MISSING_SIG_BODY "Signature for the body in a method implementation cannot be found. Type: '%1'. Assembly: '%2'." IDS_CLASSLOAD_MI_MISSING_SIG_DECL "Signature for the declaration in a method implementation cannot be found. Type: '%1'. Assembly: '%2'." + IDS_CLASSLOAD_MI_BADRETURNTYPE "Return type in method '%1' on type '%2' from assembly '%3' is not compatible with base type method '%4'." IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS "Could not load the structure '%1' from assembly '%2'. The structure is marked as eligible for type equivalence, but it has a method." IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS "Could not load the structure '%1' from assembly '%2'. The structure is marked as eligible for type equivalence, but it has a static or non-public field." diff --git a/src/coreclr/src/dlls/mscorrc/resource.h b/src/coreclr/src/dlls/mscorrc/resource.h index 342c0570d493bb..a75aa00afe1d3a 100644 --- a/src/coreclr/src/dlls/mscorrc/resource.h +++ b/src/coreclr/src/dlls/mscorrc/resource.h @@ -167,6 +167,7 @@ #define IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH 0x17a5 #define IDS_CLASSLOAD_MI_MISSING_SIG_BODY 0x17a6 #define IDS_CLASSLOAD_MI_MISSING_SIG_DECL 0x17a7 +#define IDS_CLASSLOAD_MI_BADRETURNTYPE 0x17a8 #define IDS_CLASSLOAD_TOOMANYGENERICARGS 0x17ab #define IDS_ERROR 0x17b0 diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/CastingHelper.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/CastingHelper.cs index d850cc6b334b28..86cf445f2b1047 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/CastingHelper.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/CastingHelper.cs @@ -20,6 +20,31 @@ public static bool CanCastTo(this TypeDesc thisType, TypeDesc otherType) return thisType.CanCastToInternal(otherType, null); } + public static bool IsCompatibleWith(this TypeDesc thisType, TypeDesc otherType) + { + // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1 + bool isCastFromValueTypeToReferenceType = otherType.IsValueType && !thisType.IsValueType; + if (isCastFromValueTypeToReferenceType) + { + return false; + } + + // Nullable can be cast to T, but this is not compatible according to ECMA I.8.7.1 + bool isCastFromNullableOfTtoT = thisType.IsNullable && otherType.IsEquivalentTo(thisType.Instantiation[0]); + if (isCastFromNullableOfTtoT) + { + return false; + } + + return otherType.CanCastTo(thisType); + } + + private static bool IsEquivalentTo(this TypeDesc thisType, TypeDesc otherType) + { + // TODO: Once type equivalence is implemented, this implementation needs to be enhanced to honor it. + return thisType.Equals(otherType); + } + private static bool CanCastToInternal(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protect) { if (thisType == otherType) diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataRuntimeInterfacesAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataRuntimeInterfacesAlgorithm.cs index 4b71985bfbee01..2c5d4789afce54 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataRuntimeInterfacesAlgorithm.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataRuntimeInterfacesAlgorithm.cs @@ -22,13 +22,7 @@ public override DefType[] ComputeRuntimeInterfaces(TypeDesc _type) // TODO: need to implement deduplication // https://github.com/dotnet/corert/issues/208 - if (type.IsInterface) - { - // For interfaces, the set of interfaces implemented directly matches the - // explicitly implemented interface list - return type.ExplicitlyImplementedInterfaces; - } - else if (type is InstantiatedType) + if (type is InstantiatedType) { return ComputeRuntimeInterfacesForInstantiatedType((InstantiatedType)type); } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs index dbd21a08347675..f5b1544369b7d1 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace Internal.TypeSystem { @@ -45,6 +46,9 @@ private class UnificationGroup private MethodDesc[] _members = MethodDesc.EmptyMethods; private int _memberCount = 0; + private MethodDesc[] _methodsRequiringSlotUnification = MethodDesc.EmptyMethods; + private int _methodsRequiringSlotUnificationCount = 0; + /// /// Custom enumerator struct for Unification group. Makes enumeration require 0 allocations. /// @@ -86,6 +90,21 @@ public MethodDesc Current } } + public struct Enumerable + { + private readonly MethodDesc[] _arrayToEnumerate; + + public Enumerable(MethodDesc[] arrayToEnumerate) + { + _arrayToEnumerate = arrayToEnumerate; + } + + public Enumerator GetEnumerator() + { + return new Enumerator(_arrayToEnumerate); + } + } + public UnificationGroup(MethodDesc definingMethod) { DefiningMethod = definingMethod; @@ -94,9 +113,31 @@ public UnificationGroup(MethodDesc definingMethod) public MethodDesc DefiningMethod; - public Enumerator GetEnumerator() + public Enumerable Members => new Enumerable(_members); + + public Enumerable MethodsRequiringSlotUnification => new Enumerable(_methodsRequiringSlotUnification); + + public void AddMethodRequiringSlotUnification(MethodDesc method) + { + if (RequiresSlotUnification(method)) + return; + + _methodsRequiringSlotUnificationCount++; + if (_methodsRequiringSlotUnificationCount >= _methodsRequiringSlotUnification.Length) + { + Array.Resize(ref _methodsRequiringSlotUnification, Math.Max(_methodsRequiringSlotUnification.Length * 2, 2)); + } + _methodsRequiringSlotUnification[_methodsRequiringSlotUnificationCount - 1] = method; + } + + public bool RequiresSlotUnification(MethodDesc method) { - return new Enumerator(_members); + for(int i = 0; i < _methodsRequiringSlotUnificationCount; i++) + { + if (_methodsRequiringSlotUnification[i] == method) + return true; + } + return false; } public void SetDefiningMethod(MethodDesc newDefiningMethod) @@ -395,6 +436,11 @@ private static void FindBaseUnificationGroup(MetadataType currentType, Unificati MethodDesc methodImpl = FindImplFromDeclFromMethodImpls(currentType, unificationGroup.DefiningMethod); if (methodImpl != null) { + if(methodImpl.RequiresSlotUnification()) + { + unificationGroup.AddMethodRequiringSlotUnification(unificationGroup.DefiningMethod); + unificationGroup.AddMethodRequiringSlotUnification(methodImpl); + } unificationGroup.SetDefiningMethod(methodImpl); } @@ -416,7 +462,7 @@ private static void FindBaseUnificationGroup(MetadataType currentType, Unificati // Start with removing methods that seperated themselves from the group via name/sig matches MethodDescHashtable separatedMethods = null; - foreach (MethodDesc memberMethod in unificationGroup) + foreach (MethodDesc memberMethod in unificationGroup.Members) { MethodDesc nameSigMatchMemberMethod = FindMatchingVirtualMethodOnTypeByNameAndSigWithSlotCheck(memberMethod, currentType, reverseMethodSearch: true); if (nameSigMatchMemberMethod != null && nameSigMatchMemberMethod != memberMethod) @@ -448,29 +494,68 @@ private static void FindBaseUnificationGroup(MetadataType currentType, Unificati if (separatedMethods == null) separatedMethods = new MethodDescHashtable(); separatedMethods.AddOrGetExisting(declSlot); + + if (unificationGroup.RequiresSlotUnification(declSlot) || implSlot.RequiresSlotUnification()) + { + if (implSlot.Signature.EqualsWithCovariantReturnType(unificationGroup.DefiningMethod.Signature)) + { + unificationGroup.AddMethodRequiringSlotUnification(declSlot); + unificationGroup.AddMethodRequiringSlotUnification(implSlot); + unificationGroup.SetDefiningMethod(implSlot); + } + } + continue; } - if (!unificationGroup.IsInGroupOrIsDefiningSlot(declSlot) && unificationGroup.IsInGroupOrIsDefiningSlot(implSlot)) + if (!unificationGroup.IsInGroupOrIsDefiningSlot(declSlot)) { - // Add decl to group. + if (unificationGroup.IsInGroupOrIsDefiningSlot(implSlot)) + { + // Add decl to group. - // To do so, we need to have the Unification Group of the decl slot, as it may have multiple members itself - UnificationGroup addDeclGroup = new UnificationGroup(declSlot); - FindBaseUnificationGroup(baseType, addDeclGroup); - Debug.Assert(addDeclGroup.IsInGroupOrIsDefiningSlot(declSlot)); + // To do so, we need to have the Unification Group of the decl slot, as it may have multiple members itself + UnificationGroup addDeclGroup = new UnificationGroup(declSlot); + FindBaseUnificationGroup(baseType, addDeclGroup); + Debug.Assert( + addDeclGroup.IsInGroupOrIsDefiningSlot(declSlot) || + (addDeclGroup.RequiresSlotUnification(declSlot) && addDeclGroup.DefiningMethod.Signature.EqualsWithCovariantReturnType(declSlot.Signature))); - // Add all members from the decl's unification group except for ones that have been seperated by name/sig matches - // or previously processed methodimpls. NOTE: This implies that method impls are order dependent. - if (separatedMethods == null || !separatedMethods.Contains(addDeclGroup.DefiningMethod)) - { - unificationGroup.AddToGroup(addDeclGroup.DefiningMethod); - } + foreach(MethodDesc methodImplRequiredToRemainInEffect in addDeclGroup.MethodsRequiringSlotUnification) + { + unificationGroup.AddMethodRequiringSlotUnification(methodImplRequiredToRemainInEffect); + } + + // Add all members from the decl's unification group except for ones that have been seperated by name/sig matches + // or previously processed methodimpls. NOTE: This implies that method impls are order dependent. + if (separatedMethods == null || !separatedMethods.Contains(addDeclGroup.DefiningMethod)) + { + unificationGroup.AddToGroup(addDeclGroup.DefiningMethod); + } + + foreach (MethodDesc addDeclGroupMemberMethod in addDeclGroup.Members) + { + if (separatedMethods == null || !separatedMethods.Contains(addDeclGroupMemberMethod)) + { + unificationGroup.AddToGroup(addDeclGroupMemberMethod); + } + } - foreach (MethodDesc addDeclGroupMemberMethod in addDeclGroup) + if(unificationGroup.RequiresSlotUnification(declSlot)) + { + unificationGroup.AddMethodRequiringSlotUnification(implSlot); + } + else if (implSlot == unificationGroup.DefiningMethod && implSlot.RequiresSlotUnification()) + { + unificationGroup.AddMethodRequiringSlotUnification(declSlot); + unificationGroup.AddMethodRequiringSlotUnification(implSlot); + } + } + else if (unificationGroup.RequiresSlotUnification(declSlot)) { - if (separatedMethods == null || !separatedMethods.Contains(addDeclGroupMemberMethod)) + if (implSlot.Signature.EqualsWithCovariantReturnType(unificationGroup.DefiningMethod.Signature)) { - unificationGroup.AddToGroup(addDeclGroupMemberMethod); + unificationGroup.AddMethodRequiringSlotUnification(implSlot); + unificationGroup.SetDefiningMethod(implSlot); } } } diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/MethodDesc.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/MethodDesc.cs index 3e204f8fa7546e..e9290512641a17 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/MethodDesc.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/MethodDesc.cs @@ -115,6 +115,16 @@ public int Length } public bool Equals(MethodSignature otherSignature) + { + return Equals(otherSignature, allowCovariantReturn: false); + } + + public bool EqualsWithCovariantReturnType(MethodSignature otherSignature) + { + return Equals(otherSignature, allowCovariantReturn: true); + } + + private bool Equals(MethodSignature otherSignature, bool allowCovariantReturn) { // TODO: Generics, etc. if (this._flags != otherSignature._flags) @@ -124,7 +134,13 @@ public bool Equals(MethodSignature otherSignature) return false; if (this._returnType != otherSignature._returnType) - return false; + { + if (!allowCovariantReturn) + return false; + + if (!otherSignature._returnType.IsCompatibleWith(this._returnType)) + return false; + } if (this._parameters.Length != otherSignature._parameters.Length) return false; diff --git a/src/coreclr/src/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs b/src/coreclr/src/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs index e76f5e3087057e..10b2edb0abdce5 100644 --- a/src/coreclr/src/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs +++ b/src/coreclr/src/tools/Common/TypeSystem/Common/TypeSystemHelpers.cs @@ -411,5 +411,37 @@ public static bool ContainsSignatureVariables(this TypeDesc thisType) return false; } } + + /// + /// Check if MethodImpl requires slot unification. + /// + /// Method to check + /// True when the method is marked with the PreserveBaseOverrides custom attribute, false otherwise. + public static bool RequiresSlotUnification(this MethodDesc method) + { + if (method.HasCustomAttribute("System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute")) + { +#if DEBUG + // We shouldn't be calling this for non-MethodImpls, so verify that the method being checked is really a MethodImpl + MetadataType mdType = method.OwningType as MetadataType; + if (mdType != null) + { + bool isMethodImpl = false; + foreach (MethodImplRecord methodImplRecord in mdType.VirtualMethodImplsForType) + { + if (method == methodImplRecord.Body) + { + isMethodImpl = true; + break; + } + } + Debug.Assert(isMethodImpl); + } +#endif + return true; + } + + return false; + } } } diff --git a/src/coreclr/src/vm/class.cpp b/src/coreclr/src/vm/class.cpp index c87c21d1515952..bd13819169c409 100644 --- a/src/coreclr/src/vm/class.cpp +++ b/src/coreclr/src/vm/class.cpp @@ -967,12 +967,208 @@ void ClassLoader::LoadExactParents(MethodTable *pMT) MethodTableBuilder::CopyExactParentSlots(pMT, pApproxParentMT); + ValidateMethodsWithCovariantReturnTypes(pMT); + // We can now mark this type as having exact parents pMT->SetHasExactParent(); RETURN; } +// Checks if two types are compatible according to compatible-with as described in ECMA 335 I.8.7.1 +// Most of the checks are performed by the CanCastTo, but with some cases pre-filtered out. +// +/*static*/ +bool ClassLoader::IsCompatibleWith(TypeHandle hType1, TypeHandle hType2) +{ + // Structs can be cast to the interfaces they implement, but they are not compatible according to ECMA I.8.7.1 + bool isCastFromValueTypeToReferenceType = hType2.IsValueType() && !hType1.IsValueType(); + if (isCastFromValueTypeToReferenceType) + { + return false; + } + + // Nullable can be cast to T, but this is not compatible according to ECMA I.8.7.1 + bool isCastFromNullableOfTtoT = hType1.GetMethodTable()->IsNullable() && hType2.IsEquivalentTo(hType1.GetMethodTable()->GetInstantiation()[0]); + if (isCastFromNullableOfTtoT) + { + return false; + } + + { + GCX_COOP(); + return hType2.GetMethodTable()->CanCastTo(hType1.GetMethodTable(), NULL); + } +} + +/*static*/ +void ClassLoader::ValidateMethodsWithCovariantReturnTypes(MethodTable* pMT) +{ + CONTRACTL + { + STANDARD_VM_CHECK; + PRECONDITION(CheckPointer(pMT)); + } + CONTRACTL_END; + + // + // Validation for methods with covariant return types is a two step process. + // + // The first step is to validate that the return types on overriding methods with covariant return types are + // compatible with the return type of the method being overridden. Compatibility rules are defined by + // ECMA I.8.7.1, which is what the CanCastTo() API checks. + // + // The second step is to propagate an overriding MethodImpl to all applicable vtable slots if the MethodImpl + // has the PreserveBaseOverrides attribute. This is to ensure that if we use the signature of one of + // the base type methods to call the overriding method, we still execute the overriding method. + // + // Consider this case: + // + // class A { + // RetType VirtualFunction() { } + // } + // class B : A { + // [PreserveBaseOverrides] + // DerivedRetType VirtualFunction() { .override A.VirtualFuncion } + // } + // class C : B { + // MoreDerivedRetType VirtualFunction() { .override A.VirtualFunction } + // } + // + // NOTE: Typically the attribute would be added to the MethodImpl on C, but was omitted in this example to + // illustrate how its presence on a MethodImpl on the base type can propagate as well. In other words, + // think of it as applying to the vtable slot itself, so any MethodImpl that overrides this slot on a + // derived type will propagate to all other applicable vtable slots. + // + // Given an object of type C, the attribute will ensure that: + // callvirt RetType A::VirtualFunc() -> executes the MethodImpl on C + // callvirt DerivedRetType B::VirtualFunc() -> executes the MethodImpl on C + // callvirt MoreDerivedRetType C::VirtualFunc() -> executes the MethodImpl on C + // + // Without the attribute, the second callvirt would normally execute the MethodImpl on B (the MethodImpl on + // C does not override the vtable slot of B's MethodImpl, but only overrides the declaring method's vtable slot. + // + + // Validation not applicable to interface types and value types, since these are not currently + // supported with the covariant return feature + + if (pMT->IsInterface() || pMT->IsValueType()) + return; + + MethodTable* pParentMT = pMT->GetParentMethodTable(); + if (pParentMT == NULL) + return; + + // Step 1: Validate compatibility of return types on overriding methods + + for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) + { + MethodDesc* pMD = pMT->GetMethodDescForSlot(i); + MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); + + if (pMD == pParentMD) + continue; + + if (!pMD->RequiresCovariantReturnTypeChecking() && !pParentMD->RequiresCovariantReturnTypeChecking()) + continue; + + // If the bit is not set on this method, but we reach here because it's been set on the method at the same slot on + // the base type, set the bit for the current method to ensure any future overriding method down the chain gets checked. + if (!pMD->RequiresCovariantReturnTypeChecking()) + pMD->SetRequiresCovariantReturnTypeChecking(); + + // The context used to load the return type of the parent method has to use the generic method arguments + // of the overriding method, otherwise the type comparison below will not work correctly + SigTypeContext context1(pParentMD->GetClassInstantiation(), pMD->GetMethodInstantiation()); + MetaSig methodSig1(pParentMD); + TypeHandle hType1 = methodSig1.GetReturnProps().GetTypeHandleThrowing(pParentMD->GetModule(), &context1, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS); + + SigTypeContext context2(pMD); + MetaSig methodSig2(pMD); + TypeHandle hType2 = methodSig2.GetReturnProps().GetTypeHandleThrowing(pMD->GetModule(), &context2, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS); + + _ASSERTE(hType1.GetMethodTable() != NULL); + _ASSERTE(hType2.GetMethodTable() != NULL); + + if (!IsCompatibleWith(hType1, hType2)) + { + SString strAssemblyName; + pMD->GetAssembly()->GetDisplayName(strAssemblyName); + + SString strInvalidTypeName; + TypeString::AppendType(strInvalidTypeName, TypeHandle(pMD->GetMethodTable())); + + SString strInvalidMethodName; + TypeString::AppendMethod(strInvalidMethodName, pMD, pMD->GetMethodInstantiation()); + + SString strParentMethodName; + TypeString::AppendMethod(strParentMethodName, pParentMD, pParentMD->GetMethodInstantiation()); + + COMPlusThrow( + kTypeLoadException, + IDS_CLASSLOAD_MI_BADRETURNTYPE, + strInvalidMethodName, + strInvalidTypeName, + strAssemblyName, + strParentMethodName); + } + } + + // Step 2: propate overriding MethodImpls to applicable vtable slots if the declaring method has the attribute + + MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE)); + + for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) + { + MethodDesc* pMD = pMT->GetMethodDescForSlot(i); + MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); + if (pMD == pParentMD) + continue; + + // The attribute is only applicable to MethodImpls. For anything else, it will be treated as a no-op + if (!pMD->IsMethodImpl()) + continue; + + // Search if the attribute has been applied on this vtable slot, either by the current MethodImpl, or by a previous + // MethodImpl somewhere in the base type hierarchy. + bool foundAttribute = false; + MethodTable* pCurrentMT = pMT; + while (!foundAttribute && pCurrentMT != NULL && i < pCurrentMT->GetNumVirtuals()) + { + MethodDesc* pCurrentMD = pCurrentMT->GetMethodDescForSlot(i); + + // The attribute is only applicable to MethodImpls. For anything else, it will be treated as a no-op + if (pCurrentMD->IsMethodImpl()) + { + BYTE* pVal = NULL; + ULONG cbVal = 0; + if (pCurrentMD->GetCustomAttribute(WellKnownAttribute::PreserveBaseOverridesAttribute, (const void**)&pVal, &cbVal) == S_OK) + foundAttribute = true; + } + + pCurrentMT = pCurrentMT->GetParentMethodTable(); + } + + if (!foundAttribute) + continue; + + // Search for any vtable slot still pointing at the parent method, and update it with the current overriding method + for (WORD j = i; j < pParentMT->GetNumVirtuals(); j++) + { + MethodDesc* pCurrentMD = pMT->GetMethodDescForSlot(j); + if (pCurrentMD == pParentMD) + { + // This is a vtable slot that needs to be updated to the new overriding method because of the + // presence of the attribute. + pMT->SetSlot(j, pMT->GetSlot(i)); + _ASSERT(pMT->GetMethodDescForSlot(j) == pMD); + + hMTData->UpdateImplMethodDesc(pMD, j); + } + } + } +} + //******************************************************************************* // This is the routine that computes the internal type of a given type. It normalizes // structs that have only one field (of int/ptr sized values), to be that underlying type. diff --git a/src/coreclr/src/vm/classcompat.cpp b/src/coreclr/src/vm/classcompat.cpp index f74c2247ba29d6..c89c4ee6067fb6 100644 --- a/src/coreclr/src/vm/classcompat.cpp +++ b/src/coreclr/src/vm/classcompat.cpp @@ -1405,7 +1405,7 @@ VOID MethodTableBuilder::BuildInteropVTable_PlaceVtableMethods( bmtType->pModule, NULL, pInterfaceMethodSig, cInterfaceMethodSig, - pInterfaceMD->GetModule(), NULL)) + pInterfaceMD->GetModule(), NULL, FALSE)) { // Found match, break from loop break; } @@ -2263,7 +2263,8 @@ VOID MethodTableBuilder::EnumerateMethodImpls() pSigBody, cbSigBody, bmtType->pModule, - NULL)) + NULL, + FALSE)) { BuildMethodTableThrowException(IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH); } diff --git a/src/coreclr/src/vm/clsload.hpp b/src/coreclr/src/vm/clsload.hpp index 23a051f6aeef45..042c45c513e210 100644 --- a/src/coreclr/src/vm/clsload.hpp +++ b/src/coreclr/src/vm/clsload.hpp @@ -969,10 +969,14 @@ class ClassLoader // Phase CLASS_LOAD_EXACTPARENTS of class loading // Load exact parents and interfaces and dependent structures (generics dictionary, vtable fixes) - static void LoadExactParents(MethodTable *pMT); + static void LoadExactParents(MethodTable* pMT); static void LoadExactParentAndInterfacesTransitively(MethodTable *pMT); + static void ValidateMethodsWithCovariantReturnTypes(MethodTable* pMT); + + static bool IsCompatibleWith(TypeHandle hType1, TypeHandle hType2); + // Create a non-canonical instantiation of a generic type based off the canonical instantiation // (For example, MethodTable for List is based on the MethodTable for List<__Canon>) static TypeHandle CreateTypeHandleForNonCanonicalGenericInstantiation(TypeKey *pTypeKey, diff --git a/src/coreclr/src/vm/ecall.cpp b/src/coreclr/src/vm/ecall.cpp index 7231cd3ff8f15a..414838c01fa108 100644 --- a/src/coreclr/src/vm/ecall.cpp +++ b/src/coreclr/src/vm/ecall.cpp @@ -349,7 +349,7 @@ static INT FindECIndexForMethod(MethodDesc *pMD, const LPVOID* impls) //@GENERICS: none of these methods belong to generic classes so there is no instantiation info to pass in if (!MetaSig::CompareMethodSigs(pMethodSig, cbMethodSigLen, pModule, NULL, - sig.GetRawSig(), sig.GetRawSigLen(), MscorlibBinder::GetModule(), NULL)) + sig.GetRawSig(), sig.GetRawSigLen(), MscorlibBinder::GetModule(), NULL, FALSE)) { continue; } diff --git a/src/coreclr/src/vm/memberload.cpp b/src/coreclr/src/vm/memberload.cpp index 1881b3f0b779ce..c0e26d74d32f5e 100644 --- a/src/coreclr/src/vm/memberload.cpp +++ b/src/coreclr/src/vm/memberload.cpp @@ -243,7 +243,7 @@ void MemberLoader::GetDescFromMemberRef(Module * pModule, pMethodDef->GetSig(&pMethodSig, &cMethodSig); if (!MetaSig::CompareMethodSigs(pSig, cSig, pModule, NULL, pMethodSig, - cMethodSig, pModule, NULL)) + cMethodSig, pModule, NULL, FALSE)) { // If the signatures do not match, then the correct MethodDesc has not been found. fMissingMethod = TRUE; @@ -1043,7 +1043,7 @@ BOOL CompareMethodSigWithCorrectSubstitution( pCurDeclMD->GetSig(&pCurMethodSig, &cCurMethodSig); return MetaSig::CompareMethodSigs(pSignature, cSignature, pModule, NULL, pCurMethodSig, - cCurMethodSig, pCurDeclMD->GetModule(), pDefSubst); + cCurMethodSig, pCurDeclMD->GetModule(), pDefSubst, FALSE); } else { @@ -1443,7 +1443,7 @@ MemberLoader::FindConstructor(MethodTable * pMT, PCCOR_SIGNATURE pSignature,DWOR DWORD cCurMethodSig; pCurMethod->GetSig(&pCurMethodSig, &cCurMethodSig); - if (MetaSig::CompareMethodSigs(pSignature, cSignature, pModule, NULL, pCurMethodSig, cCurMethodSig, pCurMethod->GetModule(), NULL)) + if (MetaSig::CompareMethodSigs(pSignature, cSignature, pModule, NULL, pCurMethodSig, cCurMethodSig, pCurMethod->GetModule(), NULL, FALSE)) { return pCurMethod; } diff --git a/src/coreclr/src/vm/method.hpp b/src/coreclr/src/vm/method.hpp index 5973cd6d6053fc..0102f911c6dd86 100644 --- a/src/coreclr/src/vm/method.hpp +++ b/src/coreclr/src/vm/method.hpp @@ -1829,17 +1829,18 @@ class MethodDesc enum { // enum_flag2_HasPrecode implies that enum_flag2_HasStableEntryPoint is set. - enum_flag2_HasStableEntryPoint = 0x01, // The method entrypoint is stable (either precode or actual code) - enum_flag2_HasPrecode = 0x02, // Precode has been allocated for this method + enum_flag2_HasStableEntryPoint = 0x01, // The method entrypoint is stable (either precode or actual code) + enum_flag2_HasPrecode = 0x02, // Precode has been allocated for this method - enum_flag2_IsUnboxingStub = 0x04, - enum_flag2_HasNativeCodeSlot = 0x08, // Has slot for native code + enum_flag2_IsUnboxingStub = 0x04, + enum_flag2_HasNativeCodeSlot = 0x08, // Has slot for native code - enum_flag2_IsJitIntrinsic = 0x10, // Jit may expand method as an intrinsic + enum_flag2_IsJitIntrinsic = 0x10, // Jit may expand method as an intrinsic - enum_flag2_IsEligibleForTieredCompilation = 0x20, + enum_flag2_IsEligibleForTieredCompilation = 0x20, + + enum_flag2_RequiresCovariantReturnTypeChecking = 0x40 - // unused = 0x40, // unused = 0x80, }; BYTE m_bFlags2; @@ -1902,6 +1903,19 @@ class MethodDesc m_bFlags2 |= enum_flag2_IsJitIntrinsic; } + BOOL RequiresCovariantReturnTypeChecking() + { + LIMITED_METHOD_DAC_CONTRACT; + + return (m_bFlags2 & enum_flag2_RequiresCovariantReturnTypeChecking) != 0; + } + + void SetRequiresCovariantReturnTypeChecking() + { + LIMITED_METHOD_CONTRACT; + m_bFlags2 |= enum_flag2_RequiresCovariantReturnTypeChecking; + } + static const SIZE_T s_ClassificationSizeTable[]; static SIZE_T GetBaseSize(DWORD classification) diff --git a/src/coreclr/src/vm/methodtable.cpp b/src/coreclr/src/vm/methodtable.cpp index 1706f0c327c4e4..4269f69720b7f5 100644 --- a/src/coreclr/src/vm/methodtable.cpp +++ b/src/coreclr/src/vm/methodtable.cpp @@ -8468,6 +8468,22 @@ MethodDesc *MethodTable::MethodDataObject::GetImplMethodDesc(UINT32 slotNumber) return pMDRet; } +//========================================================================================== +void MethodTable::MethodDataObject::UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber) +{ + WRAPPER_NO_CONTRACT; + _ASSERTE(slotNumber < GetNumVirtuals()); + _ASSERTE(pMD->IsMethodImpl()); + + MethodDataObjectEntry* pEntry = GetEntry(slotNumber); + + // Fill the entries one level of inheritance at a time, + // stopping when we have filled the MD we are looking for. + while (!pEntry->GetImplMethodDesc() && PopulateNextLevel()); + + pEntry->SetImplMethodDesc(pMD); +} + //========================================================================================== void MethodTable::MethodDataObject::InvalidateCachedVirtualSlot(UINT32 slotNumber) { diff --git a/src/coreclr/src/vm/methodtable.h b/src/coreclr/src/vm/methodtable.h index f5aa74556ef28f..a7f6f65168b3bf 100644 --- a/src/coreclr/src/vm/methodtable.h +++ b/src/coreclr/src/vm/methodtable.h @@ -3163,6 +3163,8 @@ public : virtual UINT32 GetNumVirtuals() = 0; virtual UINT32 GetNumMethods() = 0; + virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber) = 0; + protected: static const UINT32 INVALID_SLOT_NUMBER = UINT32_MAX; @@ -3267,6 +3269,8 @@ public : virtual UINT32 GetNumMethods() { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetCanonicalMethodTable()->GetNumMethods(); } + virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber); + protected: void Init(MethodData *pParentData); @@ -3373,6 +3377,10 @@ public : { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetNumVirtuals(); } virtual UINT32 GetNumMethods() { LIMITED_METHOD_CONTRACT; return m_pDeclMT->GetNumMethods(); } + + virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber) + { LIMITED_METHOD_CONTRACT; } + }; // class MethodDataInterface //-------------------------------------------------------------------------------------- @@ -3412,6 +3420,9 @@ public : virtual UINT32 GetNumMethods() { WRAPPER_NO_CONTRACT; return m_pDecl->GetNumVirtuals(); } + virtual void UpdateImplMethodDesc(MethodDesc* pMD, UINT32 slotNumber) + { LIMITED_METHOD_CONTRACT; } + protected: UINT32 MapToImplSlotNumber(UINT32 slotNumber); diff --git a/src/coreclr/src/vm/methodtablebuilder.cpp b/src/coreclr/src/vm/methodtablebuilder.cpp index 14ccfd4371061d..ab028235c0dc2c 100644 --- a/src/coreclr/src/vm/methodtablebuilder.cpp +++ b/src/coreclr/src/vm/methodtablebuilder.cpp @@ -892,13 +892,15 @@ MethodTableBuilder::MethodSignature::NamesEqual( /*static*/ bool MethodTableBuilder::MethodSignature::SignaturesEquivalent( const MethodSignature & sig1, - const MethodSignature & sig2) + const MethodSignature & sig2, + BOOL allowCovariantReturn) { STANDARD_VM_CONTRACT; return !!MetaSig::CompareMethodSigs( sig1.GetSignature(), static_cast(sig1.GetSignatureLength()), sig1.GetModule(), &sig1.GetSubstitution(), - sig2.GetSignature(), static_cast(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution()); + sig2.GetSignature(), static_cast(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution(), + allowCovariantReturn); } //******************************************************************************* @@ -913,7 +915,7 @@ MethodTableBuilder::MethodSignature::SignaturesExactlyEqual( return !!MetaSig::CompareMethodSigs( sig1.GetSignature(), static_cast(sig1.GetSignatureLength()), sig1.GetModule(), &sig1.GetSubstitution(), sig2.GetSignature(), static_cast(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution(), - &newVisited); + FALSE, &newVisited); } //******************************************************************************* @@ -923,7 +925,7 @@ MethodTableBuilder::MethodSignature::Equivalent( { STANDARD_VM_CONTRACT; - return NamesEqual(*this, rhs) && SignaturesEquivalent(*this, rhs); + return NamesEqual(*this, rhs) && SignaturesEquivalent(*this, rhs, FALSE); } //******************************************************************************* @@ -2156,6 +2158,83 @@ BOOL MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Equal( (elem1->methodDecl == elem2->methodDecl)); } +//******************************************************************************* +BOOL MethodTableBuilder::IsEligibleForCovariantReturns(mdToken methodDeclToken) +{ + STANDARD_VM_CONTRACT; + + // + // Note on covariant return types: right now we only support covariant returns for MethodImpls on + // classes, where the MethodDecl is also on a class. Interface methods are not supported. + // We will also allow covariant return types if both the MethodImpl and MethodDecl are not on the same type. + // + + HRESULT hr = S_OK; + IMDInternalImport* pMDInternalImport = GetMDImport(); + + // First, check if the type with the MethodImpl is a class. + if (IsValueClass() || IsInterface()) + return FALSE; + + mdToken tkParent; + hr = pMDInternalImport->GetParentToken(methodDeclToken, &tkParent); + if (FAILED(hr)) + BuildMethodTableThrowException(hr, *bmtError); + + // Second, check that the type with the MethodImpl is not the same as the type with the MethodDecl + if (GetCl() == tkParent) + return FALSE; + + // Finally, check that the type with the MethodDecl is not an interface. To do so, we need to compute the TypeDef + // token of the type with the MethodDecl, as well as its module, in order to use the metadata to check if the type + // is an interface. + mdToken declTypeDefToken = mdTokenNil; + Module* pDeclModule = GetModule(); + if (TypeFromToken(tkParent) == mdtTypeRef || TypeFromToken(tkParent) == mdtTypeDef) + { + if (!ClassLoader::ResolveTokenToTypeDefThrowing(GetModule(), tkParent, &pDeclModule, &declTypeDefToken)) + return FALSE; + } + else if (TypeFromToken(tkParent) == mdtTypeSpec) + { + ULONG cbTypeSig; + PCCOR_SIGNATURE pTypeSig; + hr = pMDInternalImport->GetSigFromToken(tkParent, &cbTypeSig, &pTypeSig); + if (FAILED(hr)) + BuildMethodTableThrowException(hr, *bmtError); + + SigParser parser(pTypeSig, cbTypeSig); + + CorElementType elementType; + IfFailThrow(parser.GetElemType(&elementType)); + + if (elementType == ELEMENT_TYPE_GENERICINST) + { + IfFailThrow(parser.GetElemType(&elementType)); + } + + if (elementType == ELEMENT_TYPE_CLASS) + { + mdToken declTypeDefOrRefToken; + IfFailThrow(parser.GetToken(&declTypeDefOrRefToken)); + if (!ClassLoader::ResolveTokenToTypeDefThrowing(GetModule(), declTypeDefOrRefToken, &pDeclModule, &declTypeDefToken)) + return FALSE; + } + } + + if (declTypeDefToken == mdTokenNil) + return FALSE; + + // Now that we have computed the TypeDef token and the module, check its attributes to verify it is not an interface. + + DWORD attr; + hr = pDeclModule->GetMDImport()->GetTypeDefProps(declTypeDefToken, &attr, NULL); + if (FAILED(hr)) + BuildMethodTableThrowException(hr, *bmtError); + + return !IsTdInterface(attr); +} + //******************************************************************************* VOID MethodTableBuilder::EnumerateMethodImpls() @@ -2196,6 +2275,7 @@ MethodTableBuilder::EnumerateMethodImpls() bmtMetaData->rgMethodImplTokens[i].fConsiderDuringInexactMethodImplProcessing = false; bmtMetaData->rgMethodImplTokens[i].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false; bmtMetaData->rgMethodImplTokens[i].interfaceEquivalenceSet = 0; + bmtMetaData->rgMethodImplTokens[i].fRequiresCovariantReturnTypeChecking = false; if (FAILED(hr)) { @@ -2365,17 +2445,26 @@ MethodTableBuilder::EnumerateMethodImpls() { BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_BODY); } + // Can't use memcmp because there may be two AssemblyRefs // in this scope, pointing to the same assembly, etc.). - if (!MetaSig::CompareMethodSigs( - pSigDecl, - cbSigDecl, - GetModule(), - &theDeclSubst, - pSigBody, - cbSigBody, - GetModule(), - NULL)) + BOOL compatibleSignatures = MetaSig::CompareMethodSigs(pSigDecl, cbSigDecl, GetModule(), &theDeclSubst, pSigBody, cbSigBody, GetModule(), NULL, FALSE); + + if (!compatibleSignatures && IsEligibleForCovariantReturns(theDecl)) + { + if (MetaSig::CompareMethodSigs(pSigDecl, cbSigDecl, GetModule(), &theDeclSubst, pSigBody, cbSigBody, GetModule(), NULL, TRUE)) + { + // Signatures matched, except for the return type. Flag that MethodImpl to check the return type at a later + // stage for compatibility, and treat it as compatible for now. + // For compatibility rules, see ECMA I.8.7.1. We will use the MethodTable::CanCastTo() at a later stage to validate + // compatibilities of the return types according to these rules. + + compatibleSignatures = TRUE; + bmtMetaData->rgMethodImplTokens[i].fRequiresCovariantReturnTypeChecking = true; + } + } + + if (!compatibleSignatures) { BuildMethodTableThrowException(IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH); } @@ -3648,10 +3737,10 @@ BOOL MethodTableBuilder::IsSelfReferencingStaticValueTypeField(mdToken dwByV PCCOR_SIGNATURE pFieldSig = pMemberSignature + 1; // skip the CALLCONV_FIELD - return MetaSig::CompareElementType(pFakeSig, pFieldSig, + return MetaSig::CompareElementType(pFakeSig, pFieldSig, pFakeSig + cFakeSig, pMemberSignature + cMemberSignature, GetModule(), GetModule(), - NULL, NULL); + NULL, NULL, FALSE); } @@ -5542,6 +5631,11 @@ MethodTableBuilder::ProcessInexactMethodImpls() if (fPreexistingImplFound) continue; + if (bmtMetaData->rgMethodImplTokens[m].fRequiresCovariantReturnTypeChecking) + { + it->GetMethodDesc()->SetRequiresCovariantReturnTypeChecking(); + } + // Otherwise, record the method impl discovery if the match is bmtMethodImpl->AddMethodImpl(*it, declMethod, bmtMetaData->rgMethodImplTokens[m].methodDecl, GetStackingAllocator()); } @@ -5818,6 +5912,7 @@ MethodTableBuilder::ProcessMethodImpls() cbCurMDSig, pCurMD->GetModule(), &pCurDeclType->GetSubstitution(), + FALSE, iPass == 0 ? &newVisited : NULL)) { declMethod = (*bmtParent->pSlotTable)[pCurMD->GetSlot()].Decl(); @@ -5858,6 +5953,11 @@ MethodTableBuilder::ProcessMethodImpls() BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token()); } + if (bmtMetaData->rgMethodImplTokens[m].fRequiresCovariantReturnTypeChecking) + { + it->GetMethodDesc()->SetRequiresCovariantReturnTypeChecking(); + } + bmtMethodImpl->AddMethodImpl(*it, declMethod, mdDecl, GetStackingAllocator()); } } @@ -6118,6 +6218,7 @@ VOID MethodTableBuilder::MethodImplCompareSignatures( bmtMethodHandle hDecl, bmtMethodHandle hImpl, + BOOL allowCovariantReturn, DWORD dwConstraintErrorCode) { CONTRACTL { @@ -6131,7 +6232,7 @@ MethodTableBuilder::MethodImplCompareSignatures( const MethodSignature &declSig(hDecl.GetMethodSignature()); const MethodSignature &implSig(hImpl.GetMethodSignature()); - if (!MethodSignature::SignaturesEquivalent(declSig, implSig)) + if (!MethodSignature::SignaturesEquivalent(declSig, implSig, allowCovariantReturn)) { LOG((LF_CLASSLOADER, LL_INFO1000, "BADSIG placing MethodImpl: %x\n", declSig.GetToken())); BuildMethodTableThrowException(COR_E_TYPELOAD, IDS_CLASSLOAD_MI_BADSIGNATURE, declSig.GetToken()); @@ -6379,6 +6480,7 @@ MethodTableBuilder::PlaceLocalDeclarationOnClass( MethodImplCompareSignatures( pDecl, pImpl, + FALSE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_LOCAL_METHOD_IMPL); /////////////////////////////// @@ -6450,6 +6552,7 @@ VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass( MethodImplCompareSignatures( pDecl, pImpl, + FALSE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL); /////////////////////////////// @@ -6552,6 +6655,7 @@ VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface( MethodImplCompareSignatures( hDecl, bmtMethodHandle(pImpl), + FALSE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL); /////////////////////////////// @@ -6600,6 +6704,7 @@ MethodTableBuilder::PlaceParentDeclarationOnClass( MethodImplCompareSignatures( pDecl, pImpl, + TRUE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_PARENT_METHOD_IMPL); //////////////////////////////// @@ -7230,7 +7335,7 @@ MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot( // Check to verify that the equivalent slot on the equivalent interface actually matches the method // on the current interface. If not, then the slot is not a match, and we should search other interfaces // for an implementation of the method. - if (!MethodSignature::SignaturesEquivalent(pCurItfMethod->GetMethodSignature(), parentImplementation.GetMethodSignature())) + if (!MethodSignature::SignaturesEquivalent(pCurItfMethod->GetMethodSignature(), parentImplementation.GetMethodSignature(), FALSE)) { continue; } diff --git a/src/coreclr/src/vm/methodtablebuilder.h b/src/coreclr/src/vm/methodtablebuilder.h index 7314c704a1142c..b4cbcdc5ed777e 100644 --- a/src/coreclr/src/vm/methodtablebuilder.h +++ b/src/coreclr/src/vm/methodtablebuilder.h @@ -809,7 +809,8 @@ class MethodTableBuilder static bool SignaturesEquivalent( const MethodSignature & sig1, - const MethodSignature & sig2); + const MethodSignature & sig2, + BOOL allowCovariantReturn); //----------------------------------------------------------------------------------------- // Returns true if the metadata signatures (PCCOR_SIGNATURE) are exactly equal. (No type equivalence permitted) @@ -1991,6 +1992,7 @@ class MethodTableBuilder // This is to detect situations where a methodimpl does not match any method on any equivalent interface. bool fThrowIfUnmatchedDuringInexactMethodImplProcessing; UINT32 interfaceEquivalenceSet;// Equivalence set in the interface map to examine + bool fRequiresCovariantReturnTypeChecking; static int __cdecl Compare(const void *elem1, const void *elem2); static BOOL Equal(const MethodImplTokenPair *elem1, const MethodImplTokenPair *elem2); }; @@ -2562,6 +2564,9 @@ class MethodTableBuilder mdToken* pDeclaration, // Method definition for Member BOOL fSameClass); // Does the declaration need to be in this class + BOOL + IsEligibleForCovariantReturns(mdToken methodDeclToken); + // -------------------------------------------------------------------------------------------- // Enumerates the method impl token pairs and resolves the impl tokens to mdtMethodDef // tokens, since we currently have the limitation that all impls are in the current class. @@ -2739,6 +2744,7 @@ class MethodTableBuilder MethodImplCompareSignatures( bmtMethodHandle hDecl, bmtMethodHandle hImpl, + BOOL allowCovariantReturn, DWORD dwConstraintErrorCode); // -------------------------------------------------------------------------------------------- diff --git a/src/coreclr/src/vm/runtimehandles.cpp b/src/coreclr/src/vm/runtimehandles.cpp index 2b4cad229bb447..a4846515f92c88 100644 --- a/src/coreclr/src/vm/runtimehandles.cpp +++ b/src/coreclr/src/vm/runtimehandles.cpp @@ -2169,7 +2169,8 @@ FCIMPL2(FC_BOOL_RET, SignatureNative::CompareSig, SignatureNative* pLhsUNSAFE, S { ret = MetaSig::CompareMethodSigs( gc.pLhs->GetCorSig(), gc.pLhs->GetCorSigSize(), gc.pLhs->GetModule(), NULL, - gc.pRhs->GetCorSig(), gc.pRhs->GetCorSigSize(), gc.pRhs->GetModule(), NULL); + gc.pRhs->GetCorSig(), gc.pRhs->GetCorSigSize(), gc.pRhs->GetModule(), NULL, + FALSE); } HELPER_METHOD_FRAME_END(); FC_RETURN_BOOL(ret); diff --git a/src/coreclr/src/vm/siginfo.cpp b/src/coreclr/src/vm/siginfo.cpp index dc21a23eac1eb5..1d3de2ba2107dc 100644 --- a/src/coreclr/src/vm/siginfo.cpp +++ b/src/coreclr/src/vm/siginfo.cpp @@ -713,7 +713,7 @@ static BOOL MethodDescMatchesSig(MethodDesc* pMD, PCCOR_SIGNATURE pSig, DWORD cS pMD->GetSig(&pSigOfMD, &cSigOfMD); return MetaSig::CompareMethodSigs(pSig, cSig, pModule, NULL, - pSigOfMD, cSigOfMD, pMD->GetModule(), NULL); + pSigOfMD, cSigOfMD, pMD->GetModule(), NULL, FALSE); } #endif // _DEBUG @@ -3007,7 +3007,7 @@ static BOOL CompareDelegatesForEquivalence(mdToken tk1, mdToken tk2, Module *pMo GetDelegateInvokeMethodSignature(tk1, pModule1, &cbSig1, &pSig1); GetDelegateInvokeMethodSignature(tk2, pModule2, &cbSig2, &pSig2); - return MetaSig::CompareMethodSigs(pSig1, cbSig1, pModule1, NULL, pSig2, cbSig2, pModule2, NULL, pVisited); + return MetaSig::CompareMethodSigs(pSig1, cbSig1, pModule1, NULL, pSig2, cbSig2, pModule2, NULL, FALSE, pVisited); } #endif // FEATURE_TYPEEQUIVALENCE @@ -3567,6 +3567,7 @@ BOOL CompareTypeTokens(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModu #pragma warning(push) #pragma warning(disable:21000) // Suppress PREFast warning about overly large function #endif + //--------------------------------------------------------------------------------------- // // Compare the next elements in two sigs. @@ -3698,7 +3699,7 @@ MetaSig::CompareElementType( // One type is already loaded, collect all the necessary information to identify the other type. if (Type1 == ELEMENT_TYPE_INTERNAL) { - IfFailThrow(CorSigUncompressPointer_EndPtr(pSig1, pEndSig1, (void **)&hInternal)); + IfFailThrow(CorSigUncompressPointer_EndPtr(pSig1, pEndSig1, (void**)&hInternal)); eOtherType = Type2; pOtherModule = pModule2; @@ -3734,9 +3735,8 @@ MetaSig::CompareElementType( { IfFailThrow(CorSigUncompressToken_EndPtr(pSig1, pEndSig1, &tkOther)); } - TypeHandle hOtherType; - hOtherType = ClassLoader::LoadTypeDefOrRefThrowing( + TypeHandle hOtherType = ClassLoader::LoadTypeDefOrRefThrowing( pOtherModule, tkOther, ClassLoader::ReturnNullIfNotFound, @@ -4237,7 +4237,7 @@ MetaSig::CompareMethodSigsNT( HRESULT hr = S_OK; EX_TRY { - if (CompareMethodSigs(pSignature1, cSig1, pModule1, pSubst1, pSignature2, cSig2, pModule2, pSubst2, pVisited)) + if (CompareMethodSigs(pSignature1, cSig1, pModule1, pSubst1, pSignature2, cSig2, pModule2, pSubst2, FALSE, pVisited)) hr = S_OK; else hr = S_FALSE; @@ -4262,6 +4262,7 @@ MetaSig::CompareMethodSigs( DWORD cSig2, Module * pModule2, const Substitution * pSubst2, + BOOL skipReturnTypeSig, TokenPairList * pVisited) //= NULL { CONTRACTL @@ -4356,8 +4357,20 @@ MetaSig::CompareMethodSigs( // This would be a breaking change to make this throw... see comment above _ASSERT(*pSig2 != ELEMENT_TYPE_SENTINEL); - // We are in bounds on both sides. Compare the element. - if (!CompareElementType( + if (i == 0 && skipReturnTypeSig) + { + SigPointer ptr1(pSig1, (DWORD)(pEndSig1 - pSig1)); + IfFailThrow(ptr1.SkipExactlyOne()); + pSig1 = ptr1.GetPtr(); + + SigPointer ptr2(pSig2, (DWORD)(pEndSig2 - pSig2)); + IfFailThrow(ptr2.SkipExactlyOne()); + pSig2 = ptr2.GetPtr(); + } + else + { + // We are in bounds on both sides. Compare the element. + if (!CompareElementType( pSig1, pSig2, pEndSig1, @@ -4367,8 +4380,9 @@ MetaSig::CompareMethodSigs( pSubst1, pSubst2, pVisited)) - { - return FALSE; + { + return FALSE; + } } } @@ -4382,7 +4396,19 @@ MetaSig::CompareMethodSigs( // do return type as well for (i = 0; i <= ArgCount1; i++) { - if (!CompareElementType( + if (i == 0 && skipReturnTypeSig) + { + SigPointer ptr1(pSig1, (DWORD)(pEndSig1 - pSig1)); + IfFailThrow(ptr1.SkipExactlyOne()); + pSig1 = ptr1.GetPtr(); + + SigPointer ptr2(pSig2, (DWORD)(pEndSig2 - pSig2)); + IfFailThrow(ptr2.SkipExactlyOne()); + pSig2 = ptr2.GetPtr(); + } + else + { + if (!CompareElementType( pSig1, pSig2, pEndSig1, @@ -4392,8 +4418,9 @@ MetaSig::CompareMethodSigs( pSubst1, pSubst2, pVisited)) - { - return FALSE; + { + return FALSE; + } } } @@ -4673,7 +4700,7 @@ BOOL MetaSig::CompareTypeDefOrRefOrSpec(Module *pModule1, mdToken tok1, ULONG cSig1,cSig2; IfFailThrow(pInternalImport1->GetTypeSpecFromToken(tok1, &pSig1, &cSig1)); IfFailThrow(pInternalImport2->GetTypeSpecFromToken(tok2, &pSig2, &cSig2)); - return MetaSig::CompareElementType(pSig1,pSig2,pSig1+cSig1,pSig2+cSig2,pModule1,pModule2,pSubst1,pSubst2,pVisited); + return MetaSig::CompareElementType(pSig1, pSig2, pSig1 + cSig1, pSig2 + cSig2, pModule1, pModule2, pSubst1, pSubst2, pVisited); } // MetaSig::CompareTypeDefOrRefOrSpec /* static */ @@ -5359,7 +5386,6 @@ void Substitution::DeleteChain() } #endif // #ifndef DACCESS_COMPILE - //--------------------------------------------------------------------------------------- // // static diff --git a/src/coreclr/src/vm/siginfo.hpp b/src/coreclr/src/vm/siginfo.hpp index e294239670520f..cdef8c2feb7e46 100644 --- a/src/coreclr/src/vm/siginfo.hpp +++ b/src/coreclr/src/vm/siginfo.hpp @@ -970,12 +970,12 @@ class MetaSig //------------------------------------------------------------------ CorElementType GetByRefType(TypeHandle* pTy) const; + //------------------------------------------------------------------ // Compare types in two signatures, first applying // - optional substitutions pSubst1 and pSubst2 // to class type parameters (E_T_VAR) in the respective signatures - static - BOOL - CompareElementType( + //------------------------------------------------------------------ + static BOOL CompareElementType( PCCOR_SIGNATURE & pSig1, PCCOR_SIGNATURE & pSig2, PCCOR_SIGNATURE pEndSig1, @@ -1002,15 +1002,16 @@ class MetaSig // Compare two complete method signatures, first applying optional substitutions pSubst1 and pSubst2 // to class type parameters (E_T_VAR) in the respective signatures static BOOL CompareMethodSigs( - PCCOR_SIGNATURE pSig1, - DWORD cSig1, - Module* pModule1, + PCCOR_SIGNATURE pSig1, + DWORD cSig1, + Module* pModule1, const Substitution* pSubst1, - PCCOR_SIGNATURE pSig2, - DWORD cSig2, - Module* pModule2, + PCCOR_SIGNATURE pSig2, + DWORD cSig2, + Module* pModule2, const Substitution* pSubst2, - TokenPairList *pVisited = NULL + BOOL skipReturnTypeSig, + TokenPairList* pVisited = NULL ); // Nonthrowing version of CompareMethodSigs diff --git a/src/coreclr/src/vm/typehandle.cpp b/src/coreclr/src/vm/typehandle.cpp index d9b1a9c2466177..2e19a3e5428e83 100644 --- a/src/coreclr/src/vm/typehandle.cpp +++ b/src/coreclr/src/vm/typehandle.cpp @@ -575,7 +575,7 @@ BOOL TypeHandle::IsBoxedAndCanCastTo(TypeHandle type, TypeHandlePairList *pPairL GC_TRIGGERS; INJECT_FAULT(COMPlusThrowOM()); - LOADS_TYPE(CLASS_DEPENDENCIES_LOADED); + LOADS_TYPE(CLASS_LOAD_EXACTPARENTS); // The caller should check for an exact match. // That will cover the cast of a (unboxed) valuetype to itself. @@ -622,7 +622,7 @@ BOOL TypeHandle::CanCastTo(TypeHandle type, TypeHandlePairList *pVisited) const MODE_ANY; INJECT_FAULT(COMPlusThrowOM()); - LOADS_TYPE(CLASS_DEPENDENCIES_LOADED); + LOADS_TYPE(CLASS_LOAD_EXACTPARENTS); } CONTRACTL_END diff --git a/src/coreclr/src/vm/wellknownattributes.h b/src/coreclr/src/vm/wellknownattributes.h index de71eb459f90cf..a853461b02147d 100644 --- a/src/coreclr/src/vm/wellknownattributes.h +++ b/src/coreclr/src/vm/wellknownattributes.h @@ -35,6 +35,7 @@ enum class WellKnownAttribute : DWORD UnmanagedFunctionPointer, ThreadStatic, WinRTMarshalingBehaviorAttribute, + PreserveBaseOverridesAttribute, CountOfWellKnownAttributes }; @@ -99,6 +100,8 @@ inline const char *GetWellKnownAttributeName(WellKnownAttribute attribute) return "System.ThreadStaticAttribute"; case WellKnownAttribute::WinRTMarshalingBehaviorAttribute: return "Windows.Foundation.Metadata.MarshalingBehaviorAttribute"; + case WellKnownAttribute::PreserveBaseOverridesAttribute: + return "System.Runtime.CompilerServices.PreserveBaseOverridesAttribute"; case WellKnownAttribute::CountOfWellKnownAttributes: default: break; // Silence compiler warnings diff --git a/src/coreclr/tests/issues.targets b/src/coreclr/tests/issues.targets index 2a2f6dc840cdbe..b3b6ef5e21caef 100644 --- a/src/coreclr/tests/issues.targets +++ b/src/coreclr/tests/issues.targets @@ -1622,6 +1622,9 @@ needs triage + + needs triage + needs triage diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnitTest.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnitTest.il new file mode 100644 index 00000000000000..5afa5155a755ab --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnitTest.il @@ -0,0 +1,1350 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly UnitTest { } + +// ======================================================================================== +// 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 { } +.class interface public auto ansi abstract IDictionary { } + +.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 implements IUnused1, IUnused2, class IGenRetType { } +.class interface public auto ansi abstract IGenDerive2 implements IUnused1, IUnused2, class IGenDerive1> { } +.class interface public auto ansi abstract IGenDerive3 implements IUnused1, IUnused2, class IGenDerive2 { } + +.class interface public auto ansi abstract INonGenericDerived1 implements IUnused1, IUnused2, class IGenRetType { } +.class interface public auto ansi abstract INonGenericDerived2 implements IUnused1, IUnused2, class INonGenericDerived1 { } +.class interface public auto ansi abstract INonGenericDerived3 implements IUnused1, IUnused2, class INonGenericDerived2 { } +.class interface public auto ansi abstract INonGenericDerived4 implements IUnused1, IUnused2, INonGenericDerived3 { } + +.class interface public auto ansi abstract IGenToNonGen1 implements IUnused1, IUnused2, IC { } +.class interface public auto ansi abstract IGenToNonGen2 implements IUnused1, IUnused2, class IGenToNonGen1> { } +.class interface public auto ansi abstract IGenToNonGen3 implements IUnused1, IUnused2, class IGenToNonGen2 { } + +.class interface public auto ansi abstract INonGenThroughGen1 implements IUnused1, IUnused2, IC { } +.class interface public auto ansi abstract INonGenThroughGen2 implements IUnused1, IUnused2, class INonGenThroughGen1> { } +.class interface public auto ansi abstract INonGenThroughGen3 implements IUnused1, IUnused2, class INonGenThroughGen2 { } +.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 implements IUnused1, IUnused2, class IGenToNonGen3 { } +.class public auto ansi beforefieldinit NonGenericDerived4 implements IUnused1, IUnused2, INonGenericDerived4 { } +.class public auto ansi beforefieldinit GenDerive3 implements IUnused1, IUnused2, class IGenDerive3 { } +.class public auto ansi beforefieldinit C implements IUnused1, IUnused2, IC { } +.class public auto ansi beforefieldinit GenRetType implements IUnused1, IUnused2, class IGenRetType { } + +.class public auto ansi beforefieldinit Base {} +.class public auto ansi beforefieldinit Derived extends class Base {} +.class public auto ansi beforefieldinit Derived2 extends class Base {} + +.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 overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 MyFuncCovariant(string& res) + { + ldarg.1 + ldstr "ICovariant GenBaseType.MyFuncCovariant()" + stind.ref + ldnull + ret + } + .method public hidebysig newslot virtual instance class IContravariant MyFuncContravariant(string& res) + { + ldarg.1 + ldstr "IContravariant 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 MyGenFunc(string& res) + { + ldarg.1 + ldstr "IGenRetType GenBaseType.MyGenFunc()" + stind.ref + ldnull + ret + } + .method public hidebysig newslot virtual instance class IGenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "IGenRetType> GenBaseType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IVariant> MultiLevelGenericVariantFunc(string&) + { + ldarg.1 + ldstr "IVariant> 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 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class INonGenThroughGen2 NonGenThroughGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IB class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "INonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IGenToNonGen1> GenToNonGen(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IB class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "IGenToNonGen1> GenMiddleType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class INonGenericDerived1 MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IGenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "INonGenericDerived1 GenMiddleType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IGenDerive1> MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IGenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "IGenDerive1> 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 extends class GenMiddleType +{ + .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::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "INonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IGenToNonGen3 GenToNonGen(string& res) + { + .override method instance class IB class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "IGenToNonGen3 TestType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class INonGenericDerived4 MyGenFunc(string& res) + { + .override method instance class IGenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "INonGenericDerived4 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IGenDerive3 MyGenFunc(string& res) + { + .override method instance class IGenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "IGenDerive3 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IGenRetType MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "IGenRetType 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::MyFunc(string& res) + ldarg.1 + ldstr "IC TestType.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class ICovariant MyFuncCovariant(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class ICovariant class GenBaseType::MyFuncCovariant(string& res) + ldarg.1 + ldstr "ICovariant TestType.MyFuncCovariant()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IContravariant MyFuncContravariant(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IContravariant class GenBaseType::MyFuncContravariant(string& res) + ldarg.1 + ldstr "IContravariant 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 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> 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 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 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 extends class GenTestType +{ + .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::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "class NonGenThroughGen4 GenMoreDerived.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGen(string& res) + { + .override method instance class IB class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "class GenToNonGen3 GenMoreDerived.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived4 MyGenFunc(string& res) + { + .override method instance class IGenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "class NonGenericDerived4 GenMoreDerived.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive3 MyGenFunc(string& res) + { + .override method instance class IGenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "class GenDerive3 GenMoreDerived.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType MyFunc(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "class GenRetType GenMoreDerived.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C MyFunc(string& res) + { + .override method instance class IB class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "class C GenMoreDerived.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class IVariant MultiLevelGenericVariantFunc(string&) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IVariant> class GenBaseType::MultiLevelGenericVariantFunc(string&) + ldarg.1 + ldstr "class IVariant 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 extends class GenMoreDerived +{ + .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::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 extends class GenTestType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class INonGenThroughGen2 NonGenThroughGenFunc(string& res) + { + .override method instance class IB class GenBaseType::NonGenThroughGenFunc(string& res) + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Invalid3 extends class GenTestType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class IVariant MultiLevelGenericVariantFunc(string&) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class IVariant> class GenBaseType::MultiLevelGenericVariantFunc(string&) + ldnull + 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 GenTestType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // And verify that the override on GetTestType is the one that executes + + .method public static bool RunTest1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class IGenRetType class GenTestType::MyFunc(string&) + pop + + ldstr "IGenRetType TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class IC class GenTestType::MyFunc(string&) + pop + + ldstr "IC TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class IGenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class IGenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class IGenDerive3 class GenTestType::MyGenFunc(string&) + pop + + ldstr "IGenDerive3 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class IGenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class INonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class INonGenericDerived4 class GenTestType::MyGenFunc(string&) + pop + + ldstr "INonGenericDerived4 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest5() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class IGenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class IGenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + ldstr "IGenToNonGen3 TestType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest6() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class INonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class INonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + pop + + ldstr "INonGenThroughGen4 TestType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest7() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class ICovariant class GenBaseType::MyFuncCovariant(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class ICovariant class GenTestType::MyFuncCovariant(string&) + pop + + ldstr "ICovariant TestType.MyFuncCovariant()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest8() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class IContravariant class GenBaseType::MyFuncContravariant(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class IContravariant class GenTestType::MyFuncContravariant(string&) + pop + + ldstr "IContravariant TestType.MyFuncContravariant()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest9() noinlining + { + .locals init (string res1) + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance class IVariant class GenMoreDerived::MultiLevelGenericVariantFunc(string&) + pop + + ldstr "class IVariant GenMoreDerived.MultiLevelGenericVariantFunc()" + ldloc.0 + ldnull + ldnull + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + + ret + } + + + + // ============== Test using GenMiddleType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns + // And verify that the override on GenMiddleType is the one that executes + + .method public static bool RunTest_Middle1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class IGenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class IGenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + ldstr "IGenDerive1> GenMiddleType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class IGenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class INonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + ldstr "INonGenericDerived1 GenMiddleType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class IGenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + ldstr "IGenToNonGen1> GenMiddleType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class INonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + ldstr "INonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ============== Test using GenMoreDerived ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // 4) The signature from GenMoreDerived with covariant returns + // And verify that the override on GenMoreDerived is the one that executes + + .method public static bool RunTest_MoreDerived1() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 1 + callvirt instance class IGenRetType class GenTestType::MyFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 2 + callvirt instance class GenRetType class GenMoreDerived::MyFunc(string&) + pop + + ldstr "class GenRetType GenMoreDerived.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_MoreDerived2() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 1 + callvirt instance class IC class GenTestType::MyFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 2 + callvirt instance class C class GenMoreDerived::MyFunc(string&) + pop + + ldstr "class C GenMoreDerived.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_MoreDerived3() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance class IGenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 1 + callvirt instance class IGenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 2 + callvirt instance class IGenDerive3 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 3 + callvirt instance class GenDerive3 class GenMoreDerived::MyGenFunc(string&) + pop + + ldstr "class GenDerive3 GenMoreDerived.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_MoreDerived4() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance class IGenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 1 + callvirt instance class INonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 2 + callvirt instance class INonGenericDerived4 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 3 + callvirt instance class NonGenericDerived4 class GenMoreDerived::MyGenFunc(string&) + pop + + ldstr "class NonGenericDerived4 GenMoreDerived.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_MoreDerived5() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 1 + callvirt instance class IGenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 2 + callvirt instance class IGenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 3 + callvirt instance class GenToNonGen3 class GenMoreDerived::GenToNonGen(string&) + pop + + ldstr "class GenToNonGen3 GenMoreDerived.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_MoreDerived6() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 0 + callvirt instance class IB class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 1 + callvirt instance class INonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 2 + callvirt instance class INonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenMoreDerived::.ctor() + ldloca.s 3 + callvirt instance class NonGenThroughGen4 class GenMoreDerived::NonGenThroughGenFunc(string&) + pop + + ldstr "class NonGenThroughGen4 GenMoreDerived.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + + // ===================================================================================== // + + .method public static void RunTest_Invalid1() noinlining + { + newobj instance void class Invalid1::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest_Invalid2() noinlining + { + newobj instance void class Invalid2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest_Invalid3() noinlining + { + newobj instance void class Invalid3::.ctor() + callvirt instance class IVariant class Invalid3::MultiLevelGenericVariantFunc() + pop + ret + } + // ===================================================================================== // + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + T1: + call bool CMain::RunTest1() + brtrue.s T2 + ldc.i4.0 + stloc.0 + + T2: + call bool CMain::RunTest2() + brtrue.s T3 + ldc.i4.0 + stloc.0 + + T3: + call bool CMain::RunTest3() + brtrue.s T4 + ldc.i4.0 + stloc.0 + + T4: + call bool CMain::RunTest4() + brtrue.s T5 + ldc.i4.0 + stloc.0 + + T5: + call bool CMain::RunTest5() + brtrue.s T6 + ldc.i4.0 + stloc.0 + + T6: + call bool CMain::RunTest6() + brtrue.s T7 + ldc.i4.0 + stloc.0 + + T7: + call bool CMain::RunTest7() + brtrue.s T8 + ldc.i4.0 + stloc.0 + + T8: + call bool CMain::RunTest8() + brtrue.s T9 + ldc.i4.0 + stloc.0 + + T9: + call bool CMain::RunTest9() + brtrue.s M1 + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + M1: + call bool CMain::RunTest_Middle1() + brtrue.s M2 + ldc.i4.0 + stloc.0 + + M2: + call bool CMain::RunTest_Middle2() + brtrue.s M3 + ldc.i4.0 + stloc.0 + + M3: + call bool CMain::RunTest_Middle3() + brtrue.s M4 + ldc.i4.0 + stloc.0 + + M4: + call bool CMain::RunTest_Middle4() + brtrue.s MOREDERIVED1 + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + MOREDERIVED1: + call bool CMain::RunTest_MoreDerived1() + brtrue.s MOREDERIVED2 + ldc.i4.0 + stloc.0 + + MOREDERIVED2: + call bool CMain::RunTest_MoreDerived2() + brtrue.s MOREDERIVED3 + ldc.i4.0 + stloc.0 + + MOREDERIVED3: + call bool CMain::RunTest_MoreDerived3() + brtrue.s MOREDERIVED4 + ldc.i4.0 + stloc.0 + + MOREDERIVED4: + call bool CMain::RunTest_MoreDerived4() + brtrue.s MOREDERIVED5 + ldc.i4.0 + stloc.0 + + MOREDERIVED5: + call bool CMain::RunTest_MoreDerived5() + brtrue.s MOREDERIVED6 + ldc.i4.0 + stloc.0 + + MOREDERIVED6: + call bool CMain::RunTest_MoreDerived6() + brtrue.s INVALID1 + 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 + + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnitTest.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnitTest.ilproj new file mode 100644 index 00000000000000..921b93a2356ead --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnitTest.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario1.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario1.il new file mode 100644 index 00000000000000..e87a43202c7ca1 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario1.il @@ -0,0 +1,319 @@ +// 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. + +// Test to validate the current unsupported scenarios will throw a TypeLoadException. +// Scenario being tested here: covariant returns on MethodImpls to interface methods +// implemented by classes + +.assembly extern System.Console { } +.assembly extern mscorlib { } +.assembly UnsupportedScenario2 { } + +.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 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Dictionary { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { + .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 GenToNonGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { + .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 interface public auto ansi abstract IBaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenericDerived4 GenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenDerive3 GenFunc() + { + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test1 implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class B NonGenThroughGenOverride() + { + .override method instance class NonGenThroughGen4 class IBaseTest::NonGenThroughGenFunc() + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Test2 implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class B GenToNonGenOverride() + { + .override method instance class GenToNonGen3 class IBaseTest::GenToNonGenFunc() + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Test3 implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType NewGenFunc1() + { + .override method instance class NonGenericDerived4 class IBaseTest::GenFunc() + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Test4 implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType> NewGenFunc2() + { + .override method instance class GenDerive3 class IBaseTest::GenFunc() + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Test5 implements class IBaseTest +{ + .method public hidebysig newslot virtual instance object NewFunc1() + { + .override method instance class GenRetType class IBaseTest::MyFunc() + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static void RunTest1() noinlining + { + newobj instance void class Test1::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + newobj instance void class Test2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + newobj instance void class Test3::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + newobj instance void class Test4::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + newobj instance void class Test5::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init (bool V_0) + ldc.i4.1 + stloc.0 + + T1: + .try + { + call void CMain::RunTest1() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test1." + call void [System.Console]System.Console::WriteLine(string) + leave.s T2 + } + 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 T2 + } + + T2: + .try + { + call void CMain::RunTest2() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test2." + call void [System.Console]System.Console::WriteLine(string) + leave.s T3 + } + 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 T3 + } + + T3: + .try + { + call void CMain::RunTest3() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test3." + call void [System.Console]System.Console::WriteLine(string) + leave.s T4 + } + 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 T4 + } + + T4: + .try + { + call void CMain::RunTest4() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test4." + call void [System.Console]System.Console::WriteLine(string) + leave.s T5 + } + 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 T5 + } + + T5: + .try + { + call void CMain::RunTest5() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test5." + 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 + + ldc.i4.s 101 + ret + + PASS: + ldstr "Test PASSED" + call void [System.Console]System.Console::WriteLine(string) + ldc.i4.s 100 + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method CMain::.ctor + +} // end of class CMain diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario1.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario1.ilproj new file mode 100644 index 00000000000000..01b74f71e93043 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario1.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario2.il new file mode 100644 index 00000000000000..d87cd8bb22ea5e --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario2.il @@ -0,0 +1,319 @@ +// 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. + +// Test to validate the current unsupported scenarios will throw a TypeLoadException. +// Scenario being tested here: covariant returns on default interface methods. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly UnsupportedScenario2 { } + +.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 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Dictionary { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { + .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 GenToNonGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { + .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 interface public auto ansi abstract BaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenericDerived4 GenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenDerive3 GenFunc() + { + ldnull + ret + } +} + +.class interface public auto ansi abstract Test1 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class B NonGenThroughGenOverride() + { + .override method instance class NonGenThroughGen4 class BaseTest::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class interface public auto ansi abstract Test2 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class B GenToNonGenOverride() + { + .override method instance class GenToNonGen3 class BaseTest::GenToNonGenFunc() + ldnull + ret + } +} + +.class interface public auto ansi abstract Test3 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType NewGenFunc1() + { + .override method instance class NonGenericDerived4 class BaseTest::GenFunc() + ldnull + ret + } +} + +.class interface public auto ansi abstract Test4 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType> NewGenFunc2() + { + .override method instance class GenDerive3 class BaseTest::GenFunc() + ldnull + ret + } +} + +.class interface public auto ansi abstract Test5 implements class BaseTest +{ + .method public hidebysig newslot virtual instance object NewFunc1() + { + .override method instance class GenRetType class BaseTest::MyFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static void RunTest1() noinlining + { + ldtoken class Test1 + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + ldtoken class Test2 + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + ldtoken class Test3 + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + ldtoken class Test4 + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + ldtoken class Test5 + call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init (bool V_0) + ldc.i4.1 + stloc.0 + + T1: + .try + { + call void CMain::RunTest1() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test1." + call void [System.Console]System.Console::WriteLine(string) + leave.s T2 + } + 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 T2 + } + + T2: + .try + { + call void CMain::RunTest2() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test2." + call void [System.Console]System.Console::WriteLine(string) + leave.s T3 + } + 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 T3 + } + + T3: + .try + { + call void CMain::RunTest3() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test3." + call void [System.Console]System.Console::WriteLine(string) + leave.s T4 + } + 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 T4 + } + + T4: + .try + { + call void CMain::RunTest4() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test4." + call void [System.Console]System.Console::WriteLine(string) + leave.s T5 + } + 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 T5 + } + + T5: + .try + { + call void CMain::RunTest5() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test5." + 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 + + ldc.i4.s 101 + ret + + PASS: + ldstr "Test PASSED" + call void [System.Console]System.Console::WriteLine(string) + ldc.i4.s 100 + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method CMain::.ctor + +} // end of class CMain diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario2.ilproj new file mode 100644 index 00000000000000..7e95e6b070bbcc --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario2.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario3.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario3.il new file mode 100644 index 00000000000000..78a75da9080680 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario3.il @@ -0,0 +1,346 @@ +// 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. + +// Test to validate the current unsupported scenarios will throw a TypeLoadException. +// Scenario being tested here: covariant returns on MethodImpls to interface methods +// implemented by structs + +.assembly extern System.Console { } +.assembly extern mscorlib { } +.assembly UnsupportedScenario3 { } + +.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 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Dictionary { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { + .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 GenToNonGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { + .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 interface public auto ansi abstract IBaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenericDerived4 GenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenDerive3 GenFunc() + { + ldnull + ret + } +} + +.class public sealed auto ansi Test1 + extends [mscorlib]System.ValueType + implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class B NonGenThroughGenOverride() + { + .override method instance class NonGenThroughGen4 class IBaseTest::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class public sealed auto ansi Test2 + extends [mscorlib]System.ValueType + implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class B GenToNonGenOverride() + { + .override method instance class GenToNonGen3 class IBaseTest::GenToNonGenFunc() + ldnull + ret + } +} + +.class public sealed auto ansi Test3 + extends [mscorlib]System.ValueType + implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType NewGenFunc1() + { + .override method instance class NonGenericDerived4 class IBaseTest::GenFunc() + ldnull + ret + } +} + +.class public sealed auto ansi Test4 + extends [mscorlib]System.ValueType + implements class IBaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType> NewGenFunc2() + { + .override method instance class GenDerive3 class IBaseTest::GenFunc() + ldnull + ret + } +} + +.class public sealed auto ansi Test5 + extends [mscorlib]System.ValueType + implements class IBaseTest +{ + .method public hidebysig newslot virtual instance object NewFunc1() + { + .override method instance class GenRetType class IBaseTest::MyFunc() + ldnull + ret + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static void RunTest1() noinlining + { + .locals init (valuetype Test1) + ldloca.s 0 + initobj valuetype Test1 + ldloc.0 + box valuetype Test1 + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + .locals init (valuetype Test2) + ldloca.s 0 + initobj valuetype Test2 + ldloc.0 + box valuetype Test2 + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + .locals init (valuetype Test3) + ldloca.s 0 + initobj valuetype Test3 + ldloc.0 + box valuetype Test3 + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + .locals init (valuetype Test4) + ldloca.s 0 + initobj valuetype Test4 + ldloc.0 + box valuetype Test4 + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + .locals init (valuetype Test5) + ldloca.s 0 + initobj valuetype Test5 + ldloc.0 + box valuetype Test5 + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init (bool V_0) + ldc.i4.1 + stloc.0 + + T1: + .try + { + call void CMain::RunTest1() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test1." + call void [System.Console]System.Console::WriteLine(string) + leave.s T2 + } + 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 T2 + } + + T2: + .try + { + call void CMain::RunTest2() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test2." + call void [System.Console]System.Console::WriteLine(string) + leave.s T3 + } + 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 T3 + } + + T3: + .try + { + call void CMain::RunTest3() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test3." + call void [System.Console]System.Console::WriteLine(string) + leave.s T4 + } + 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 T4 + } + + T4: + .try + { + call void CMain::RunTest4() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test4." + call void [System.Console]System.Console::WriteLine(string) + leave.s T5 + } + 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 T5 + } + + T5: + .try + { + call void CMain::RunTest5() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test5." + 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 + + ldc.i4.s 101 + ret + + PASS: + ldstr "Test PASSED" + call void [System.Console]System.Console::WriteLine(string) + ldc.i4.s 100 + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method CMain::.ctor + +} // end of class CMain diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario3.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario3.ilproj new file mode 100644 index 00000000000000..a182efdb3bb629 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Interfaces/UnsupportedScenario3.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/ImplicitOverrideSameSigAsDecl.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/ImplicitOverrideSameSigAsDecl.il new file mode 100644 index 00000000000000..facd99dbe81f66 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/ImplicitOverrideSameSigAsDecl.il @@ -0,0 +1,451 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly ImplicitOverrideSameSigAsDecl { } + +// ======================================================================================== +// 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 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Dictionary { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { + .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 GenToNonGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { + .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 } +} + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(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(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(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType>::.ctor() + ret + } +} + +// ======================================================================================== +// SECOND LAYER type: overrides all virtuals on GenBaseType using MethodImpls with +// covariant return types (more derived return types) +// ======================================================================================== + +.class public auto ansi beforefieldinit GenTestType extends class GenBaseType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenOverride(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenOverride(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 TestType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive3 NewGenFunc2(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 TestType.NewGenFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType NewFunc1(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenRetType TestType.NewFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C NewFunc2(string& res) + { + .override method instance class B class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "C TestType.NewFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +// ======================================================================================== +// THIRD LAYER INVALID types: implicitly override the virtual methods on GenBaseType, using +// the same signature as GenBaseType, and are expected to throw TypeLoadExceptions on load +// because the return types here are not compatible with the return types used on GenTestType +// ======================================================================================== + +.class public auto ansi beforefieldinit Invalid1 extends class GenTestType +{ + .method public hidebysig virtual instance object MyFunc(string& res) + { + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid2 extends class GenTestType +{ + .method public hidebysig virtual instance class B MyFunc(string& res) + { + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid3 extends class GenTestType +{ + .method public hidebysig virtual instance class B GenToNonGen(string& res) + { + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid4 extends class GenTestType +{ + .method public hidebysig virtual instance class B NonGenThroughGenFunc(string& res) + { + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid5 extends class GenTestType +{ + .method public hidebysig virtual instance class GenRetType MyGenFunc(string& res) + { + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid6 extends class GenTestType +{ + .method public hidebysig virtual instance class GenRetType> MyGenFunc(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 public static void RunTest1() noinlining + { + newobj instance void class Invalid1::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + newobj instance void class Invalid2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + newobj instance void class Invalid3::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + newobj instance void class Invalid4::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + newobj instance void class Invalid5::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest6() noinlining + { + newobj instance void class Invalid6::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init (bool V_0) + ldc.i4.1 + stloc.0 + + T1: + .try + { + call void CMain::RunTest1() + 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 T2 + } + 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 T2 + } + + T2: + .try + { + call void CMain::RunTest2() + 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 T3 + } + 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 T3 + } + + T3: + .try + { + call void CMain::RunTest3() + 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 T4 + } + 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 T4 + } + + T4: + .try + { + call void CMain::RunTest4() + 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 T5 + } + 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 T5 + } + + T5: + .try + { + call void CMain::RunTest5() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid5." + call void [System.Console]System.Console::WriteLine(string) + leave.s T6 + } + 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 T6 + } + + T6: + .try + { + call void CMain::RunTest6() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid6." + 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 + + ldc.i4.s 101 + ret + + PASS: + ldstr "Test PASSED" + call void [System.Console]System.Console::WriteLine(string) + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/ImplicitOverrideSameSigAsDecl.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/ImplicitOverrideSameSigAsDecl.ilproj new file mode 100644 index 00000000000000..20cae0e097a067 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/ImplicitOverrideSameSigAsDecl.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/OverrideSameSigAsDecl.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/OverrideSameSigAsDecl.il new file mode 100644 index 00000000000000..4d497eef358e2a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/OverrideSameSigAsDecl.il @@ -0,0 +1,483 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly OverrideSameSigAsDecl { } + +// ======================================================================================== +// 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 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Dictionary { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { + .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 GenToNonGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { + .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 } +} + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(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(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(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType>::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType TestNonGenericDerived(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== +// SECOND LAYER type: overrides all virtuals on GenBaseType using MethodImpls with +// covariant return types (more derived return types) +// ======================================================================================== + +.class public auto ansi beforefieldinit GenTestType extends class GenBaseType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenOverride(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenOverride(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 TestType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive3 NewGenFunc2(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 TestType.NewGenFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType NewFunc1(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenRetType TestType.NewFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C NewFunc2(string& res) + { + .override method instance class B class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "C TestType.NewFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenBaseType::.ctor() + ret + } +} + +// ======================================================================================== +// THIRD LAYER INVALID types: explicitly override the virtual methods on GenBaseType, using +// the same signature as GenBaseType, and are expected to throw TypeLoadExceptions on load +// because the return types here are not compatible with the return types used on GenTestType +// ======================================================================================== + +.class public auto ansi beforefieldinit Invalid1 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class B NonGenThroughGenOverride_Invalid(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Invalid2 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class B GenToNonGenOverride_Invalid(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Invalid3 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class GenRetType NewGenFunc1_Invalid(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Invalid4 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class GenRetType> NewGenFunc2_Invalid(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Invalid5 extends class GenTestType +{ + .method public hidebysig newslot virtual instance object NewFunc1_Invalid(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit Invalid6 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class B NewFunc2_Invalid(string& res) + { + .override method instance class B class GenBaseType::MyFunc(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 public static void RunTest1() noinlining + { + newobj instance void class Invalid1::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + newobj instance void class Invalid2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + newobj instance void class Invalid3::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + newobj instance void class Invalid4::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + newobj instance void class Invalid5::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest6() noinlining + { + newobj instance void class Invalid6::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init (bool V_0) + ldc.i4.1 + stloc.0 + + T1: + .try + { + call void CMain::RunTest1() + 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 T2 + } + 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 T2 + } + + T2: + .try + { + call void CMain::RunTest2() + 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 T3 + } + 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 T3 + } + + T3: + .try + { + call void CMain::RunTest3() + 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 T4 + } + 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 T4 + } + + T4: + .try + { + call void CMain::RunTest4() + 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 T5 + } + 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 T5 + } + + T5: + .try + { + call void CMain::RunTest5() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid5." + call void [System.Console]System.Console::WriteLine(string) + leave.s T6 + } + 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 T6 + } + + T6: + .try + { + call void CMain::RunTest6() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Invalid6." + 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 + + ldc.i4.s 101 + ret + + PASS: + ldstr "Test PASSED" + call void [System.Console]System.Console::WriteLine(string) + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/OverrideSameSigAsDecl.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/OverrideSameSigAsDecl.ilproj new file mode 100644 index 00000000000000..7832fd86e93975 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/ReturnTypeValidation/OverrideSameSigAsDecl.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Structs/IncompatibleOverride.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Structs/IncompatibleOverride.il new file mode 100644 index 00000000000000..8687088b3b1287 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Structs/IncompatibleOverride.il @@ -0,0 +1,344 @@ +// 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. + +// +// Invalid scenario verification: overriding a base type method returning an interface type +// with a MethodImpl that returns a struct implementing that interface should throw: +// struct is castable to the interface it implements, but not compatible with it. +// + +.assembly extern System.Console { } +.assembly extern mscorlib { } +.assembly IncompatibleOverride { } + + +// ======================================================================================== +// Types that will be used as return types on the various methods +// ======================================================================================== + +.class interface public auto ansi abstract IA { } +.class interface public auto ansi abstract IGenRetType { } +.class interface public auto ansi abstract IDictionary { } + +.class interface public auto ansi abstract IB implements IA { } +.class interface public auto ansi abstract IGenDerive implements class IGenRetType { } + +// Structs implementing the interfaces +.class public sealed auto ansi A extends [mscorlib]System.ValueType + implements IA { } + +.class public sealed auto ansi B extends [mscorlib]System.ValueType + implements IB { } + +.class public sealed auto ansi RetType extends [mscorlib]System.ValueType + implements class IGenRetType { } + +.class public sealed auto ansi DerivedRetType extends [mscorlib]System.ValueType + implements class IGenDerive { } + +.class public sealed auto ansi GenRetType extends [mscorlib]System.ValueType + implements class IGenRetType> { } + +.class public sealed auto ansi DerivedGenRetType extends [mscorlib]System.ValueType + implements class IGenDerive> { } + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class IA NonGen(string& res) + { + ldarg.1 + ldstr "IA GenBaseType.NonGen()" + stind.ref + ldnull + ret + } + .method public hidebysig newslot virtual instance class IGenRetType GenFunc(string& res) + { + ldarg.1 + ldstr "IGenRetType GenBaseType.GenFunc()" + stind.ref + ldnull + ret + } + .method public hidebysig newslot virtual instance class IGenRetType> GenFunc(string& res) + { + ldarg.1 + ldstr "IGenRetType> GenBaseType.GenFunc()" + stind.ref + ldnull + ret + } +} + +// ======================================================================================== +// INVALID TYPES: override base type methods and return structs implementing the return type +// interfaces of the overridden methods. +// ======================================================================================== + + +.class public auto ansi beforefieldinit Invalid1 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance valuetype A NonGen(string& res) + { + .override method instance class IA class GenBaseType::NonGen(string& res) + .locals ( valuetype A ) + ldloc.0 + ret + } +} + +.class public auto ansi beforefieldinit Invalid2 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance valuetype B NonGen(string& res) + { + .override method instance class IA class GenBaseType::NonGen(string& res) + .locals ( valuetype B ) + ldloc.0 + ret + } +} + +.class public auto ansi beforefieldinit Invalid3 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance valuetype RetType GenFunc(string& res) + { + .override method instance class IGenRetType class GenBaseType::GenFunc(string& res) + .locals ( valuetype RetType ) + ldloc.0 + ret + } +} + +.class public auto ansi beforefieldinit Invalid4 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance valuetype DerivedRetType GenFunc(string& res) + { + .override method instance class IGenRetType class GenBaseType::GenFunc(string& res) + .locals ( valuetype DerivedRetType ) + ldloc.0 + ret + } +} + +.class public auto ansi beforefieldinit Invalid5 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance valuetype GenRetType GenFunc(string& res) + { + .override method instance class IGenRetType> class GenBaseType::GenFunc(string& res) + .locals ( valuetype GenRetType ) + ldloc.0 + ret + } +} + +.class public auto ansi beforefieldinit Invalid6 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance valuetype DerivedGenRetType GenFunc(string& res) + { + .override method instance class IGenRetType> class GenBaseType::GenFunc(string& res) + .locals ( valuetype DerivedGenRetType ) + ldloc.0 + ret + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static void RunTest1() noinlining + { + newobj instance void class Invalid1::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + newobj instance void class Invalid2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + newobj instance void class Invalid3::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + newobj instance void class Invalid4::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + newobj instance void class Invalid5::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest6() noinlining + { + newobj instance void class Invalid6::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init (bool V_0) + ldc.i4.1 + stloc.0 + + T1: + .try + { + call void CMain::RunTest1() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test1." + call void [System.Console]System.Console::WriteLine(string) + leave.s T2 + } + 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 T2 + } + + T2: + .try + { + call void CMain::RunTest2() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test2." + call void [System.Console]System.Console::WriteLine(string) + leave.s T3 + } + 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 T3 + } + + T3: + .try + { + call void CMain::RunTest3() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test3." + call void [System.Console]System.Console::WriteLine(string) + leave.s T4 + } + 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 T4 + } + + T4: + .try + { + call void CMain::RunTest4() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test4." + call void [System.Console]System.Console::WriteLine(string) + leave.s T5 + } + 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 T5 + } + + T5: + .try + { + call void CMain::RunTest5() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test5." + call void [System.Console]System.Console::WriteLine(string) + leave.s T6 + } + 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 T6 + } + + T6: + .try + { + call void CMain::RunTest6() + ldc.i4.0 + stloc.0 + ldstr "FAIL: did not catch expected TypeLoadException when loading Test5." + 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 + + ldc.i4.s 101 + ret + + PASS: + ldstr "Test PASSED" + call void [System.Console]System.Console::WriteLine(string) + ldc.i4.s 100 + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method CMain::.ctor + +} // end of class CMain diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Structs/IncompatibleOverride.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Structs/IncompatibleOverride.ilproj new file mode 100644 index 00000000000000..cc3de09a7be488 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Structs/IncompatibleOverride.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/AttributeTesting.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/AttributeTesting.il new file mode 100644 index 00000000000000..da7e5144dd925d --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/AttributeTesting.il @@ -0,0 +1,1281 @@ +// 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. + +// This test validates the behavior in the presence/absence of the PreserveBaseOverridesAttribute. +// Each test scenario will have 3 layers of type inheritance (T1,T2,T3), and we test the following scenarios: +// +// Scenario A: Attribute placed T1's MethodDecl (attribute treated as NOP - only applicable to MethodImpls) +// ============================================================================== +// Scenario A.1: T2 explicitly overrides T1's, T3 explicitly overrides T1's MethodDecl +// Scenario A.2: T2 explicitly overrides T1's, T3 explicitly overrides T2's MethodImpl +// Scenario A.3: T2 explicitly overrides T1's, T3 implicitly overrides T1's MethodDecl +// Scenario A.4: T2 explicitly overrides T1's, T3 implicitly overrides T2's MethodImpl +// Scenario A.5: T2 implicitly overrides T1's, T3 explicitly overrides T1's method +// Scenario A.6: T2 implicitly overrides T1's, T3 explicitly overrides T2's method +// Scenario A.7: T2 implicitly overrides T1's, T3 implicitly overrides T1/T2's method +// +// SCENARIO B: T2 has MethodImpl that overrides T1's MethodDecl, WITHOUT any attribute +// ============================================================================== +// Scenario B.1: T3 explicitly overrides T1's MethodDecl +// Scenario B.2: T3 explicitly overrides T2's MethodImpl +// Scenario B.3: T3 implicitly overrides T1's MethodDecl +// Scenario B.4: T3 implicitly overrides T2's MethodImpl +// +// SCENARIO C: T2 has MethodImpl that overrides T1's MethodDecl, WITH the attribute +// ============================================================================== +// Scenario C.1: T3 explicitly overrides T1's MethodDecl +// Scenario C.2: T3 explicitly overrides T2's MethodImpl +// Scenario C.3: T3 implicitly overrides T1's MethodDecl +// Scenario C.4: T3 implicitly overrides T2's MethodImpl +// +// SCENARIO D: T2 implicitly overrides T1's method, WITH the attribute (Attribute treated as NOP) +// ============================================================================== +// Scenario D.1: T3 explicitly overrides T1's method +// Scenario D.2: T3 explicitly overrides T2's method +// Scenario D.3: T3 implicitly overrides T1/T2's method +// +// SCENARIO E: T2 implicitly overrides T1's method, WITHOUT the attribute +// ============================================================================== +// Scenario E.1: T3 explicitly overrides T1's method +// Scenario E.2: T3 explicitly overrides T2's method +// Scenario E.3: T3 implicitly overrides T1/T2's method +// + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly AttributeTesting { } + + +// Scenario A +.namespace A +{ + .class public auto ansi beforefieldinit T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance string Func1() + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + ldstr "T1" + ret + } + } + .class public auto ansi beforefieldinit T2Exp extends A.T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func2() + { + .override method instance string class A.T1::Func1() + ldstr "T2" + ret + } + } + .class public auto ansi beforefieldinit T2Imp extends A.T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T2" + ret + } + } + + // Scenario A.1: T2 explicitly overrides T1's, T3 explicitly overrides T1's MethodDecl + .class public auto ansi beforefieldinit T3_1 extends A.T2Exp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class A.T1::Func1() + ldstr "T3" + ret + } + } + // Scenario A.2: T2 explicitly overrides T1's, T3 explicitly overrides T2's MethodImpl + .class public auto ansi beforefieldinit T3_2 extends A.T2Exp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class A.T2Exp::Func2() + ldstr "T3" + ret + } + } + + // Scenario A.3: T2 explicitly overrides T1's, T3 implicitly overrides T1's MethodDecl + .class public auto ansi beforefieldinit T3_3 extends A.T2Exp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T3" + ret + } + } + + // Scenario A.4: T2 explicitly overrides T1's, T3 implicitly overrides T2's MethodImpl + .class public auto ansi beforefieldinit T3_4 extends A.T2Exp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func2() + { + ldstr "T3" + ret + } + } + + // Scenario A.5: T2 implicitly overrides T1's, T3 explicitly overrides T1's method + .class public auto ansi beforefieldinit T3_5 extends A.T2Imp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class A.T1::Func1() + ldstr "T3" + ret + } + } + + // Scenario A.6: T2 implicitly overrides T1's, T3 explicitly overrides T2's method + .class public auto ansi beforefieldinit T3_6 extends A.T2Imp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class A.T2Imp::Func1() + ldstr "T3" + ret + } + } + + // Scenario A.7: T2 implicitly overrides T1's, T3 implicitly overrides T1/T2's method + .class public auto ansi beforefieldinit T3_7 extends A.T2Imp + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T3" + ret + } + } +} + +// Scenario B +.namespace B +{ + .class public auto ansi beforefieldinit T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func1() + { + ldstr "T1" + ret + } + } + .class public auto ansi beforefieldinit T2 extends B.T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func2() + { + .override method instance string class B.T1::Func1() + ldstr "T2" + ret + } + } + + // Scenario B.1: T3 explicitly overrides T1's MethodDecl + .class public auto ansi beforefieldinit T3_1 extends B.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class B.T1::Func1() + ldstr "T3" + ret + } + } + + // Scenario B.2: T3 explicitly overrides T2's MethodImpl + .class public auto ansi beforefieldinit T3_2 extends B.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class B.T2::Func2() + ldstr "T3" + ret + } + } + + // Scenario B.3: T3 implicitly overrides T1's MethodDecl + .class public auto ansi beforefieldinit T3_3 extends B.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T3" + ret + } + } + + // Scenario B.4: T3 implicitly overrides T2's MethodImpl + .class public auto ansi beforefieldinit T3_4 extends B.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func2() + { + ldstr "T3" + ret + } + } +} + +// Scenario C +.namespace C +{ + .class public auto ansi beforefieldinit T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func1() + { + ldstr "T1" + ret + } + } + .class public auto ansi beforefieldinit T2 extends C.T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func2() + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance string class C.T1::Func1() + ldstr "T2" + ret + } + } + + // Scenario C.1: T3 explicitly overrides T1's MethodDecl + .class public auto ansi beforefieldinit T3_1 extends C.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class C.T1::Func1() + ldstr "T3" + ret + } + } + + // Scenario C.2: T3 explicitly overrides T2's MethodImpl + .class public auto ansi beforefieldinit T3_2 extends C.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class C.T2::Func2() + ldstr "T3" + ret + } + } + + // Scenario C.3: T3 implicitly overrides T1's MethodDecl + .class public auto ansi beforefieldinit T3_3 extends C.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T3" + ret + } + } + + // Scenario C.4: T3 implicitly overrides T2's MethodImpl + .class public auto ansi beforefieldinit T3_4 extends C.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func2() + { + ldstr "T3" + ret + } + } +} + +// Scenario D +.namespace D +{ + .class public auto ansi beforefieldinit T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func1() + { + ldstr "T1" + ret + } + } + .class public auto ansi beforefieldinit T2 extends D.T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + ldstr "T2" + ret + } + } + + // Scenario D.1: T3 explicitly overrides T1's method + .class public auto ansi beforefieldinit T3_1 extends D.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class D.T1::Func1() + ldstr "T3" + ret + } + } + + // Scenario D.2: T3 explicitly overrides T2's method + .class public auto ansi beforefieldinit T3_2 extends D.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class D.T2::Func1() + ldstr "T3" + ret + } + } + + // Scenario D.3: T3 implicitly overrides T1/T2's method + .class public auto ansi beforefieldinit T3_3 extends D.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T3" + ret + } + } +} + +// Scenario E +.namespace E +{ + .class public auto ansi beforefieldinit T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func1() + { + ldstr "T1" + ret + } + } + .class public auto ansi beforefieldinit T2 extends E.T1 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T2" + ret + } + } + + // Scenario E.1: T3 explicitly overrides T1's method + .class public auto ansi beforefieldinit T3_1 extends E.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class E.T1::Func1() + ldstr "T3" + ret + } + } + + // Scenario E.2: T3 explicitly overrides T2's method + .class public auto ansi beforefieldinit T3_2 extends E.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig newslot virtual instance string Func3() + { + .override method instance string class E.T2::Func1() + ldstr "T3" + ret + } + } + + // Scenario E.3: T3 implicitly overrides T1/T2's method + .class public auto ansi beforefieldinit T3_3 extends E.T2 + { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + .method public hidebysig virtual instance string Func1() + { + ldstr "T3" + ret + } + } +} + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method private hidebysig static bool CheckResult (string expected,string actual) cil managed + { + // Method begins at RVA 0x217c + // Code size 45 (0x2d) + .maxstack 8 + + // Console.WriteLine("EXPECTED: " + expected); + IL_0000: ldstr " EXPECTED: " + IL_0005: ldarg.0 + IL_0006: call string [System.Runtime]System.String::Concat(string, string) + IL_000b: call void [System.Console]System.Console::WriteLine(string) + // Console.WriteLine("ACTUAL : " + actual); + IL_0010: ldstr " ACTUAL : " + IL_0015: ldarg.1 + IL_0016: call string [System.Runtime]System.String::Concat(string, string) + IL_001b: call void [System.Console]System.Console::WriteLine(string) + // Console.WriteLine(); + IL_0020: call void [System.Console]System.Console::WriteLine() + // return expected == actual; + IL_0025: ldarg.0 + IL_0026: ldarg.1 + IL_0027: call bool [System.Runtime]System.String::op_Equality(string, string) + // (no C# code) + IL_002c: ret + } // end of method Program::CheckResult + + + // =================================================== + + .method private hidebysig static bool ScenarioA_Test1 () cil managed + { + ldstr "ScenarioA_Test1" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_1::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T2" + newobj instance void A.T3_1::.ctor() + callvirt instance string A.T2Exp::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_1::.ctor() + callvirt instance string A.T3_1::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioA_Test2 () cil managed + { + ldstr "ScenarioA_Test2" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_2::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_2::.ctor() + callvirt instance string A.T2Exp::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_2::.ctor() + callvirt instance string A.T3_2::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioA_Test3 () cil managed + { + ldstr "ScenarioA_Test3" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_3::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T2" + newobj instance void A.T3_3::.ctor() + callvirt instance string A.T2Exp::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_3::.ctor() + callvirt instance string A.T3_3::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioA_Test4 () cil managed + { + ldstr "ScenarioA_Test4" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_4::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_4::.ctor() + callvirt instance string A.T2Exp::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_4::.ctor() + callvirt instance string A.T3_4::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioA_Test5 () cil managed + { + ldstr "ScenarioA_Test5" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_5::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_5::.ctor() + callvirt instance string A.T2Imp::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_5::.ctor() + callvirt instance string A.T3_5::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioA_Test6 () cil managed + { + ldstr "ScenarioA_Test6" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_6::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_6::.ctor() + callvirt instance string A.T2Imp::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_6::.ctor() + callvirt instance string A.T3_6::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioA_Test7 () cil managed + { + ldstr "ScenarioA_Test7" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void A.T3_7::.ctor() + callvirt instance string class A.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_7::.ctor() + callvirt instance string A.T2Imp::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void A.T3_7::.ctor() + callvirt instance string A.T3_7::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + // =================================================== + + .method private hidebysig static bool ScenarioB_Test1 () cil managed + { + ldstr "ScenarioB_Test1" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void B.T3_1::.ctor() + callvirt instance string class B.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T2" + newobj instance void B.T3_1::.ctor() + callvirt instance string B.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_1::.ctor() + callvirt instance string B.T3_1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioB_Test2 () cil managed + { + ldstr "ScenarioB_Test2" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void B.T3_2::.ctor() + callvirt instance string class B.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_2::.ctor() + callvirt instance string B.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_2::.ctor() + callvirt instance string B.T3_2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioB_Test3 () cil managed + { + ldstr "ScenarioB_Test3" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void B.T3_3::.ctor() + callvirt instance string class B.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T2" + newobj instance void B.T3_3::.ctor() + callvirt instance string B.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_3::.ctor() + callvirt instance string B.T3_3::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioB_Test4 () cil managed + { + ldstr "ScenarioB_Test4" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void B.T3_4::.ctor() + callvirt instance string class B.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_4::.ctor() + callvirt instance string B.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_4::.ctor() + callvirt instance string B.T3_4::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void B.T3_4::.ctor() + callvirt instance string B.T3_4::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + // =================================================== + + .method private hidebysig static bool ScenarioC_Test1 () cil managed + { + ldstr "ScenarioC_Test1" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void C.T3_1::.ctor() + callvirt instance string class C.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_1::.ctor() + callvirt instance string C.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_1::.ctor() + callvirt instance string C.T3_1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioC_Test2 () cil managed + { + ldstr "ScenarioC_Test2" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void C.T3_2::.ctor() + callvirt instance string class C.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_2::.ctor() + callvirt instance string C.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_2::.ctor() + callvirt instance string C.T3_2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioC_Test3 () cil managed + { + ldstr "ScenarioC_Test3" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void C.T3_3::.ctor() + callvirt instance string class C.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T2" + newobj instance void C.T3_3::.ctor() + callvirt instance string C.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_3::.ctor() + callvirt instance string C.T3_3::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioC_Test4 () cil managed + { + ldstr "ScenarioC_Test4" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void C.T3_4::.ctor() + callvirt instance string class C.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_4::.ctor() + callvirt instance string C.T2::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_4::.ctor() + callvirt instance string C.T3_4::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void C.T3_4::.ctor() + callvirt instance string C.T3_4::Func2() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + // =================================================== + + .method private hidebysig static bool ScenarioD_Test1 () cil managed + { + ldstr "ScenarioD_Test1" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void D.T3_1::.ctor() + callvirt instance string class D.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_1::.ctor() + callvirt instance string D.T2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_1::.ctor() + callvirt instance string D.T3_1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_1::.ctor() + callvirt instance string D.T3_1::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioD_Test2 () cil managed + { + ldstr "ScenarioD_Test2" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void D.T3_2::.ctor() + callvirt instance string class D.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_2::.ctor() + callvirt instance string D.T2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_2::.ctor() + callvirt instance string D.T3_2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_1::.ctor() + callvirt instance string D.T3_1::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioD_Test3 () cil managed + { + ldstr "ScenarioD_Test3" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void D.T3_3::.ctor() + callvirt instance string class D.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_3::.ctor() + callvirt instance string D.T2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void D.T3_3::.ctor() + callvirt instance string D.T3_3::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + // =================================================== + + .method private hidebysig static bool ScenarioE_Test1 () cil managed + { + ldstr "ScenarioE_Test1" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void E.T3_1::.ctor() + callvirt instance string class E.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_1::.ctor() + callvirt instance string E.T2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_1::.ctor() + callvirt instance string E.T3_1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_1::.ctor() + callvirt instance string E.T3_1::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioE_Test2 () cil managed + { + ldstr "ScenarioE_Test2" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void E.T3_2::.ctor() + callvirt instance string class E.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_2::.ctor() + callvirt instance string E.T2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_2::.ctor() + callvirt instance string E.T3_2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_1::.ctor() + callvirt instance string E.T3_1::Func3() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method private hidebysig static bool ScenarioE_Test3 () cil managed + { + ldstr "ScenarioE_Test3" + call void [System.Console]System.Console::WriteLine(string) + + ldstr "T3" + newobj instance void E.T3_3::.ctor() + callvirt instance string class E.T1::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_3::.ctor() + callvirt instance string E.T2::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldstr "T3" + newobj instance void E.T3_3::.ctor() + callvirt instance string E.T3_3::Func1() + call bool CMain::CheckResult(string, string) + brfalse.s FAILED + + ldc.i4.1 + ret + FAILED: + ldc.i4.0 + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + // ==================================================== // + + ldloc.0 + call bool CMain::ScenarioA_Test1() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioA_Test2() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioA_Test3() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioA_Test4() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioA_Test5() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioA_Test6() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioA_Test7() + and + stloc.0 + + // ==================================================== // + + ldloc.0 + call bool CMain::ScenarioB_Test1() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioB_Test2() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioB_Test3() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioB_Test4() + and + stloc.0 + + // ==================================================== // + + ldloc.0 + call bool CMain::ScenarioC_Test1() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioC_Test2() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioC_Test3() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioC_Test4() + and + stloc.0 + + // ==================================================== // + + ldloc.0 + call bool CMain::ScenarioD_Test1() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioD_Test2() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioD_Test3() + and + stloc.0 + + // ==================================================== // + + ldloc.0 + call bool CMain::ScenarioE_Test1() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioE_Test2() + and + stloc.0 + + ldloc.0 + call bool CMain::ScenarioE_Test3() + and + stloc.0 + + // ==================================================== // + + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/AttributeTesting.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/AttributeTesting.ilproj new file mode 100644 index 00000000000000..4fb61666a1e57e --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/AttributeTesting.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest.il new file mode 100644 index 00000000000000..ae503e14ab11bf --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest.il @@ -0,0 +1,469 @@ +.assembly extern System.Console { } +.assembly extern System.Collections { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly UnitTest { } + +.class public auto ansi abstract Base {} +.class public auto ansi abstract Derived extends Base {} + +.class public auto ansi beforefieldinit C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance int32[] M1() + { + ldnull + ret + } + + .method public hidebysig newslot virtual instance class [System.Runtime]System.Collections.Generic.IList`1 M2() + { + ldnull + ret + } + + .method public hidebysig newslot virtual instance int32 M3() + { + ldc.i4.0 + ret + } + + .method public hidebysig newslot virtual instance valuetype [mscorlib]System.Nullable`1 M4() + { + ldc.i4.0 + newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + ret + } + + .method public hidebysig newslot virtual instance class [System.Runtime]System.Collections.Generic.IList`1 M5() + { + ldnull + ret + } + + .method public hidebysig newslot virtual instance native int[] M6() + { + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C2 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class [System.Runtime]System.Collections.Generic.IList`1 M1() + { + .override method instance int32[] C1::M1(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C3 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance int32[] M2() + { + .override method instance class [System.Runtime]System.Collections.Generic.IList`1 C1::M2(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C4 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig virtual instance valuetype [mscorlib]System.Nullable`1 M3() + { + .override method instance int32 C1::M3(); + ldc.i4.0 + newobj instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0) + ret + } +} + +.class public auto ansi beforefieldinit C5 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig virtual instance int32 M4() + { + .override method instance valuetype [mscorlib]System.Nullable`1 C1::M4(); + ldc.i4.0 + ret + } +} + +.class public auto ansi beforefieldinit C6 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig virtual instance uint32[] M1() + { + .override method instance int32[] C1::M1(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C7 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance uint32[] M2() + { + .override method instance class [System.Runtime]System.Collections.Generic.IList`1 C1::M2(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C8 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class Derived[] M5() + { + .override method instance class [System.Runtime]System.Collections.Generic.IList`1 C1::M5(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C9 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig virtual instance uint64[] M6() + { + .override method instance native int[] C1::M6(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit C10 extends C1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig virtual instance uint32[] M6() + { + .override method instance native int[] C1::M6(); + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Main extends [mscorlib]System.Object +{ + .method public static void RunTestC1() noinlining + { + newobj instance void class C1::.ctor() + callvirt instance int32[] class C1::M1() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC2() noinlining + { + newobj instance void class C2::.ctor() + callvirt instance int32[] class C1::M1() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC3() noinlining + { + newobj instance void class C3::.ctor() + callvirt instance class [System.Runtime]System.Collections.Generic.IList`1 class C1::M2() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC4() noinlining + { + newobj instance void class C4::.ctor() + callvirt instance int32 class C1::M3() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC5() noinlining + { + newobj instance void class C5::.ctor() + callvirt instance valuetype [mscorlib]System.Nullable`1 C1::M4() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC6() noinlining + { + newobj instance void class C6::.ctor() + callvirt instance int32[] class C1::M1() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC7() noinlining + { + newobj instance void class C7::.ctor() + callvirt instance class [System.Runtime]System.Collections.Generic.IList`1 class C1::M2() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC8() noinlining + { + newobj instance void class C8::.ctor() + callvirt instance class [System.Runtime]System.Collections.Generic.IList`1 class C1::M5() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC9() noinlining + { + newobj instance void class C9::.ctor() + callvirt instance native int[] class C1::M6() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public static void RunTestC10() noinlining + { + newobj instance void class C10::.ctor() + callvirt instance native int[] class C1::M6() + pop + ldstr "Succeeded" + call void [System.Console]System.Console::WriteLine(string) + ret + } + + .method public hidebysig static int32 Main(string[] args) cil managed + { + .entrypoint + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + ldstr "C1" + call void [System.Console]System.Console::WriteLine(string) + + .try + { + call void Main::RunTestC1() + leave.s CC2 + } + catch [mscorlib]System.TypeLoadException + { + ldstr "Caught unexpected TypeLoadException:" + call void [System.Console]System.Console::WriteLine(string) + call void [System.Console]System.Console::WriteLine(object) + ldc.i4.0 + stloc.0 + leave.s CC2 + } + +CC2: + ldstr "C2: override int32[] by IList" + call void [System.Console]System.Console::WriteLine(string) + + .try + { + call void Main::RunTestC2() + 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 by int32[]" + call void [System.Console]System.Console::WriteLine(string) + + .try + { + call void Main::RunTestC3() + leave.s CC4 + } + catch [mscorlib]System.TypeLoadException + { + ldstr "Caught unexpected TypeLoadException:" + call void [System.Console]System.Console::WriteLine(string) + call void [System.Console]System.Console::WriteLine(object) + ldc.i4.0 + stloc.0 + leave.s CC4 + } + +CC4: + ldstr "C4: override int32 by Nullable`1" + 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 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: + ldstr "C6: override int32[] by uint32[]" + call void [System.Console]System.Console::WriteLine(string) + + .try + { + call void Main::RunTestC6() + leave.s CC7 + } + catch [mscorlib]System.TypeLoadException + { + ldstr "Caught unexpected TypeLoadException:" + call void [System.Console]System.Console::WriteLine(string) + call void [System.Console]System.Console::WriteLine(object) + ldc.i4.0 + stloc.0 + leave.s CC7 + } +CC7: + ldstr "C7: override IList1 by uint32[]" + call void [System.Console]System.Console::WriteLine(string) + + .try + { + call void Main::RunTestC7() + leave.s CC8 + } + catch [mscorlib]System.TypeLoadException + { + ldstr "Caught unexpected TypeLoadException:" + call void [System.Console]System.Console::WriteLine(string) + call void [System.Console]System.Console::WriteLine(object) + ldc.i4.0 + stloc.0 + leave.s CC8 + } +CC8: + ldstr "C8: override IList by Derived[]" + call void [System.Console]System.Console::WriteLine(string) + + .try + { + call void Main::RunTestC8() + leave.s CC9 + } + catch [mscorlib]System.TypeLoadException + { + ldstr "Caught unexpected TypeLoadException:" + call void [System.Console]System.Console::WriteLine(string) + 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 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest.ilproj new file mode 100644 index 00000000000000..2a6c4198b627a9 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/CompatibleWithTest.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.il new file mode 100644 index 00000000000000..78bc586b531020 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly A{} + +.class public auto ansi beforefieldinit A +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.ilproj new file mode 100644 index 00000000000000..c4248224974169 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.il new file mode 100644 index 00000000000000..92f988163e670f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.il @@ -0,0 +1,14 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern A{} +.assembly B{} + + +.class public auto ansi beforefieldinit B extends [A]A +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.ilproj new file mode 100644 index 00000000000000..5dafe94b9dbfe1 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.il new file mode 100644 index 00000000000000..a151cd015efd8c --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.il @@ -0,0 +1,14 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern B{} +.assembly C{} + +.class public auto ansi beforefieldinit C extends [B]B +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.ilproj new file mode 100644 index 00000000000000..f4c3d16fcfd0aa --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.il new file mode 100644 index 00000000000000..dec049b045bbad --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly Dictionary{} + +.class public auto ansi beforefieldinit Dictionary +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.ilproj new file mode 100644 index 00000000000000..6e3dd6c0bf32ed --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.il new file mode 100644 index 00000000000000..3b79f7a200772f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.il @@ -0,0 +1,80 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib { } +.assembly extern A { } +.assembly extern B { } +.assembly extern GenRetType { } +.assembly extern Dictionary { } + +.assembly GenBaseType { } + +.class public auto ansi beforefieldinit GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } + + .method public hidebysig newslot virtual instance object MyFunc(string& res) + { + ldarg.1 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void [A]A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class [B]B MyFunc(string& res) + { + ldarg.1 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void [B]B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class [B]B GenToNonGen(string& res) + { + ldarg.1 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void [B]B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class [B]B NonGenThroughGenFunc(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void [B]B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class [GenRetType]GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class [GenRetType]GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class [GenRetType]GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class [GenRetType]GenRetType>::.ctor() + ret + } + .method public hidebysig newslot virtual instance class [GenRetType]GenRetType TestNonGenericDerived(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class [GenRetType]GenRetType::.ctor() + ret + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.ilproj new file mode 100644 index 00000000000000..92c1d500858832 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.il new file mode 100644 index 00000000000000..7ba3ff8507c8b9 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern GenRetType{} +.assembly GenDerive1{} + +.class public auto ansi beforefieldinit GenDerive1 extends class [GenRetType]GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.ilproj new file mode 100644 index 00000000000000..b560c1792a242a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.il new file mode 100644 index 00000000000000..2a2d9b8da7c08f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.il @@ -0,0 +1,14 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern GenDerive1{} +.assembly extern Dictionary{} +.assembly GenDerive2{} + +.class public auto ansi beforefieldinit GenDerive2 extends class [GenDerive1]GenDerive1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.ilproj new file mode 100644 index 00000000000000..4c841ecd1683c2 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.il new file mode 100644 index 00000000000000..0be33cd740c20c --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern GenDerive2{} +.assembly GenDerive3{} + +.class public auto ansi beforefieldinit GenDerive3 extends class [GenDerive2]GenDerive2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.ilproj new file mode 100644 index 00000000000000..4463d91b5ac1bf --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.il new file mode 100644 index 00000000000000..f36dcc47430eaf --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.il @@ -0,0 +1,12 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly GenRetType{} + +.class public auto ansi beforefieldinit GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.ilproj new file mode 100644 index 00000000000000..28124cdaf40f1b --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.il new file mode 100644 index 00000000000000..8b0e80812d4d9a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.il @@ -0,0 +1,101 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} + +.assembly extern A { } +.assembly extern B { } +.assembly extern C { } +.assembly extern Dictionary { } +.assembly extern GenRetType { } +.assembly extern GenDerive1 { } +.assembly extern GenDerive2 { } +.assembly extern GenDerive3 { } +.assembly extern NonGenericDerived1 { } +.assembly extern NonGenericDerived2 { } +.assembly extern NonGenericDerived3 { } +.assembly extern NonGenericDerived4 { } +.assembly extern GenToNonGen1 { } +.assembly extern GenToNonGen2 { } +.assembly extern GenToNonGen3 { } +.assembly extern NonGenThroughGen1 { } +.assembly extern NonGenThroughGen2 { } +.assembly extern NonGenThroughGen3 { } +.assembly extern NonGenThroughGen4 { } + +.assembly extern GenBaseType { } + +.assembly GenTestType { } + +.class public auto ansi beforefieldinit GenTestType extends class [GenBaseType]GenBaseType +{ + .method public hidebysig newslot virtual instance class [NonGenThroughGen4]NonGenThroughGen4 NonGenThroughGenOverride(string& res) + { + .override method instance class [B]B class [GenBaseType]GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class [GenToNonGen3]GenToNonGen3 GenToNonGenOverride(string& res) + { + .override method instance class [B]B class [GenBaseType]GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class [NonGenericDerived4]NonGenericDerived4 NewGenFunc1(string& res) + { + .override method instance class [GenRetType]GenRetType class [GenBaseType]GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 TestType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class [GenDerive3]GenDerive3 NewGenFunc2(string& res) + { + .override method instance class [GenRetType]GenRetType> class [GenBaseType]GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 TestType.NewGenFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class [GenRetType]GenRetType NewFunc1(string& res) + { + .override method instance object class [GenBaseType]GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenRetType TestType.NewFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class [C]C NewFunc2(string& res) + { + .override method instance class [B]B class [GenBaseType]GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "C TestType.NewFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class [GenBaseType]GenBaseType::.ctor() + ret + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.ilproj new file mode 100644 index 00000000000000..4d2eb180d699c8 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.il new file mode 100644 index 00000000000000..0db5ede06079dd --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern C{} +.assembly GenToNonGen1{} + +.class public auto ansi beforefieldinit GenToNonGen1 extends [C]C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.ilproj new file mode 100644 index 00000000000000..6431ad98866f61 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.il new file mode 100644 index 00000000000000..9556f0ed989519 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.il @@ -0,0 +1,14 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern GenToNonGen1{} +.assembly extern Dictionary{} +.assembly GenToNonGen2{} + +.class public auto ansi beforefieldinit GenToNonGen2 extends class [GenToNonGen1]GenToNonGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.ilproj new file mode 100644 index 00000000000000..4b942c58ba0aa8 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.il new file mode 100644 index 00000000000000..bcbd4eb12851e6 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.il @@ -0,0 +1,14 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern GenToNonGen2 { } + +.assembly GenToNonGen3{} + +.class public auto ansi beforefieldinit GenToNonGen3 extends class [GenToNonGen2]GenToNonGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.ilproj new file mode 100644 index 00000000000000..b8ad4600c9c6a1 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.il new file mode 100644 index 00000000000000..e47082ab030f69 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.il @@ -0,0 +1,11 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern C{} +.assembly NonGenThroughGen1{} + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends [C]C { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.ilproj new file mode 100644 index 00000000000000..b15fc7a3cdb015 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.il new file mode 100644 index 00000000000000..beab86bb6d8962 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern NonGenThroughGen1{} +.assembly extern Dictionary{} +.assembly NonGenThroughGen2{} + +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class [NonGenThroughGen1]NonGenThroughGen1> { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.ilproj new file mode 100644 index 00000000000000..33147e73fb7c0f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.il new file mode 100644 index 00000000000000..e0e83f9a419343 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.il @@ -0,0 +1,15 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern NonGenThroughGen2{} +.assembly NonGenThroughGen3{} + +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class [NonGenThroughGen2]NonGenThroughGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.ilproj new file mode 100644 index 00000000000000..cc0e7773e557d3 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.il new file mode 100644 index 00000000000000..2e2401783c9c88 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern NonGenThroughGen3{} +.assembly NonGenThroughGen4{} + +.class public auto ansi beforefieldinit NonGenThroughGen4 extends [NonGenThroughGen3]NonGenThroughGen3 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.ilproj new file mode 100644 index 00000000000000..5a9a6a9848df56 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.il new file mode 100644 index 00000000000000..07b26bf22890d3 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.il @@ -0,0 +1,12 @@ +// 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. + +.assembly extern mscorlib { } +.assembly extern GenRetType { } + +.assembly NonGenericDerived1 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class [GenRetType]GenRetType { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.ilproj new file mode 100644 index 00000000000000..9f9d5761f55881 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.il new file mode 100644 index 00000000000000..4cc4f7e3530b87 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.il @@ -0,0 +1,13 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern mscorlib{} +.assembly extern NonGenericDerived1{} +.assembly NonGenericDerived2{} + +.class public auto ansi beforefieldinit NonGenericDerived2 extends class [NonGenericDerived1]NonGenericDerived1 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.ilproj new file mode 100644 index 00000000000000..f6aaa70acbcc8a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.il new file mode 100644 index 00000000000000..08face4ff92089 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.il @@ -0,0 +1,11 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern NonGenericDerived2{} +.assembly NonGenericDerived3{} + +.class public auto ansi beforefieldinit NonGenericDerived3 extends class [NonGenericDerived2]NonGenericDerived2 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.ilproj new file mode 100644 index 00000000000000..d6f9c874cd545f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.il new file mode 100644 index 00000000000000..7e761a1b021de3 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.il @@ -0,0 +1,11 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern NonGenericDerived3{} +.assembly NonGenericDerived4{} + +.class public auto ansi beforefieldinit NonGenericDerived4 extends [NonGenericDerived3]NonGenericDerived3 { + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.ilproj new file mode 100644 index 00000000000000..fef53b39e4be4f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.il new file mode 100644 index 00000000000000..c5e108029e7e2e --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.il @@ -0,0 +1,684 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly ReOverrideMoreDerivedReturn { } + +// ======================================================================================== +// 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 D extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerivedRetType extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerivedRetType2 extends class GenDerivedRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Dictionary +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive4 extends class GenDerive3 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 +{ + .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 extends NonGenericDerived4 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenToNonGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen4 extends class GenToNonGen3 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 +{ + .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 extends NonGenThroughGen4 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(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(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(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType>::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType TestNonGenericDerived(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== +// SECOND LAYER type: overrides all virtuals on GenBaseType using MethodImpls with +// covariant return types (more derived return types) +// ======================================================================================== + +.class public auto ansi beforefieldinit GenTestType extends class GenBaseType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenFunc(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGen(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived4 MyGenFunc(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive3 MyGenFunc(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerivedRetType MyFunc(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenDerivedRetType TestType.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C MyFunc(string& res) + { + .override method instance class B class GenBaseType::MyFunc(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 types: explicitly override the virtual methods on GenBaseType, using +// more derived return types than the ones in the MethodImpls on GenTestType +// ======================================================================================== + +.class public auto ansi beforefieldinit GenDerivedTestType extends class GenTestType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen5 NonGenThroughGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen5 DerivedTestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen4 GenToNonGen(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen4 DerivedTestType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived5 MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived5 DerivedTestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive4 MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive4 DerivedTestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerivedRetType2 MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenDerivedRetType2 DerivedTestType.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class D MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "D DerivedTestType.MyFunc()" + stind.ref + 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 GenDerivedTestType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenTestType with covariant returns + // 3) The signature from GenDerivedTestType with covariant returns + // And verify that the override on GenDerivedTestType is the one that executes + + .method public static bool RunTest1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 1 + callvirt instance class GenDerivedRetType class GenTestType::MyFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 2 + callvirt instance class GenDerivedRetType2 class GenDerivedTestType::MyFunc(string&) + pop + + ldstr "GenDerivedRetType2 DerivedTestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 1 + callvirt instance class C class GenTestType::MyFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 2 + callvirt instance class D class GenDerivedTestType::MyFunc(string&) + pop + + ldstr "D DerivedTestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 1 + callvirt instance class GenDerive3 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 2 + callvirt instance class GenDerive4 class GenDerivedTestType::MyGenFunc(string&) + pop + + ldstr "GenDerive4 DerivedTestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived4 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 2 + callvirt instance class NonGenericDerived5 class GenDerivedTestType::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived5 DerivedTestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest5() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 2 + callvirt instance class GenToNonGen4 class GenDerivedTestType::GenToNonGen(string&) + pop + + ldstr "GenToNonGen4 DerivedTestType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest6() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 2 + callvirt instance class NonGenThroughGen5 class GenDerivedTestType::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen5 DerivedTestType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ===================================================================================== // + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + T1: + call bool CMain::RunTest1() + brtrue.s T2 + ldc.i4.0 + stloc.0 + + T2: + call bool CMain::RunTest2() + brtrue.s T3 + ldc.i4.0 + stloc.0 + + T3: + call bool CMain::RunTest3() + brtrue.s T4 + ldc.i4.0 + stloc.0 + + T4: + call bool CMain::RunTest4() + brtrue.s T5 + ldc.i4.0 + stloc.0 + + T5: + call bool CMain::RunTest5() + brtrue.s T6 + ldc.i4.0 + stloc.0 + + T6: + call bool CMain::RunTest6() + brtrue.s DONE + ldc.i4.0 + stloc.0 + + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.ilproj new file mode 100644 index 00000000000000..8617ffc5cdd29f --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.il new file mode 100644 index 00000000000000..ec1022254d0fc0 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.il @@ -0,0 +1,1392 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly UnitTest { } + +// ======================================================================================== +// 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 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Dictionary +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 +{ + .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 GenToNonGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 +{ + .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 } +} + + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(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(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(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType>::.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 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class NonGenThroughGen2 NonGenThroughGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen1> GenToNonGen(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived1 MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived1 GenMiddleType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive1> MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive1> 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 extends class GenMiddleType +{ + .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 B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGen(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived4 MyGenFunc(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive3 MyGenFunc(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenRetType TestType.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "C TestType.MyFunc()" + 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 B 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 B 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 GenRetType 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 GenRetType> 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 B MyFunc(string& res) + { + ldstr "Should never execute this method" + newobj instance void [System.Runtime]System.Exception::.ctor(string) + throw + } +} + + +// ======================================================================================== +// FOURTH LAYER type: implicitly overrides all MethodImpls from GenTestType +// ======================================================================================== + +.class public auto ansi beforefieldinit ImplicitOverrideToMethodImpls extends class GenTestType +{ + .method public hidebysig virtual instance class NonGenThroughGen4 NonGenThroughGenFunc(string& res) + { + ldarg.1 + ldstr "NonGenThroughGen4 ImplicitOverrideToMethodImpls.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class GenToNonGen3 GenToNonGen(string& res) + { + ldarg.1 + ldstr "GenToNonGen3 ImplicitOverrideToMethodImpls.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class NonGenericDerived4 MyGenFunc(string& res) + { + ldarg.1 + ldstr "NonGenericDerived4 ImplicitOverrideToMethodImpls.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class GenDerive3 MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenDerive3 ImplicitOverrideToMethodImpls.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class GenRetType MyFunc(string& res) + { + ldarg.1 + ldstr "GenRetType ImplicitOverrideToMethodImpls.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class C MyFunc(string& res) + { + ldarg.1 + ldstr "C ImplicitOverrideToMethodImpls.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +// ======================================================================================== +// FOURTH LAYER type: overrides all MethodImpls from GenTestType using MethodImpls with the +// same return type used in GetTestType +// ======================================================================================== + +.class public auto ansi beforefieldinit ExplicitOverrideToMethodImpls extends class GenTestType +{ + .method public hidebysig virtual instance class NonGenThroughGen4 NonGenThroughGenFunc_MethodImpl(string& res) + { + .override method instance class NonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 ExplicitOverrideToMethodImpls.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class GenToNonGen3 GenToNonGen_MethodImpl(string& res) + { + .override method instance class GenToNonGen3 class GenTestType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 ExplicitOverrideToMethodImpls.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class NonGenericDerived4 MyGenFunc_MethodImpl(string& res) + { + .override method instance class NonGenericDerived4 class GenTestType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 ExplicitOverrideToMethodImpls.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class GenDerive3 MyGenFunc_MethodImpl(string& res) + { + .override method instance class GenDerive3 class GenTestType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 ExplicitOverrideToMethodImpls.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class GenRetType MyFunc_MethodImpl(string& res) + { + .override method instance class GenRetType class GenTestType::MyFunc(string& res) + ldarg.1 + ldstr "GenRetType ExplicitOverrideToMethodImpls.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig virtual instance class C MyFunc_MethodImpl(string& res) + { + .override method instance class C class GenTestType::MyFunc(string& res) + ldarg.1 + ldstr "C ExplicitOverrideToMethodImpls.MyFunc()" + stind.ref + 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 GenTestType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // And verify that the override on GetTestType is the one that executes + + .method public static bool RunTest1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class GenRetType class GenTestType::MyFunc(string&) + pop + + ldstr "GenRetType TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class C class GenTestType::MyFunc(string&) + pop + + ldstr "C TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class GenDerive3 class GenTestType::MyGenFunc(string&) + pop + + ldstr "GenDerive3 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class NonGenericDerived4 class GenTestType::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived4 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest5() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class GenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + ldstr "GenToNonGen3 TestType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest6() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class NonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ============== Test using ImplicitOverrideToMethodImpls ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // 4) The signature from ImplicitOverrideToMethodImpls + // And verify that the override on ImplicitOverrideToMethodImpls is the one that executes + + .method public static bool RunTest_ImplicitOverride1() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class GenRetType class GenTestType::MyFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class GenRetType class ImplicitOverrideToMethodImpls::MyFunc(string&) + pop + + ldstr "GenRetType ImplicitOverrideToMethodImpls.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ImplicitOverride2() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class C class GenTestType::MyFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class C class ImplicitOverrideToMethodImpls::MyFunc(string&) + pop + + ldstr "C ImplicitOverrideToMethodImpls.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ImplicitOverride3() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class GenDerive3 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class GenDerive3 class ImplicitOverrideToMethodImpls::MyGenFunc(string&) + pop + + ldstr "GenDerive3 ImplicitOverrideToMethodImpls.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ImplicitOverride4() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class NonGenericDerived4 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class NonGenericDerived4 class ImplicitOverrideToMethodImpls::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived4 ImplicitOverrideToMethodImpls.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ImplicitOverride5() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class GenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class GenToNonGen3 class ImplicitOverrideToMethodImpls::GenToNonGen(string&) + pop + + ldstr "GenToNonGen3 ImplicitOverrideToMethodImpls.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ImplicitOverride6() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class NonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class ImplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class NonGenThroughGen4 class ImplicitOverrideToMethodImpls::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen4 ImplicitOverrideToMethodImpls.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ============== Test using ExplicitOverrideToMethodImpls ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // 4) The signature from ExplicitOverrideToMethodImpls + // And verify that the override on ExplicitOverrideToMethodImpls is the one that executes + + .method public static bool RunTest_ExplicitOverride1() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class GenRetType class GenTestType::MyFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class GenRetType class ExplicitOverrideToMethodImpls::MyFunc(string&) + pop + + ldstr "GenRetType ExplicitOverrideToMethodImpls.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ExplicitOverride2() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class C class GenTestType::MyFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class C class ExplicitOverrideToMethodImpls::MyFunc(string&) + pop + + ldstr "C ExplicitOverrideToMethodImpls.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ExplicitOverride3() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class GenDerive3 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class GenDerive3 class ExplicitOverrideToMethodImpls::MyGenFunc(string&) + pop + + ldstr "GenDerive3 ExplicitOverrideToMethodImpls.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ExplicitOverride4() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class NonGenericDerived4 class GenTestType::MyGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class NonGenericDerived4 class ExplicitOverrideToMethodImpls::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived4 ExplicitOverrideToMethodImpls.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ExplicitOverride5() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class GenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class GenToNonGen3 class ExplicitOverrideToMethodImpls::GenToNonGen(string&) + pop + + ldstr "GenToNonGen3 ExplicitOverrideToMethodImpls.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_ExplicitOverride6() noinlining + { + .locals init (string res1, string res2, string res3, string res4) + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 2 + callvirt instance class NonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class ExplicitOverrideToMethodImpls::.ctor() + ldloca.s 3 + callvirt instance class NonGenThroughGen4 class ExplicitOverrideToMethodImpls::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen4 ExplicitOverrideToMethodImpls.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldloc.3 + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ============== Test using GenMiddleType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns + // And verify that the override on GenMiddleType is the one that executes + + .method public static bool RunTest_Middle1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + ldstr "GenDerive1> GenMiddleType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived1 GenMiddleType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + ldstr "GenToNonGen1> GenMiddleType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ===================================================================================== // + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + T1: + call bool CMain::RunTest1() + brtrue.s T2 + ldc.i4.0 + stloc.0 + + T2: + call bool CMain::RunTest2() + brtrue.s T3 + ldc.i4.0 + stloc.0 + + T3: + call bool CMain::RunTest3() + brtrue.s T4 + ldc.i4.0 + stloc.0 + + T4: + call bool CMain::RunTest4() + brtrue.s T5 + ldc.i4.0 + stloc.0 + + T5: + call bool CMain::RunTest5() + brtrue.s T6 + ldc.i4.0 + stloc.0 + + T6: + call bool CMain::RunTest6() + brtrue.s M1 + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + M1: + call bool CMain::RunTest_Middle1() + brtrue.s M2 + ldc.i4.0 + stloc.0 + + M2: + call bool CMain::RunTest_Middle2() + brtrue.s M3 + ldc.i4.0 + stloc.0 + + M3: + call bool CMain::RunTest_Middle3() + brtrue.s M4 + ldc.i4.0 + stloc.0 + + M4: + call bool CMain::RunTest_Middle4() + brtrue.s IMP_OVERRIDE1 + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + IMP_OVERRIDE1: + call bool CMain::RunTest_ImplicitOverride1() + brtrue.s IMP_OVERRIDE2 + ldc.i4.0 + stloc.0 + + IMP_OVERRIDE2: + call bool CMain::RunTest_ImplicitOverride2() + brtrue.s IMP_OVERRIDE3 + ldc.i4.0 + stloc.0 + + IMP_OVERRIDE3: + call bool CMain::RunTest_ImplicitOverride3() + brtrue.s IMP_OVERRIDE4 + ldc.i4.0 + stloc.0 + + IMP_OVERRIDE4: + call bool CMain::RunTest_ImplicitOverride4() + brtrue.s IMP_OVERRIDE5 + ldc.i4.0 + stloc.0 + + IMP_OVERRIDE5: + call bool CMain::RunTest_ImplicitOverride5() + brtrue.s IMP_OVERRIDE6 + ldc.i4.0 + stloc.0 + + IMP_OVERRIDE6: + call bool CMain::RunTest_ImplicitOverride6() + brtrue.s EXP_OVERRIDE1 + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + EXP_OVERRIDE1: + call bool CMain::RunTest_ExplicitOverride1() + brtrue.s EXP_OVERRIDE2 + ldc.i4.0 + stloc.0 + + EXP_OVERRIDE2: + call bool CMain::RunTest_ExplicitOverride2() + brtrue.s EXP_OVERRIDE3 + ldc.i4.0 + stloc.0 + + EXP_OVERRIDE3: + call bool CMain::RunTest_ExplicitOverride3() + brtrue.s EXP_OVERRIDE4 + ldc.i4.0 + stloc.0 + + EXP_OVERRIDE4: + call bool CMain::RunTest_ExplicitOverride4() + brtrue.s EXP_OVERRIDE5 + ldc.i4.0 + stloc.0 + + EXP_OVERRIDE5: + call bool CMain::RunTest_ExplicitOverride5() + brtrue.s EXP_OVERRIDE6 + ldc.i4.0 + stloc.0 + + EXP_OVERRIDE6: + call bool CMain::RunTest_ExplicitOverride6() + brtrue.s DONE + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.ilproj new file mode 100644 index 00000000000000..921b93a2356ead --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.il new file mode 100644 index 00000000000000..6d76c7d27f3db1 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.il @@ -0,0 +1,1177 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly UnitTestDelegates { } + + +// ======================================================================================== +// 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 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Dictionary +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 +{ + .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 GenToNonGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 +{ + .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 private auto ansi sealed En extends [System.Runtime]System.Enum +{ + .field public specialname rtspecialname int32 value__ +} + + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(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(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(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType>::.ctor() + ret + } + + .method public hidebysig newslot virtual instance int32[] RetIntArr() + { + ldstr "base.retintarr" + call void [System.Console]System.Console::WriteLine(string) + 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 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class NonGenThroughGen2 NonGenThroughGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen1> GenToNonGen(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived1 MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived1 GenMiddleType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive1> MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive1> 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 extends class GenMiddleType +{ + .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 B class GenBaseType::NonGenThroughGenFunc(string& res) + ldarg.1 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGen(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived4 MyGenFunc(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived4 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive3 MyGenFunc(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive3 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenRetType TestType.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "C TestType.MyFunc()" + 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 B 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 B 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 GenRetType 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 GenRetType> 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 B MyFunc(string& res) + { + ldstr "Should never execute this method" + newobj instance void [System.Runtime]System.Exception::.ctor(string) + throw + } +} + + +// ======================================================================================== +// Delegates that will be used for the various method calls +// ======================================================================================== + +.class private auto ansi sealed Del_Obj extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_Obj::.ctor + + .method public hidebysig newslot virtual + instance object Invoke(string& res) runtime managed + { + } // end of method Del_Obj::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_Obj::BeginInvoke + + .method public hidebysig newslot virtual + instance object EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_Obj::EndInvoke + +} // end of class Del_Obj + +.class private auto ansi sealed Del_B extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_B::.ctor + + .method public hidebysig newslot virtual + instance class B Invoke(string& res) runtime managed + { + } // end of method Del_B::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_B::BeginInvoke + + .method public hidebysig newslot virtual + instance class B EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_B::EndInvoke + +} // end of class Del_B + +.class private auto ansi sealed Del_GenRetType_int_object extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenRetType_int_object::.ctor + + .method public hidebysig newslot virtual + instance class GenRetType + Invoke(string& res) runtime managed + { + } // end of method Del_GenRetType_int_object::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenRetType_int_object::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenRetType + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenRetType_int_object::EndInvoke + +} // end of class Del_GenRetType_int_object + +.class private auto ansi sealed Del_GenRetType extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenRetType::.ctor + + .method public hidebysig newslot virtual + instance class GenRetType> + Invoke(string& res) runtime managed + { + } // end of method Del_GenRetType::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenRetType::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenRetType> + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenRetType::EndInvoke + +} // end of class Del_GenRetType + +.class private auto ansi sealed Del_NonGenThroughGen2 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_NonGenThroughGen2::.ctor + + .method public hidebysig newslot virtual + instance class NonGenThroughGen2 + Invoke(string& res) runtime managed + { + } // end of method Del_NonGenThroughGen2::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_NonGenThroughGen2::BeginInvoke + + .method public hidebysig newslot virtual + instance class NonGenThroughGen2 + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_NonGenThroughGen2::EndInvoke + +} // end of class Del_NonGenThroughGen2 + +.class private auto ansi sealed Del_GenToNonGen1 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenToNonGen1::.ctor + + .method public hidebysig newslot virtual + instance class GenToNonGen1> + Invoke(string& res) runtime managed + { + } // end of method Del_GenToNonGen1::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenToNonGen1::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenToNonGen1> + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenToNonGen1::EndInvoke + +} // end of class Del_GenToNonGen1 + +.class private auto ansi sealed Del_NonGenericDerived1 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_NonGenericDerived1::.ctor + + .method public hidebysig newslot virtual + instance class NonGenericDerived1 + Invoke(string& res) runtime managed + { + } // end of method Del_NonGenericDerived1::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_NonGenericDerived1::BeginInvoke + + .method public hidebysig newslot virtual + instance class NonGenericDerived1 + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_NonGenericDerived1::EndInvoke + +} // end of class Del_NonGenericDerived1 + +.class private auto ansi sealed Del_GenDerive1 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenDerive1::.ctor + + .method public hidebysig newslot virtual + instance class GenDerive1> + Invoke(string& res) runtime managed + { + } // end of method Del_GenDerive1::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenDerive1::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenDerive1> + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenDerive1::EndInvoke + +} // end of class Del_GenDerive1 + +.class private auto ansi sealed Del_NonGenThroughGen4 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_NonGenThroughGen4::.ctor + + .method public hidebysig newslot virtual + instance class NonGenThroughGen4 + Invoke(string& res) runtime managed + { + } // end of method Del_NonGenThroughGen4::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_NonGenThroughGen4::BeginInvoke + + .method public hidebysig newslot virtual + instance class NonGenThroughGen4 + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_NonGenThroughGen4::EndInvoke + +} // end of class Del_NonGenThroughGen4 + +.class private auto ansi sealed Del_GenToNonGen3 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenToNonGen3::.ctor + + .method public hidebysig newslot virtual + instance class GenToNonGen3 + Invoke(string& res) runtime managed + { + } // end of method Del_GenToNonGen3::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenToNonGen3::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenToNonGen3 + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenToNonGen3::EndInvoke + +} // end of class Del_GenToNonGen3 + +.class private auto ansi sealed Del_NonGenericDerived4 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_NonGenericDerived4::.ctor + + .method public hidebysig newslot virtual + instance class NonGenericDerived4 + Invoke(string& res) runtime managed + { + } // end of method Del_NonGenericDerived4::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_NonGenericDerived4::BeginInvoke + + .method public hidebysig newslot virtual + instance class NonGenericDerived4 + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_NonGenericDerived4::EndInvoke + +} // end of class Del_NonGenericDerived4 + +.class private auto ansi sealed Del_GenDerive3 extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenDerive3::.ctor + + .method public hidebysig newslot virtual + instance class GenDerive3 + Invoke(string& res) runtime managed + { + } // end of method Del_GenDerive3::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenDerive3::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenDerive3 + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenDerive3::EndInvoke + +} // end of class Del_GenDerive3 + +.class private auto ansi sealed Del_GenRetType_U_V extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_GenRetType_U_V::.ctor + + .method public hidebysig newslot virtual + instance class GenRetType + Invoke(string& res) runtime managed + { + } // end of method Del_GenRetType_U_V::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_GenRetType_U_V::BeginInvoke + + .method public hidebysig newslot virtual + instance class GenRetType + EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_GenRetType_U_V::EndInvoke + +} // end of class Del_GenRetType_U_V + +.class private auto ansi sealed Del_C extends [System.Runtime]System.MulticastDelegate +{ + .method public hidebysig specialname rtspecialname + instance void .ctor(object 'object', + native int 'method') runtime managed + { + } // end of method Del_C::.ctor + + .method public hidebysig newslot virtual + instance class C Invoke(string& res) runtime managed + { + } // end of method Del_C::Invoke + + .method public hidebysig newslot virtual + instance class [System.Runtime]System.IAsyncResult + BeginInvoke(string& res, + class [System.Runtime]System.AsyncCallback callback, + object 'object') runtime managed + { + } // end of method Del_C::BeginInvoke + + .method public hidebysig newslot virtual + instance class C EndInvoke(string& res, + class [System.Runtime]System.IAsyncResult result) runtime managed + { + } // end of method Del_C::EndInvoke + +} // end of class Del_C + + + +// ======================================================================================== + +.class private auto ansi beforefieldinit CMain extends [System.Runtime]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 + // Code size 164 (0xa4) + .maxstack 2 + .locals init (bool V_0) + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: call bool [System.Runtime]System.String::op_Equality(string, + string) + IL_0007: stloc.0 + IL_0008: ldstr "EXPECTED: " + IL_000d: ldarg.0 + IL_000e: call string [System.Runtime]System.String::Concat(string, + string) + IL_0013: call void [System.Console]System.Console::WriteLine(string) + IL_0018: ldstr "ACTUAL1 : " + IL_001d: ldarg.1 + IL_001e: call string [System.Runtime]System.String::Concat(string, + string) + IL_0023: call void [System.Console]System.Console::WriteLine(string) + IL_0028: ldarg.2 + IL_0029: call bool [System.Runtime]System.String::IsNullOrEmpty(string) + IL_002e: brtrue.s IL_004e + + IL_0030: ldstr "ACTUAL2 : " + IL_0035: ldarg.2 + IL_0036: call string [System.Runtime]System.String::Concat(string, + string) + IL_003b: call void [System.Console]System.Console::WriteLine(string) + 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) + 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) + IL_0054: brtrue.s IL_0074 + + IL_0056: ldstr "ACTUAL3 : " + IL_005b: ldarg.3 + IL_005c: call string [System.Runtime]System.String::Concat(string, + string) + IL_0061: call void [System.Console]System.Console::WriteLine(string) + 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) + 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) + IL_007b: brtrue.s IL_009d + + IL_007d: ldstr "ACTUAL4 : " + IL_0082: ldarg.s d + IL_0084: call string [System.Runtime]System.String::Concat(string, + string) + IL_0089: call void [System.Console]System.Console::WriteLine(string) + 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) + IL_0099: br.s IL_009c + + IL_009b: ldc.i4.0 + IL_009c: stloc.0 + IL_009d: call void [System.Console]System.Console::WriteLine() + IL_00a2: ldloc.0 + IL_00a3: ret + } // end of method Program::CheckResults + + + // ============== Test using GenTestType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // And verify that the override on GetTestType is the one that executes + + .method public hidebysig static bool RunTest1() cil managed noinlining + { + .locals init (string res1, string res2, string res3, class GenTestType thisPtr) + + newobj instance void class GenTestType::.ctor() + stloc.s thisPtr + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance object class GenBaseType::MyFunc(string&) + newobj instance void Del_Obj::.ctor(object, native int) + ldloca.s 0 + callvirt instance object Del_Obj::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenRetType class GenTestType::MyFunc(string&) + newobj instance void class Del_GenRetType_U_V::.ctor(object, native int) + ldloca.s 1 + callvirt instance class GenRetType class Del_GenRetType_U_V::Invoke(string&) + pop + + ldstr "GenRetType TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public hidebysig static bool RunTest2() cil managed noinlining + { + .locals init (string res1, string res2, string res3, class GenTestType thisPtr) + + newobj instance void class GenTestType::.ctor() + stloc.s thisPtr + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class B class GenBaseType::MyFunc(string&) + newobj instance void Del_B::.ctor(object, native int) + ldloca.s 0 + callvirt instance class B Del_B::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class C class GenTestType::MyFunc(string&) + newobj instance void Del_C::.ctor(object, native int) + ldloca.s 1 + callvirt instance class C Del_C::Invoke(string&) + pop + + ldstr "C TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public hidebysig static bool RunTest3() cil managed noinlining + { + .locals init (string res1, string res2, string res3, class GenTestType thisPtr) + + newobj instance void class GenTestType::.ctor() + stloc.s thisPtr + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenRetType> class GenBaseType::MyGenFunc(string&) + newobj instance void class Del_GenRetType::.ctor(object, native int) + ldloca.s 0 + callvirt instance class GenRetType> class Del_GenRetType::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + newobj instance void class Del_GenDerive1::.ctor(object, native int) + ldloca.s 1 + callvirt instance class GenDerive1> class Del_GenDerive1::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenDerive3 class GenTestType::MyGenFunc(string&) + newobj instance void class Del_GenDerive3::.ctor(object, native int) + ldloca.s 2 + callvirt instance class GenDerive3 class Del_GenDerive3::Invoke(string&) + pop + + ldstr "GenDerive3 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public hidebysig static bool RunTest4() cil managed noinlining + { + .locals init (string res1, string res2, string res3, class GenTestType thisPtr) + + newobj instance void class GenTestType::.ctor() + stloc.s thisPtr + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenRetType class GenBaseType::MyGenFunc(string&) + newobj instance void class Del_GenRetType_int_object::.ctor(object, native int) + ldloca.s 0 + callvirt instance class GenRetType class Del_GenRetType_int_object::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + newobj instance void class Del_NonGenericDerived1::.ctor(object, native int) + ldloca.s 1 + callvirt instance class NonGenericDerived1 class Del_NonGenericDerived1::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class NonGenericDerived4 class GenTestType::MyGenFunc(string&) + newobj instance void class Del_NonGenericDerived4::.ctor(object, native int) + ldloca.s 2 + callvirt instance class NonGenericDerived4 class Del_NonGenericDerived4::Invoke(string&) + pop + + ldstr "NonGenericDerived4 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public hidebysig static bool RunTest5() cil managed noinlining + { + .locals init (string res1, string res2, string res3, class GenTestType thisPtr) + + newobj instance void class GenTestType::.ctor() + stloc.s thisPtr + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class B class GenBaseType::GenToNonGen(string&) + newobj instance void class Del_B::.ctor(object, native int) + ldloca.s 0 + callvirt instance class B class Del_B::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + newobj instance void class Del_GenToNonGen1::.ctor(object, native int) + ldloca.s 1 + callvirt instance class GenToNonGen1> class Del_GenToNonGen1::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class GenToNonGen3 class GenTestType::GenToNonGen(string&) + newobj instance void class Del_GenToNonGen3::.ctor(object, native int) + ldloca.s 2 + callvirt instance class GenToNonGen3 class Del_GenToNonGen3::Invoke(string&) + pop + + ldstr "GenToNonGen3 TestType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public hidebysig static bool RunTest6() cil managed noinlining + { + .locals init (string res1, string res2, string res3, class GenTestType thisPtr) + + newobj instance void class GenTestType::.ctor() + stloc.s thisPtr + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class B class GenBaseType::NonGenThroughGenFunc(string&) + newobj instance void class Del_B::.ctor(object, native int) + ldloca.s 0 + callvirt instance class B class Del_B::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + newobj instance void class Del_NonGenThroughGen2::.ctor(object, native int) + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class Del_NonGenThroughGen2::Invoke(string&) + pop + + ldloc.s thisPtr + ldloc.s thisPtr + ldvirtftn instance class NonGenThroughGen4 class GenTestType::NonGenThroughGenFunc(string&) + newobj instance void class Del_NonGenThroughGen4::.ctor(object, native int) + ldloca.s 2 + callvirt instance class NonGenThroughGen4 class Del_NonGenThroughGen4::Invoke(string&) + pop + + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method private hidebysig static int32 Main(string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + T1: + call bool CMain::RunTest1() + brtrue.s T2 + ldc.i4.0 + stloc.0 + + T2: + call bool CMain::RunTest2() + brtrue.s T3 + ldc.i4.0 + stloc.0 + + T3: + call bool CMain::RunTest3() + brtrue.s T4 + ldc.i4.0 + stloc.0 + + T4: + call bool CMain::RunTest4() + brtrue.s T5 + ldc.i4.0 + stloc.0 + + T5: + call bool CMain::RunTest5() + brtrue.s T6 + ldc.i4.0 + stloc.0 + + T6: + call bool CMain::RunTest6() + brtrue.s DONE + ldc.i4.0 + stloc.0 + + // ===================================================================================== // + + 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 [System.Runtime]System.Object::.ctor() + ret + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.ilproj new file mode 100644 index 00000000000000..1667d3b14ac0ba --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.il new file mode 100644 index 00000000000000..3a0b2f40158488 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.il @@ -0,0 +1,245 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } + +.assembly extern A { } +.assembly extern B { } +.assembly extern C { } +.assembly extern Dictionary { } +.assembly extern GenRetType { } +.assembly extern GenDerive1 { } +.assembly extern GenDerive2 { } +.assembly extern GenDerive3 { } +.assembly extern NonGenericDerived1 { } +.assembly extern NonGenericDerived2 { } +.assembly extern NonGenericDerived3 { } +.assembly extern NonGenericDerived4 { } +.assembly extern GenToNonGen1 { } +.assembly extern GenToNonGen2 { } +.assembly extern GenToNonGen3 { } +.assembly extern NonGenThroughGen1 { } +.assembly extern NonGenThroughGen2 { } +.assembly extern NonGenThroughGen3 { } +.assembly extern NonGenThroughGen4 { } + +.assembly extern GenBaseType { } +.assembly extern GenTestType { } + +.assembly UnitTestMultiModule { } + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static bool RunTest1() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenRetType TestType.NewFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class [GenTestType]GenTestType::.ctor() + ldloca.s 0 + callvirt instance object class [GenBaseType]GenBaseType::MyFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenRetType TestType.NewFunc1()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest2() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: C TestType.NewFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class [GenTestType]GenTestType::.ctor() + ldloca.s 0 + callvirt instance class [B]B class [GenBaseType]GenBaseType::MyFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "C TestType.NewFunc2()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest3() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenDerive3 TestType.NewGenFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class [GenTestType]GenTestType::.ctor() + ldloca.s 0 + callvirt instance class [GenRetType]GenRetType> class [GenBaseType]GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerive3 TestType.NewGenFunc2()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest4() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: NonGenericDerived4 TestType.NewGenFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class [GenTestType]GenTestType::.ctor() + ldloca.s 0 + callvirt instance class [GenRetType]GenRetType class [GenBaseType]GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenericDerived4 TestType.NewGenFunc1()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest5() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenToNonGen3 TestType.GenToNonGenOverride()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class [GenTestType]GenTestType::.ctor() + ldloca.s 0 + callvirt instance class [B]B class [GenBaseType]GenBaseType::GenToNonGen(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenToNonGen3 TestType.GenToNonGenOverride()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest6() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class [GenTestType]GenTestType::.ctor() + ldloca.s 0 + callvirt instance class [B]B class [GenBaseType]GenBaseType::NonGenThroughGenFunc(string& res) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenThroughGen4 TestType.NonGenThroughGenFunc()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + T1: + call bool CMain::RunTest1() + brtrue.s T2 + ldc.i4.0 + stloc.0 + + T2: + call bool CMain::RunTest2() + brtrue.s T3 + ldc.i4.0 + stloc.0 + + T3: + call bool CMain::RunTest3() + brtrue.s T4 + ldc.i4.0 + stloc.0 + + T4: + call bool CMain::RunTest4() + brtrue.s T5 + ldc.i4.0 + stloc.0 + + T5: + call bool CMain::RunTest5() + brtrue.s T6 + ldc.i4.0 + stloc.0 + + T6: + call bool CMain::RunTest6() + brtrue.s DONE + ldc.i4.0 + stloc.0 + + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.ilproj new file mode 100644 index 00000000000000..f745a3e04ee199 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.ilproj @@ -0,0 +1,35 @@ + + + Exe + BuildAndRun + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.il new file mode 100644 index 00000000000000..75bcddd5de63e8 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.il @@ -0,0 +1,903 @@ +// 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. + +.assembly extern System.Console { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly UnitTest_GVM { } + +// ======================================================================================== +// 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 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Dictionary +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 +{ + .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 extends class NonGenericDerived1 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + +.class public auto ansi beforefieldinit GenToNonGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 +{ + .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 extends class NonGenThroughGen2 +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} + + +// ======================================================================================== +// Main base type with various virtual methods that will be overriden later +// ======================================================================================== + +.class public auto ansi beforefieldinit GenBaseType +{ + .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 + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(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(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(string& res) + { + ldarg.1 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType> MyGenFunc(string& res) + { + ldarg.1 + ldstr "GenRetType> GenBaseType.MyGenFunc()" + stind.ref + newobj instance void class GenRetType>::.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 extends class GenBaseType +{ + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } + + .method public hidebysig newslot virtual instance class NonGenThroughGen2 NonGenThroughGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::NonGenThroughGenFunc<[1]>(string& res) + ldarg.1 + ldstr "NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen1> GenToNonGen(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::GenToNonGen<[1]>(string& res) + ldarg.1 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived1 MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "NonGenericDerived1 GenMiddleType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive1> MyGenFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class GenRetType> class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "GenDerive1> 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 extends class GenMiddleType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen5 NonGenThroughGenFunc(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc<[1]>(string& res) + ldarg.1 + ldstr "NonGenThroughGen5 TestType.NonGenThroughGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGen(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen<[1]>(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGen()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived5 MyGenFunc(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "NonGenericDerived5 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive2 MyGenFunc(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "GenDerive2 TestType.MyGenFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance object class GenBaseType::MyFunc<[1]>(string& res) + ldarg.1 + ldstr "GenRetType TestType.MyFunc()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class C MyFunc(string& res) + { + .custom instance void [System.Runtime]System.Runtime.CompilerServices.PreserveBaseOverridesAttribute::.ctor() = (01 00 00 00) + .override method instance class B class GenBaseType::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 extends class GenMiddleType +{ + // 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(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc<[1]>(string& res) + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid2 extends class GenMiddleType +{ + // Invalid: when comparing 'object' with !!Y in the instantiation + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenOverride(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen<[1]>(string& res) + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid3 extends class GenMiddleType +{ + // Invalid when comparing !!Y and 'object' in instantiation of GenRetType + .method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc<[1]>(string& res) + ldnull + ret + } + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed { ret } +} +.class public auto ansi beforefieldinit Invalid4 extends class GenMiddleType +{ + // Invalid when comparing !!Y and 'string' in instantiation of Dictionary + .method public hidebysig newslot virtual instance class GenDerive3 NewGenFunc2(string& res) + { + .override method instance class GenRetType> class GenBaseType::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 GenTestType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns (when applicable) + // 3) The signature from GenTestType with covariant returns + // And verify that the override on GetTestType is the one that executes + + .method public static bool RunTest1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class GenRetType class GenTestType::MyFunc(string&) + pop + + ldstr "GenRetType TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class C class GenTestType::MyFunc(string&) + pop + + ldstr "C TestType.MyFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class GenDerive2 class GenTestType::MyGenFunc(string&) + pop + + ldstr "GenDerive2 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class NonGenericDerived5 class GenTestType::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived5 TestType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest5() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class GenToNonGen3 class GenTestType::GenToNonGen(string&) + pop + + ldstr "GenToNonGen3 TestType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest6() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenTestType::.ctor() + ldloca.s 2 + callvirt instance class NonGenThroughGen5 class GenTestType::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen5 TestType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + // ============== Test using GenMiddleType ============== // + // These test methods will callvirt each method using: + // 1) The signature from GetBaseType + // 2) The signature from GenMiddleType with covariant returns + // And verify that the override on GenMiddleType is the one that executes + + .method public static bool RunTest_Middle1() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class GenDerive1> class GenMiddleType::MyGenFunc(string&) + pop + + ldstr "GenDerive1> GenMiddleType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle2() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class NonGenericDerived1 class GenMiddleType::MyGenFunc(string&) + pop + + ldstr "NonGenericDerived1 GenMiddleType.MyGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle3() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class GenToNonGen1> class GenMiddleType::GenToNonGen(string&) + pop + + ldstr "GenToNonGen1> GenMiddleType.GenToNonGen()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + ret + } + + .method public static bool RunTest_Middle4() noinlining + { + .locals init (string res1, string res2, string res3) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string&) + pop + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 1 + callvirt instance class NonGenThroughGen2 class GenMiddleType::NonGenThroughGenFunc(string&) + pop + + ldstr "NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + ldloc.0 + ldloc.1 + ldloc.2 + ldnull + call bool CMain::CheckResults(string,string,string,string,string) + 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::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunInvalidTest2() noinlining + { + newobj instance void class Invalid2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunInvalidTest3() noinlining + { + newobj instance void class Invalid3::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunInvalidTest4() noinlining + { + newobj instance void class Invalid4::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + // ===================================================================================== // + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + .locals init ( bool result ) + + ldc.i4.1 + stloc.0 + + T1: + call bool CMain::RunTest1() + brtrue.s T2 + ldc.i4.0 + stloc.0 + + T2: + call bool CMain::RunTest2() + brtrue.s T3 + ldc.i4.0 + stloc.0 + + T3: + call bool CMain::RunTest3() + brtrue.s T4 + ldc.i4.0 + stloc.0 + + T4: + call bool CMain::RunTest4() + brtrue.s T5 + ldc.i4.0 + stloc.0 + + T5: + call bool CMain::RunTest5() + brtrue.s T6 + ldc.i4.0 + stloc.0 + + T6: + call bool CMain::RunTest6() + brtrue.s M1 + ldc.i4.0 + stloc.0 + + M1: + call bool CMain::RunTest_Middle1() + brtrue.s M2 + ldc.i4.0 + stloc.0 + + M2: + call bool CMain::RunTest_Middle2() + brtrue.s M3 + ldc.i4.0 + stloc.0 + + M3: + call bool CMain::RunTest_Middle3() + brtrue.s M4 + ldc.i4.0 + stloc.0 + + M4: + call bool CMain::RunTest_Middle4() + brtrue.s INVALID1 + 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 + + 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 + } +} diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.ilproj new file mode 100644 index 00000000000000..6dbb26234d34e0 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 8fe6a6dca457c8..85538c671c8ab2 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -633,6 +633,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PreserveBaseOverridesAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PreserveBaseOverridesAttribute.cs new file mode 100644 index 00000000000000..6f45c2d95a23cf --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PreserveBaseOverridesAttribute.cs @@ -0,0 +1,11 @@ +// 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. + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class PreserveBaseOverridesAttribute : Attribute + { + } +} diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 52b631512e1da7..9a51bfe8e107ec 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -9151,6 +9151,11 @@ public void OnCompleted(System.Action continuation) { } public void UnsafeOnCompleted(System.Action continuation) { } } } + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public sealed class PreserveBaseOverridesAttribute : Attribute + { + public PreserveBaseOverridesAttribute() {} + } } namespace System.Runtime.ConstrainedExecution {