diff --git a/docs/design/features/covariant-return-methods.md b/docs/design/features/covariant-return-methods.md new file mode 100644 index 00000000000000..817af3eaea377b --- /dev/null +++ b/docs/design/features/covariant-return-methods.md @@ -0,0 +1,74 @@ +# 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 more derived reference type than the method it overrides. Covariant return methods can only be described through MethodImpl records, and as an initial implementation, will have the following limitations: +1. Covariant return methods will only be applicable to methods on reference types: the MethodDecl and MethodImpl records can only be on reference types. Methods on interfaces will not be supported. +2. Return types in covariant return methods can only be reference types: covariant interface return types are not supported. + +Supporting interfaces comes with many complications (ex: interface equivalence, default interface methods, variance on generic interfaces, etc...), which is why the feature will initially only support classes. + +MethodImpl checking will allow a return type to vary as long as the override is compatible with the return type of the method overriden (i.e. a derived type). + +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 `ValidateMethodImplRemainsInEffectAttribute` 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. In other words, when a MethodImpl on type A overrides some method using a derived return type in the signature, any type deriving from A will be allowed to have a MethodImpl record that overrides the same method as long as the return type used in the signature is the same or more derived than the return type used in the MethodImpl signature on type A. 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 + +### Signature Checking + +Signature checking for MethodImpl is done through the `MetaSig::CompareElementType` method, which is called from various places in the runtime when comparing method signatures. This method compares the signatures of two types, and will now take a boolean flag that would allow for derived type checking behavior. The boolean flag will be set to `TRUE` appropriately during comparison of the return type signatures between a MethodImpl and MethodDecl records. + +The type signature checking algorithm will perform the following: +1. Traverse and compare the signatures for `type1` and `type2` recursively. +2. If the signatures mismatch at any given point, and the current element type for `type2` is `ELEMENT_TYPE_CLASS` or `ELEMENT_TYPE_GENERICINST`: + + Check for covariant return eligibility + + Compute the parent type's signature and parent type's generic substitution of `type2` + + Perform a recursive call to re-compare `type1` with the new parent type signature of `type2`. + +Note: if `ELEMENT_TYPE_INTERNAL` is encountered in either of the type signatures, both types will be fully loaded and compared for compatibility. + +### VTable Slot Checking + +This will be done during the call to `SetupMethodTable2` where we propagate inheritance (see methodtablebuilder.cpp around line 10642). TODO: add algorithm description here. + +### [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/inc/sigbuilder.h b/src/coreclr/src/inc/sigbuilder.h index c1ad67af0f2e34..938e50d8f31346 100644 --- a/src/coreclr/src/inc/sigbuilder.h +++ b/src/coreclr/src/inc/sigbuilder.h @@ -74,6 +74,8 @@ class SigBuilder } void AppendBlob(const PVOID pBlob, SIZE_T cbBlob); + + void AppendSignature(const PCCOR_SIGNATURE pSig, const PCCOR_SIGNATURE pSigEnd); }; #endif // _SIGBUILDER_H_ diff --git a/src/coreclr/src/utilcode/sigbuilder.cpp b/src/coreclr/src/utilcode/sigbuilder.cpp index 922e1613ca3697..58d0c374cf66a0 100644 --- a/src/coreclr/src/utilcode/sigbuilder.cpp +++ b/src/coreclr/src/utilcode/sigbuilder.cpp @@ -119,6 +119,22 @@ void SigBuilder::AppendBlob(const PVOID pBlob, SIZE_T cbBlob) m_dwLength += (DWORD)cbBlob; } +void SigBuilder::AppendSignature(const PCCOR_SIGNATURE pSig, const PCCOR_SIGNATURE pSigEnd) +{ + STANDARD_VM_CONTRACT; + + // Overflow checks + if (pSigEnd < pSig) + ThrowOutOfMemory(); + + DWORD cbSig = (DWORD)(pSigEnd - pSig); + + Ensure(cbSig); + memcpy(&m_pBuffer[m_dwLength], pSig, cbSig); + + m_dwLength += cbSig; +} + void SigBuilder::Grow(SIZE_T cbMin) { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/src/vm/class.cpp b/src/coreclr/src/vm/class.cpp index c87c21d1515952..53233207379e28 100644 --- a/src/coreclr/src/vm/class.cpp +++ b/src/coreclr/src/vm/class.cpp @@ -967,12 +967,90 @@ void ClassLoader::LoadExactParents(MethodTable *pMT) MethodTableBuilder::CopyExactParentSlots(pMT, pApproxParentMT); + if (!pMT->IsInterface() && !pMT->IsValueType()) + { + ValidateMethodImplRemainsInEffect(pMT); + } + // We can now mark this type as having exact parents pMT->SetHasExactParent(); RETURN; } +/*static*/ +void ClassLoader::ValidateMethodImplRemainsInEffect(MethodTable* pMT) +{ + CONTRACT_VOID + { + STANDARD_VM_CHECK; + PRECONDITION(CheckPointer(pMT)); + PRECONDITION(!pMT->IsInterface() && !pMT->IsValueType()); + } + CONTRACT_END; + + MethodTable* pParentMT = pMT->GetParentMethodTable(); + if (pParentMT == NULL) + RETURN; + + BYTE* pVal = NULL; + ULONG cbVal = 0; + HRESULT hr = pMT->GetCustomAttribute(WellKnownAttribute::ValidateMethodImplRemainsInEffectAttribute, (const void**)&pVal, &cbVal); + if (hr != S_OK) + RETURN; + + for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) + { + MethodDesc* pMD = pMT->GetMethodDescForSlot(i); + MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); + + DWORD originalIndex = pMD->GetSlot(); + if (originalIndex == i) + continue; + + DWORD originalIndexParent = pParentMD->GetSlot(); + if (originalIndex == originalIndexParent) + continue; + + // 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); + + // Type1 has to be equal to Type2, or a base type of Type2 (covariant returns) + + if (!MetaSig::CompareTypeHandles(hType1, hType2, TRUE /* allowDerivedClass */ )) + { + 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); + } + } + + RETURN; +} + //******************************************************************************* // 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..fb569e93c7c130 100644 --- a/src/coreclr/src/vm/clsload.hpp +++ b/src/coreclr/src/vm/clsload.hpp @@ -969,10 +969,12 @@ 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 ValidateMethodImplRemainsInEffect(MethodTable* pMT); + // 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/methodtablebuilder.cpp b/src/coreclr/src/vm/methodtablebuilder.cpp index 14ccfd4371061d..bbcf4e5183be85 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); } //******************************************************************************* @@ -2365,6 +2367,41 @@ MethodTableBuilder::EnumerateMethodImpls() { BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_BODY); } + + BOOL allowCovariantReturn = FALSE; + if (!IsValueClass() && !IsInterface()) + { + // Note on covariant return types: right now we only support covariant returns for MethodImpls on + // class, where the MethodDecl is also on a class. Interface methods are not supported. In order to allow + // covariant return type checking in the call to CompareMethodSigs, we need to verify whether the type with + // the MethodDecl is an interface. + // We will also allow covariant return types if both the MethodImpl and MethodDecl are not on the same type. + + hr = pMDInternalImport->GetParentToken(theDecl, &tkParent); + if (FAILED(hr)) + BuildMethodTableThrowException(hr, *bmtError); + + if (GetCl() != tkParent) + { + CONTRACT_VIOLATION(LoadsTypeViolation); + MethodTable* pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing( + GetModule(), + tkParent, + &bmtGenerics->typeContext, + ClassLoader::ThrowIfNotFound, + ClassLoader::PermitUninstDefOrRef, + ClassLoader::LoadTypes, + CLASS_LOAD_APPROXPARENTS).GetMethodTable()->GetCanonicalMethodTable(); + + CONSISTENCY_CHECK(pDeclMT != NULL); + + if (!pDeclMT->IsInterface() && !pDeclMT->IsValueType()) + { + allowCovariantReturn = TRUE; + } + } + } + // Can't use memcmp because there may be two AssemblyRefs // in this scope, pointing to the same assembly, etc.). if (!MetaSig::CompareMethodSigs( @@ -2375,7 +2412,8 @@ MethodTableBuilder::EnumerateMethodImpls() pSigBody, cbSigBody, GetModule(), - NULL)) + NULL, + allowCovariantReturn)) { BuildMethodTableThrowException(IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH); } @@ -3648,10 +3686,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); } @@ -5818,6 +5856,7 @@ MethodTableBuilder::ProcessMethodImpls() cbCurMDSig, pCurMD->GetModule(), &pCurDeclType->GetSubstitution(), + FALSE, iPass == 0 ? &newVisited : NULL)) { declMethod = (*bmtParent->pSlotTable)[pCurMD->GetSlot()].Decl(); @@ -6118,6 +6157,7 @@ VOID MethodTableBuilder::MethodImplCompareSignatures( bmtMethodHandle hDecl, bmtMethodHandle hImpl, + BOOL allowCovariantReturn, DWORD dwConstraintErrorCode) { CONTRACTL { @@ -6131,7 +6171,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 +6419,7 @@ MethodTableBuilder::PlaceLocalDeclarationOnClass( MethodImplCompareSignatures( pDecl, pImpl, + FALSE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_LOCAL_METHOD_IMPL); /////////////////////////////// @@ -6450,6 +6491,7 @@ VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass( MethodImplCompareSignatures( pDecl, pImpl, + FALSE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL); /////////////////////////////// @@ -6552,6 +6594,7 @@ VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface( MethodImplCompareSignatures( hDecl, bmtMethodHandle(pImpl), + FALSE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL); /////////////////////////////// @@ -6600,6 +6643,7 @@ MethodTableBuilder::PlaceParentDeclarationOnClass( MethodImplCompareSignatures( pDecl, pImpl, + TRUE /* allowCovariantReturn */, IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_PARENT_METHOD_IMPL); //////////////////////////////// @@ -7230,7 +7274,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..7a07533ab42f59 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) @@ -2739,6 +2740,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 58b8d86f5b5c86..7d8ade1d3b628f 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 @@ -3002,7 +3002,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 @@ -3562,6 +3562,255 @@ 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 two type handles for equality, or that hType2 is a derived class of hType1. +// The derived type check is used by the covariant returns feature. +// +// static +BOOL MetaSig::CompareTypeHandles(TypeHandle hType1, TypeHandle hType2, BOOL allowDerivedClass) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + PRECONDITION(!hType1.IsNull() && !hType2.IsNull()); + } + CONTRACTL_END; + + if (hType1 == hType2) + return TRUE; + + if (!allowDerivedClass) + return FALSE; + + if (hType1.IsNull() || hType2.IsValueType()) + { + return FALSE; + } + + while (!hType2.IsNull()) + { + if (hType1 == hType2) + return TRUE; + hType2 = hType2.GetParent(); + } + + return FALSE; +} + +//--------------------------------------------------------------------------------------- +// +// Check if a type signature is eligible for covariant return types. +// +// static +BOOL MetaSig::IsTypeSignatureEligibleForCovariantReturnType( + PCCOR_SIGNATURE pSig, + PCCOR_SIGNATURE pEndSig, + Module* pModule, + BOOL isBaseTypeSig, + mdToken* pTypeDefToken, /* = NULL */ + Module** ppTypeDefModule, /* = NULL */ + mdToken* pParentTypeDefOrRefOrSpecToken) /* = NULL */ +{ + CorElementType elementType = ELEMENT_TYPE_MAX; + + IfFailThrow(CorSigUncompressElementType_EndPtr(pSig, pEndSig, &elementType)); + + // System.Object is always eligible as a base type since all reference types derive from it + if (isBaseTypeSig && elementType == ELEMENT_TYPE_OBJECT) + { + return TRUE; + } + + if (elementType == ELEMENT_TYPE_GENERICINST) + { + IfFailThrow(CorSigUncompressElementType_EndPtr(pSig, pEndSig, &elementType)); + } + + // Getting the parent siganture is only applicable to classes, so exclude anything else + if (elementType != ELEMENT_TYPE_CLASS) + { + return FALSE; + } + + mdToken typeRefOrDefToken; + IfFailThrow(CorSigUncompressToken_EndPtr(pSig, pEndSig, &typeRefOrDefToken)); + + // Ensure we are working with the typedef token + mdToken typeDefToken; + Module* pFoundModule; + if (!ClassLoader::ResolveTokenToTypeDefThrowing(pModule, typeRefOrDefToken, &pFoundModule, &typeDefToken)) + { + return FALSE; + } + + DWORD attr; + mdToken parentTypeDefOrRefOrSpecToken; + IfFailThrow(pFoundModule->GetMDImport()->GetTypeDefProps(typeDefToken, &attr, &parentTypeDefOrRefOrSpecToken)); + + // Check the validity of the parent type token if this is a signature of a derived type. + if(!isBaseTypeSig && !pFoundModule->GetMDImport()->IsValidToken(parentTypeDefOrRefOrSpecToken)) + { + return FALSE; + } + + if (ppTypeDefModule != NULL) + *ppTypeDefModule = pFoundModule; + if (pTypeDefToken != NULL) + *pTypeDefToken = typeDefToken; + if (pParentTypeDefOrRefOrSpecToken != NULL) + *pParentTypeDefOrRefOrSpecToken = parentTypeDefOrRefOrSpecToken; + + return TRUE; +} + +//--------------------------------------------------------------------------------------- +// +// Compute the base type token (it will either be a typedef or typeref token), and returns the +// module where that base type token is declared. +// +// static +BOOL MetaSig::ComputeBaseTypeTokenAndModule( + mdToken tk, + Module* pModule, + mdToken* pBaseTypeDefOrRefToken, + Module** ppBaseTypeTokenModule) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + INJECT_FAULT(COMPlusThrowOM()); + PRECONDITION(CheckPointer(pModule)); + PRECONDITION(TypeFromToken(tk) == mdtTypeRef || TypeFromToken(tk) == mdtTypeDef); + MODE_ANY; + } + CONTRACTL_END; + + // Ensure we are working with the typedef token + mdToken typeDefToken; + Module* pFoundModule; + if (!ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pFoundModule, &typeDefToken)) + return FALSE; + + DWORD attr; + mdToken tkTypeParent; + IfFailThrow(pFoundModule->GetMDImport()->GetTypeDefProps(typeDefToken, &attr, &tkTypeParent)); + + if (!pFoundModule->GetMDImport()->IsValidToken(tkTypeParent)) + return FALSE; + + if (TypeFromToken(tkTypeParent) == mdtTypeSpec) + { + ULONG cbSig; + PCCOR_SIGNATURE pSig; + IfFailThrow(pFoundModule->GetMDImport()->GetSigFromToken(tkTypeParent, &cbSig, &pSig)); + + PCCOR_SIGNATURE pEndSig = pSig + cbSig; + CorElementType elementType = ELEMENT_TYPE_MAX; + + IfFailThrow(CorSigUncompressElementType_EndPtr(pSig, pEndSig, &elementType)); + if (elementType == ELEMENT_TYPE_GENERICINST) + { + IfFailThrow(CorSigUncompressElementType_EndPtr(pSig, pEndSig, &elementType)); + } + + if (elementType != ELEMENT_TYPE_CLASS) + return FALSE; + + IfFailThrow(CorSigUncompressToken_EndPtr(pSig, pEndSig, pBaseTypeDefOrRefToken)); + *ppBaseTypeTokenModule = pFoundModule; + return TRUE; + } + else if (TypeFromToken(tkTypeParent) == mdtTypeRef || TypeFromToken(tkTypeParent) == mdtTypeDef) + { + *pBaseTypeDefOrRefToken = tkTypeParent; + *ppBaseTypeTokenModule = pFoundModule; + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------------------- +// +// Extract the parent type's signature and stubstitution from the input type signature +// +// static +BOOL MetaSig::GetParentSignatureAndSubstitution( + PCCOR_SIGNATURE pSig, + PCCOR_SIGNATURE pEndSig, + Module* pModule, + const Substitution* pSubst, + Module** ppParentTypeModule, + SigBuilder& parentTypeSig, + Substitution& parentTypeSubst) +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + INJECT_FAULT(COMPlusThrowOM()); + PRECONDITION(CheckPointer(pModule)); + PRECONDITION(CheckPointer(ppParentTypeModule)); + MODE_ANY; + } + CONTRACTL_END; + + mdToken typeDefToken; + mdToken parentTypeDefOrRefOrSpecToken; + Module* pTypeDefModule; + if (!IsTypeSignatureEligibleForCovariantReturnType(pSig, pEndSig, pModule, FALSE, &typeDefToken, &pTypeDefModule, &parentTypeDefOrRefOrSpecToken)) + { + return FALSE; + } + + // If the parent type token is a TypeSpec token, we need to load the substitution from the signature and + // chain it to the existing substitution (if there is one) + + if (TypeFromToken(parentTypeDefOrRefOrSpecToken) == mdtTypeSpec) + { + ULONG cbParentTypeSig; + PCCOR_SIGNATURE pParentTypeSig; + IfFailThrow(pTypeDefModule->GetMDImport()->GetSigFromToken(parentTypeDefOrRefOrSpecToken, &cbParentTypeSig, &pParentTypeSig)); + + parentTypeSig.AppendSignature(pParentTypeSig, pParentTypeSig + cbParentTypeSig); + parentTypeSubst = Substitution(parentTypeDefOrRefOrSpecToken, pTypeDefModule, pSubst); + *ppParentTypeModule = pTypeDefModule; + } + else if (TypeFromToken(parentTypeDefOrRefOrSpecToken) == mdtTypeDef || TypeFromToken(parentTypeDefOrRefOrSpecToken) == mdtTypeRef) + { + // We need to special case type System.Object since it has its own element type. We don't need to do the same for type String + // because it's a sealed type, and no other class can derive from it. + + Module* pParentModule; + mdTypeDef parentTypeDefToken; + BOOL resolvedToken = ClassLoader::ResolveTokenToTypeDefThrowing(pTypeDefModule, parentTypeDefOrRefOrSpecToken, &pParentModule, &parentTypeDefToken); + + if (resolvedToken && pParentModule == g_pObjectClass->GetModule() && parentTypeDefToken == g_pObjectClass->GetCl()) + { + parentTypeSig.AppendElementType(ELEMENT_TYPE_OBJECT); + } + else + { + parentTypeSig.AppendElementType(ELEMENT_TYPE_CLASS); + parentTypeSig.AppendToken(parentTypeDefOrRefOrSpecToken); + } + + parentTypeSubst = pSubst == NULL ? Substitution() : Substitution(*pSubst); + *ppParentTypeModule = pTypeDefModule; + } + else + { + return FALSE; + } + + return TRUE; +} + //--------------------------------------------------------------------------------------- // // Compare the next elements in two sigs. @@ -3577,6 +3826,7 @@ MetaSig::CompareElementType( Module * pModule2, const Substitution * pSubst1, const Substitution * pSubst2, + BOOL allowDerivedClass, TokenPairList * pVisited) // = NULL { CONTRACTL @@ -3586,7 +3836,10 @@ MetaSig::CompareElementType( INJECT_FAULT(COMPlusThrowOM()); MODE_ANY; } - CONTRACTL_END + CONTRACTL_END; + + PCCOR_SIGNATURE pSig1Start = pSig1; + PCCOR_SIGNATURE pSig2Start = pSig2; redo: // We jump here if the Type was a ET_CMOD prefix. @@ -3621,6 +3874,7 @@ MetaSig::CompareElementType( pSubst2->GetModule(), pSubst1, pSubst2->GetNext(), + allowDerivedClass, pVisited); } @@ -3648,6 +3902,7 @@ MetaSig::CompareElementType( pModule2, pSubst1->GetNext(), pSubst2, + allowDerivedClass, pVisited); } @@ -3686,21 +3941,21 @@ MetaSig::CompareElementType( { if ((Type1 == ELEMENT_TYPE_INTERNAL) || (Type2 == ELEMENT_TYPE_INTERNAL)) { - TypeHandle hInternal; + TypeHandle hType1, hType2; CorElementType eOtherType; Module * pOtherModule; // 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 **)&hType1)); eOtherType = Type2; pOtherModule = pModule2; } else { - IfFailThrow(CorSigUncompressPointer_EndPtr(pSig2, pEndSig2, (void **)&hInternal)); + IfFailThrow(CorSigUncompressPointer_EndPtr(pSig2, pEndSig2, (void **)&hType2)); eOtherType = Type1; pOtherModule = pModule1; @@ -3711,11 +3966,30 @@ MetaSig::CompareElementType( { case ELEMENT_TYPE_OBJECT: { - return (hInternal.AsMethodTable() == g_pObjectClass); + if (Type1 == ELEMENT_TYPE_INTERNAL) + { + // Type2 is ELEMENT_TYPE_OBJECT. Return true only if Type1 is also type object. + return hType1.AsMethodTable() == g_pObjectClass; + } + else + { + // Type1 is ELEMENT_TYPE_OBJECT. Return true if Type2 is type System.Object or any other class + // if allowDerivedClass is TRUE. + if (hType2.AsMethodTable() == g_pObjectClass) + { + return TRUE; + } + else + { + return allowDerivedClass ? CompareTypeHandles(TypeHandle(g_pObjectClass), hType2, TRUE) : FALSE; + } + } } case ELEMENT_TYPE_STRING: { - return (hInternal.AsMethodTable() == g_pStringClass); + return Type1 == ELEMENT_TYPE_INTERNAL ? + hType1.AsMethodTable() == g_pStringClass : + hType2.AsMethodTable() == g_pStringClass; } case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: @@ -3724,20 +3998,23 @@ MetaSig::CompareElementType( if (Type1 == ELEMENT_TYPE_INTERNAL) { IfFailThrow(CorSigUncompressToken_EndPtr(pSig2, pEndSig2, &tkOther)); + hType2 = ClassLoader::LoadTypeDefOrRefThrowing( + pOtherModule, + tkOther, + ClassLoader::ReturnNullIfNotFound, + ClassLoader::FailIfUninstDefOrRef); } else { IfFailThrow(CorSigUncompressToken_EndPtr(pSig1, pEndSig1, &tkOther)); + hType1 = ClassLoader::LoadTypeDefOrRefThrowing( + pOtherModule, + tkOther, + ClassLoader::ReturnNullIfNotFound, + ClassLoader::FailIfUninstDefOrRef); } - TypeHandle hOtherType; - - hOtherType = ClassLoader::LoadTypeDefOrRefThrowing( - pOtherModule, - tkOther, - ClassLoader::ReturnNullIfNotFound, - ClassLoader::FailIfUninstDefOrRef); - return (hInternal == hOtherType); + return CompareTypeHandles(hType1, hType2, allowDerivedClass); } default: { @@ -3747,7 +4024,57 @@ MetaSig::CompareElementType( } else { - return FALSE; // types must be the same + if (allowDerivedClass) + { + // Quick check of Type1 for eligibility before starting to traverse base type chain in Type2 + if (!IsTypeSignatureEligibleForCovariantReturnType(pSig1Start, pEndSig1, pModule1, TRUE)) + { + return FALSE; + } + + // Obvious case: string derives from object. + if (Type1 == ELEMENT_TYPE_OBJECT && Type2 == ELEMENT_TYPE_STRING) + { + return TRUE; + } + + Module* pParentTypeModule; + Substitution parentTypeSubst; + SigBuilder parentTypeSigBuilder; + if (GetParentSignatureAndSubstitution(pSig2Start, pEndSig2, pModule2, pSubst2, &pParentTypeModule, parentTypeSigBuilder, parentTypeSubst)) + { + DWORD cbParentTypeSig; + PCCOR_SIGNATURE pParentTypeSig = (PCCOR_SIGNATURE)parentTypeSigBuilder.GetSignature(&cbParentTypeSig); + PCCOR_SIGNATURE pParentTypeSigEnd = pParentTypeSig + cbParentTypeSig; + + // + // Given that we're going to restart the current type comparaison between Type1 and the base type of Type2, and + // given that the signature pointers for both types are passed by reference to get updated during each call to + // CompareElementType(), we need to make some adjustments to the two signature pointers: + // 1) We need to reset pSig1 to the begining of the current signature of Type1 to compare it with the newly + // computed basetype signature. + // 2) Given that we will be using the base type signature as Type2, we also need to skip one element from the + // original signature for Type2. + // + SigParser parser = SigParser(pSig2Start); + IfFailThrow(parser.SkipExactlyOne()); + pSig1 = pSig1Start; + pSig2 = parser.GetPtr(); + + return CompareElementType( + pSig1, + pParentTypeSig, + pEndSig1, + pParentTypeSigEnd, + pModule1, + pParentTypeModule, + pSubst1, + parentTypeSubst.GetInst().IsNull() ? NULL : &parentTypeSubst, + allowDerivedClass); + } + } + + return FALSE; } } @@ -3831,6 +4158,7 @@ MetaSig::CompareElementType( pModule2, pSubst1, pSubst2, + FALSE, pVisited)) { return FALSE; @@ -3846,7 +4174,75 @@ MetaSig::CompareElementType( IfFailThrow(CorSigUncompressToken_EndPtr(pSig1, pEndSig1, &tk1)); IfFailThrow(CorSigUncompressToken_EndPtr(pSig2, pEndSig2, &tk2)); - return CompareTypeTokens(tk1, tk2, pModule1, pModule2, pVisited); + if (CompareTypeTokens(tk1, tk2, pModule1, pModule2, pVisited)) + { + return TRUE; + } + + if (allowDerivedClass && Type1 == ELEMENT_TYPE_CLASS) + { + // + // We need to check if Type2 derives from Type1. Note that if Type1 is a generic type, + // we cannot check for inheritance here because we need to properly keep track of substitutions. + // + // Here's an example: + // class Class0 { } + // class Class1 : Class0 { } + // class Class2 : Class1 { } + // class Class3 : Class2 { } + // class Class4 : Class3{ } + // + // Here, we need to check if Class4 derives from Class0 + // + // In that example, if we just look at the typedef tokens for Class0 and Class4, and traverse the + // parent chain of Class4 to check if it derives from Class0, we would be always returning true, which + // is wrong. Here's a counter example: if Class2 was declared as 'Class2 : Class1', + // then Class4 would be deriving from Class0, and not from Class0. + // + // Therefore, we need to keep track of the substitutions: + // A -> ARG1 -> T -> int32 + // B -> ARG2 -> int16 + // + // To handle that case, we need to compute the base type *AND* base type substitution chain of type2, and + // recompare that with type1. If type1 is generic, we'll return return FALSE here, so that we can properly + // handle this scenario correctly under ELEMENT_TYPE_GENERICINST. + // + + // First, check if Type1 is eligible for covariant returns + + mdToken typeDefToken1; + Module* pTypeDefModule1; + if (!IsTypeSignatureEligibleForCovariantReturnType(pSig1Start, pEndSig1, pModule1, TRUE, &typeDefToken1, &pTypeDefModule1)) + { + return FALSE; + } + + // Second, check if Type1 is generic. If so, we'll return FALSE here, and have that handled under ELEMENT_TYPE_GENERICINST + + HENUMInternal hEnumGenericPars; + IfFailThrow(pTypeDefModule1->GetMDImport()->EnumInit(mdtGenericParam, typeDefToken1, &hEnumGenericPars)); + if (pTypeDefModule1->GetMDImport()->EnumGetCount(&hEnumGenericPars) != 0) + { + return FALSE; + } + + // Finally, walk the base type chain of Type2 to check if it derives from Type1. At this point, we don't need to + // worry about generic substitutions because we know that Type1 is non-generic. + + mdToken baseType2Token; + Module* pBaseType2Module; + while (ComputeBaseTypeTokenAndModule(tk2, pModule2, &baseType2Token, &pBaseType2Module) && !(baseType2Token == tk2 && pBaseType2Module == pModule2)) + { + tk2 = baseType2Token; + pModule2 = pBaseType2Module; + if (CompareTypeTokens(tk1, tk2, pModule1, pModule2, pVisited)) + { + return TRUE; + } + } + } + + return FALSE; } case ELEMENT_TYPE_FNPTR: @@ -3890,6 +4286,7 @@ MetaSig::CompareElementType( pModule2, pSubst1, pSubst2, + FALSE, &newVisited)) { return FALSE; @@ -3918,8 +4315,54 @@ MetaSig::CompareElementType( pModule2, pSubst1, pSubst2, + allowDerivedClass, &newVisitedAlwaysForbidden)) { + if (allowDerivedClass) + { + // Quick check of Type1 for eligibility before starting to traverse base type chain in Type2 + if (!IsTypeSignatureEligibleForCovariantReturnType(pSig1Start, pEndSig1, pModule1, TRUE)) + { + return FALSE; + } + + Module* pParentTypeModule; + Substitution parentTypeSubst; + SigBuilder parentTypeSigBuilder; + if (GetParentSignatureAndSubstitution(pSig2Start, pEndSig2, pModule2, pSubst2, &pParentTypeModule, parentTypeSigBuilder, parentTypeSubst)) + { + DWORD cbParentTypeSig; + PCCOR_SIGNATURE pParentTypeSig = (PCCOR_SIGNATURE)parentTypeSigBuilder.GetSignature(&cbParentTypeSig); + PCCOR_SIGNATURE pParentTypeSigEnd = pParentTypeSig + cbParentTypeSig; + + // + // Given that we're going to restart the current type comparaison between Type1 and the base type of Type2, and + // given that the signature pointers for both types are passed by reference to get updated during each call to + // CompareElementType(), we need to make some adjustments to the two signature pointers: + // 1) We need to reset pSig1 to the begining of the current signature of Type1 to compare it with the newly + // computed basetype signature. + // 2) Given that we will be using the base type signature as Type2, we also need to skip one element from the + // original signature for Type2. + // + SigParser parser = SigParser(pSig2Start); + IfFailThrow(parser.SkipExactlyOne()); + pSig1 = pSig1Start; + pSig2 = parser.GetPtr(); + + return CompareElementType( + pSig1, + pParentTypeSig, + pEndSig1, + pParentTypeSigEnd, + pModule1, + pParentTypeModule, + pSubst1, + parentTypeSubst.GetInst().IsNull() ? NULL : &parentTypeSubst, + allowDerivedClass, + &newVisitedAlwaysForbidden); + } + } + return FALSE; } @@ -3943,6 +4386,7 @@ MetaSig::CompareElementType( pModule2, pSubst1, pSubst2, + FALSE, &newVisited)) { return FALSE; @@ -3971,6 +4415,7 @@ MetaSig::CompareElementType( pModule2, pSubst1, pSubst2, + FALSE, pVisited)) { return FALSE; @@ -4051,7 +4496,7 @@ MetaSig::CompareElementType( IfFailThrow(CorSigUncompressPointer_EndPtr(pSig1, pEndSig1, (void **)&hType1)); IfFailThrow(CorSigUncompressPointer_EndPtr(pSig2, pEndSig2, (void **)&hType2)); - return (hType1 == hType2); + return CompareTypeHandles(hType1, hType2, allowDerivedClass); } } // switch // Unreachable @@ -4125,6 +4570,7 @@ MetaSig::CompareTypeDefsUnderSubstitutions( pSubst2->GetModule(), pSubst1->GetNext(), pSubst2->GetNext(), + FALSE, pVisited)) { return FALSE; @@ -4232,7 +4678,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; @@ -4257,6 +4703,7 @@ MetaSig::CompareMethodSigs( DWORD cSig2, Module * pModule2, const Substitution * pSubst2, + BOOL allowCovariantReturn, TokenPairList * pVisited) //= NULL { CONTRACTL @@ -4293,6 +4740,33 @@ MetaSig::CompareMethodSigs( return FALSE; } + // + // If we are comparing the return type signatures and allow for covariant returns, + // we need to check if the return type on the second signature is a generic type, + // and if so, chain its generic instantiation arguments to the substitution chain. + // This is necessary in case we need to compute the base type signature of the second + // type's signature, and compare that to the first type's signature, to allow for + // derived types. + // + SigPointer instArgSignature; + Substitution instArgsSubstitution; + if (allowCovariantReturn) + { + MetaSig metaSig2(pSig2, (DWORD)(pEndSig2 - pSig2), pModule2, NULL); + SigParser parser(metaSig2.GetReturnProps()); + + CorElementType returnElementType; + IfFailThrow(parser.GetElemType(&returnElementType)); + + if (returnElementType == ELEMENT_TYPE_GENERICINST) + { + IfFailThrow(parser.SkipExactlyOne()); // Skip generic type definition signature + IfFailThrow(parser.GetData(NULL)); // Skip number of generic arguments + instArgSignature = SigPointer(parser.GetPtr()); + instArgsSubstitution = Substitution(pModule2, instArgSignature, pSubst2); + } + } + __int8 callConv = *pSig1; pSig1++; @@ -4360,7 +4834,8 @@ MetaSig::CompareMethodSigs( pModule1, pModule2, pSubst1, - pSubst2, + (i == 0 && allowCovariantReturn) ? &instArgsSubstitution : pSubst2, + i == 0 && allowCovariantReturn, pVisited)) { return FALSE; @@ -4385,7 +4860,8 @@ MetaSig::CompareMethodSigs( pModule1, pModule2, pSubst1, - pSubst2, + (i == 0 && allowCovariantReturn) ? &instArgsSubstitution : pSubst2, + i == 0 && allowCovariantReturn, pVisited)) { return FALSE; @@ -4426,7 +4902,7 @@ BOOL MetaSig::CompareFieldSigs( pEndSig1 = pSig1 + cSig1; pEndSig2 = pSig2 + cSig2; - return(CompareElementType(++pSig1, ++pSig2, pEndSig1, pEndSig2, pModule1, pModule2, NULL, NULL, pVisited)); + return(CompareElementType(++pSig1, ++pSig2, pEndSig1, pEndSig2, pModule1, pModule2, NULL, NULL, FALSE, pVisited)); } #ifndef DACCESS_COMPILE @@ -4668,7 +5144,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, FALSE, pVisited); } // MetaSig::CompareTypeDefOrRefOrSpec /* static */ @@ -5253,6 +5729,7 @@ MetaSig::GetUnmanagedCallingConvention( *pPinvokeMapOut = (CorPinvokeMap)0; return TRUE; } +#endif // #ifndef DACCESS_COMPILE //--------------------------------------------------------------------------------------- // @@ -5353,8 +5830,6 @@ void Substitution::DeleteChain() delete this; } -#endif // #ifndef DACCESS_COMPILE - //--------------------------------------------------------------------------------------- // // static diff --git a/src/coreclr/src/vm/siginfo.hpp b/src/coreclr/src/vm/siginfo.hpp index e294239670520f..cb51cba1e4f94e 100644 --- a/src/coreclr/src/vm/siginfo.hpp +++ b/src/coreclr/src/vm/siginfo.hpp @@ -970,12 +970,43 @@ class MetaSig //------------------------------------------------------------------ CorElementType GetByRefType(TypeHandle* pTy) const; + // Compare two type handles for equality. If the two types are not equal, and allowDerivedClass + // is TRUE, return true if hType2 derives from hType1. This inheritance check is used to allow + // for covariant return types on MethodImpls. + static BOOL CompareTypeHandles(TypeHandle hType1, TypeHandle hType2, BOOL allowDerivedClass); + + // Check if a type signature is eligible for covariant return types. + static BOOL IsTypeSignatureEligibleForCovariantReturnType( + PCCOR_SIGNATURE pSig, + PCCOR_SIGNATURE pEndSig, + Module* pModule, + BOOL isBaseTypeSig, + mdToken* pTypeDefToken = NULL, + Module** ppTypeDefModule = NULL, + mdToken* pParentTypeDefOrRefOrSpecToken = NULL); + + // Compute the base type token (it will either be a typedef or typeref token), and returns the + // module where that base type token is declared. + static BOOL ComputeBaseTypeTokenAndModule( + mdToken tk, + Module* pModule, + mdToken* pBaseTypeDefOrRefToken, + Module** ppBaseTypeTokenModule); + + // Extract the parent type's signature and stubstitution from the input type signature + static BOOL GetParentSignatureAndSubstitution( + PCCOR_SIGNATURE pSig, + PCCOR_SIGNATURE pEndSig, + Module* pModule, + const Substitution* pSubst, + Module** ppParentTypeModule, + SigBuilder& parentTypeSig, + Substitution& parentTypeSubst); + // 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, @@ -984,6 +1015,7 @@ class MetaSig Module * pModule2, const Substitution * pSubst1, const Substitution * pSubst2, + BOOL allowDerivedClass, TokenPairList * pVisited = NULL); @@ -1002,15 +1034,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 allowCovariantReturn, + TokenPairList* pVisited = NULL ); // Nonthrowing version of CompareMethodSigs diff --git a/src/coreclr/src/vm/wellknownattributes.h b/src/coreclr/src/vm/wellknownattributes.h index de71eb459f90cf..8401f233cd0c56 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, + ValidateMethodImplRemainsInEffectAttribute, CountOfWellKnownAttributes }; @@ -99,6 +100,8 @@ inline const char *GetWellKnownAttributeName(WellKnownAttribute attribute) return "System.ThreadStaticAttribute"; case WellKnownAttribute::WinRTMarshalingBehaviorAttribute: return "Windows.Foundation.Metadata.MarshalingBehaviorAttribute"; + case WellKnownAttribute::ValidateMethodImplRemainsInEffectAttribute: + return "System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute"; case WellKnownAttribute::CountOfWellKnownAttributes: default: break; // Silence compiler warnings diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns.il new file mode 100644 index 00000000000000..53e63da6764013 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns.il @@ -0,0 +1,311 @@ +// 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 InterfaceReturns { } + +.class interface public auto ansi abstract IA { } +.class interface public auto ansi abstract IB implements IA { } +.class interface public auto ansi abstract IC implements IB { } +.class interface public auto ansi abstract IGenRetType { } + +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 implements class IGenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 implements class IGenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 implements IC { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + +.class public auto ansi beforefieldinit NonGenThroughGen1 implements class IC { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.class public auto ansi beforefieldinit BaseTest +{ + .method public hidebysig newslot virtual instance object MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class IB MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class IB GenToNonGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class IB NonGenThroughGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class IGenRetType GenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class IGenRetType> GenFunc() + { + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test1 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenOverride() + { + .override method instance class IB class BaseTest::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test2 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenOverride() + { + .override method instance class IB class BaseTest::GenToNonGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test3 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1() + { + .override method instance class IGenRetType class BaseTest::GenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test4 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class GenDerive3 NewGenFunc2() + { + .override method instance class IGenRetType> class BaseTest::GenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test5 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class IGenRetType NewFunc1() + { + .override method instance object class BaseTest::MyFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test6 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class IC NewFunc2() + { + .override method instance class IB class BaseTest::MyFunc() + ldnull + 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 static void RunTest6() noinlining + { + newobj instance void class Test6::.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 Test6." + 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/InterfaceReturns/InterfaceReturns.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns.ilproj new file mode 100644 index 00000000000000..d7bdba968e9fc5 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns2.il new file mode 100644 index 00000000000000..18615637fa3146 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns2.il @@ -0,0 +1,271 @@ +// 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 InterfaceReturns { } + +.class interface public auto ansi abstract IA { } +.class interface public auto ansi abstract IB implements IA { } +.class interface public auto ansi abstract IC implements IB { } +.class interface public auto ansi abstract IGenRetType { } + +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 implements class IGenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 implements class IGenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 implements IC { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + +.class public auto ansi beforefieldinit NonGenThroughGen1 implements class IC { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.class public auto ansi beforefieldinit BaseTest +{ + .method public hidebysig newslot virtual instance class IGenRetType 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 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class IB NonGenThroughGenOverride() + { + .override method instance class NonGenThroughGen4 class BaseTest::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test2 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class IB GenToNonGenOverride() + { + .override method instance class GenToNonGen3 class BaseTest::GenToNonGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test3 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class IGenRetType NewGenFunc1() + { + .override method instance class NonGenericDerived4 class BaseTest::GenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test4 extends class BaseTest +{ + .method public hidebysig newslot virtual instance class IGenRetType> NewGenFunc2() + { + .override method instance class GenDerive3 class BaseTest::GenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test5 extends class BaseTest +{ + .method public hidebysig newslot virtual instance object NewFunc1() + { + .override method instance class IGenRetType class BaseTest::MyFunc() + ldnull + 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/InterfaceReturns/InterfaceReturns2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns2.ilproj new file mode 100644 index 00000000000000..8516b81f94df5d --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns2.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns3.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns3.il new file mode 100644 index 00000000000000..ad95ca3cdc85af --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns3.il @@ -0,0 +1,272 @@ +// 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 InterfaceReturns { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } + +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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 public auto ansi beforefieldinit Test1 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class B NonGenThroughGenOverride() + { + .override method instance class NonGenThroughGen4 class BaseTest::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test2 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class B GenToNonGenOverride() + { + .override method instance class GenToNonGen3 class BaseTest::GenToNonGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test3 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType NewGenFunc1() + { + .override method instance class NonGenericDerived4 class BaseTest::GenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test4 implements class BaseTest +{ + .method public hidebysig newslot virtual instance class GenRetType> NewGenFunc2() + { + .override method instance class GenDerive3 class BaseTest::GenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit 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 + { + 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/InterfaceReturns/InterfaceReturns3.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns3.ilproj new file mode 100644 index 00000000000000..3a29ebd99e0676 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns3.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns4.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns4.il new file mode 100644 index 00000000000000..9b1e3358af1efd --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns4.il @@ -0,0 +1,272 @@ +// 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 InterfaceReturns { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } + +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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 + { + 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/InterfaceReturns/InterfaceReturns4.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns4.ilproj new file mode 100644 index 00000000000000..70cebeb5c5c015 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/InterfaceReturns/InterfaceReturns4.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns.il new file mode 100644 index 00000000000000..74807f59f14170 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns.il @@ -0,0 +1,276 @@ +// 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 StructReturns { } + +.class public sealed auto ansi A extends [mscorlib]System.ValueType { } +.class public sealed auto ansi GenStruct extends [mscorlib]System.ValueType { } + + +.class public auto ansi C { } +.class public auto ansi GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + + +.class public auto ansi beforefieldinit BaseType +{ + .method public hidebysig newslot virtual instance valuetype A MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance valuetype A GenToNonGen() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance valuetype A NonGenThroughGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance valuetype GenStruct MyGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance valuetype GenStruct> MyGenFunc() + { + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test1 extends class BaseType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenOverride() + { + .override method instance valuetype A class BaseType::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test2 extends class BaseType +{ + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGenOverride() + { + .override method instance valuetype A class BaseType::GenToNonGen() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test3 extends class BaseType +{ + .method public hidebysig newslot virtual instance class NonGenericDerived4 NewGenFunc1() + { + .override method instance valuetype GenStruct class BaseType::MyGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test4 extends class BaseType +{ + .method public hidebysig newslot virtual instance class GenDerive3 NewGenFunc1() + { + .override method instance valuetype GenStruct> class BaseType::MyGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test5 extends class BaseType +{ + .method public hidebysig newslot virtual instance class C NewFunc2() + { + .override method instance valuetype A class BaseType::MyFunc() + ldnull + 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/StructReturns/StructReturns.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns.ilproj new file mode 100644 index 00000000000000..19bd401728977b --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns2.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns2.il new file mode 100644 index 00000000000000..bce446c50b2a3a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns2.il @@ -0,0 +1,276 @@ +// 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 StructReturns { } + +.class public sealed auto ansi A extends [mscorlib]System.ValueType { } +.class public sealed auto ansi GenStruct extends [mscorlib]System.ValueType { } + + +.class public auto ansi C { } +.class public auto ansi GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends class C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + + +.class public auto ansi beforefieldinit BaseType +{ + .method public hidebysig newslot virtual instance class C MyFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenToNonGen3 GenToNonGen() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenThroughGen4 NonGenThroughGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class NonGenericDerived4 MyGenFunc() + { + ldnull + ret + } + .method public hidebysig newslot virtual instance class GenDerive3 MyGenFunc() + { + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test1 extends class BaseType +{ + .method public hidebysig newslot virtual instance valuetype A NonGenThroughGenOverride() + { + .override method instance class NonGenThroughGen4 class BaseType::NonGenThroughGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test2 extends class BaseType +{ + .method public hidebysig newslot virtual instance valuetype A GenToNonGenOverride() + { + .override method instance class GenToNonGen3 class BaseType::GenToNonGen() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test3 extends class BaseType +{ + .method public hidebysig newslot virtual instance valuetype GenStruct NewGenFunc1() + { + .override method instance class NonGenericDerived4 class BaseType::MyGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test4 extends class BaseType +{ + .method public hidebysig newslot virtual instance valuetype GenStruct> NewGenFunc1() + { + .override method instance class GenDerive3 class BaseType::MyGenFunc() + ldnull + ret + } +} + +.class public auto ansi beforefieldinit Test5 extends class BaseType +{ + .method public hidebysig newslot virtual instance valuetype A NewFunc2() + { + .override method instance class C class BaseType::MyFunc() + ldnull + 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/StructReturns/StructReturns2.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns2.ilproj new file mode 100644 index 00000000000000..4b89683efdc7ba --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/StructReturns/StructReturns2.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + 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..0388370550bc28 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.il @@ -0,0 +1,9 @@ +// 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 { } 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..5709f614f85279 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/A.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..3a49d6fd3f9644 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.il @@ -0,0 +1,10 @@ +// 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 { } 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..030302f6445ce4 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/B.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..ece5321703e258 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.il @@ -0,0 +1,10 @@ +// 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 { } 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..fa878a880b4d6e --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/C.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..f23cc2e3f2e7f7 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.il @@ -0,0 +1,9 @@ +// 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 { } 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..f73733601e918c --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/Dictionary.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..7d70bf4fb86135 --- /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.0 + 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.0 + 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.0 + 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.0 + 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.0 + 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.0 + 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.0 + 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..0ba90cee027431 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenBaseType.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..9678d6dda30015 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.il @@ -0,0 +1,10 @@ +// 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 { } 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..447fae7b5a25e3 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..b50fbfc783ea66 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.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 mscorlib{} +.assembly extern GenDerive1{} +.assembly extern Dictionary{} +.assembly GenDerive2{} + +.class public auto ansi beforefieldinit GenDerive2 extends class [GenDerive1]GenDerive1> { } 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..67c599a2657d44 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..1d531f3f5db3ed --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.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 mscorlib{} +.assembly extern GenDerive2{} +.assembly GenDerive3{} + +.class public auto ansi beforefieldinit GenDerive3 extends class [GenDerive2]GenDerive2 { } + 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..4cae55804628b4 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenDerive3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..094a68b83d0fdb --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.il @@ -0,0 +1,9 @@ +// 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 { } 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..c36b5efac15064 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenRetType.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..1ced09374c2564 --- /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..5f1ffa699d6145 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenTestType.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..f86b57b3d47fba --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.il @@ -0,0 +1,10 @@ +// 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 { } 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..51aef6456c4ade --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..f8f34cb85b0ef1 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.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 mscorlib{} +.assembly extern GenToNonGen1{} +.assembly extern Dictionary{} +.assembly GenToNonGen2{} + +.class public auto ansi beforefieldinit GenToNonGen2 extends class [GenToNonGen1]GenToNonGen1> { } 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..c81e5d4c2422fe --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..741ef9184c2cf2 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.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 extern GenToNonGen2 { } + +.assembly GenToNonGen3{} + + +.class public auto ansi beforefieldinit GenToNonGen3 extends class [GenToNonGen2]GenToNonGen2 { } 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..af288880534b43 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/GenToNonGen3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..581a4275bb6eef --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.il @@ -0,0 +1,9 @@ +// 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 { } 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..bc6a5b3ca706e4 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..1dd2d0410e47ef --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.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 mscorlib{} +.assembly extern NonGenThroughGen1{} +.assembly extern Dictionary{} +.assembly NonGenThroughGen2{} + +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class [NonGenThroughGen1]NonGenThroughGen1> { } 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..6b9e08b1060ce6 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..e55a296326bccb --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.il @@ -0,0 +1,10 @@ +// 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 { } 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..edab938e925187 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..16a50342681806 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.il @@ -0,0 +1,9 @@ +// 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 { } 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..74e921be626589 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenThroughGen4.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..cc4f836083bb74 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.il @@ -0,0 +1,10 @@ +// 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 { } 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..773e2a12982652 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived1.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..50fd143311dd5b --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.il @@ -0,0 +1,10 @@ +// 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 { } 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..19201aa97848bc --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived2.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..406a6a013bdfea --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.il @@ -0,0 +1,9 @@ +// 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 { } 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..a035dcde822ca9 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived3.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..8b803f0adf4cc7 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.il @@ -0,0 +1,9 @@ +// 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 { } 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..a382f20f7c64cf --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/Modules/NonGenericDerived4.ilproj @@ -0,0 +1,11 @@ + + + + Library + BuildOnly + 1 + + + + + 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..bc43bcafb0254a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.il @@ -0,0 +1,469 @@ +// 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 { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } +.class public auto ansi beforefieldinit D extends C { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit GenDerivedRetType extends class GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } +.class public auto ansi beforefieldinit GenDerive4 extends class GenDerive3 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } +.class public auto ansi beforefieldinit NonGenericDerived5 extends NonGenericDerived4 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } +.class public auto ansi beforefieldinit GenToNonGen4 extends class GenToNonGen3 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } +.class public auto ansi beforefieldinit NonGenThroughGen5 extends NonGenThroughGen4 { } + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== + +.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 GenDerivedRetType NewFunc1(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenDerivedRetType 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 + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit GenDerivedTestType extends class GenTestType +{ + .method public hidebysig newslot virtual instance class NonGenThroughGen5 NonGenThroughGenOverride(string& res) + { + .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 GenToNonGenOverride(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen4 DerivedTestType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived5 NewGenFunc1(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived5 DerivedTestType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive4 NewGenFunc2(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive4 DerivedTestType.NewGenFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerivedRetType NewFunc1(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "GenDerivedRetType DerivedTestType.NewFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class D NewFunc2(string& res) + { + .override method instance class B class GenBaseType::MyFunc(string& res) + ldarg.1 + ldstr "D DerivedTestType.NewFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static bool RunTest1() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenDerivedRetType DerivedTestType.NewFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerivedRetType DerivedTestType.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: D DerivedTestType.NewFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "D DerivedTestType.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: GenDerive4 DerivedTestType.NewGenFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerive4 DerivedTestType.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: NonGenericDerived5 DerivedTestType.NewGenFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenericDerived5 DerivedTestType.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: GenToNonGen4 DerivedTestType.GenToNonGenOverride()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenToNonGen4 DerivedTestType.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: NonGenThroughGen5 DerivedTestType.NonGenThroughGenFunc()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenThroughGen5 DerivedTestType.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/OverrideMoreDerivedReturn.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.ilproj new file mode 100644 index 00000000000000..919060123e065a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideMoreDerivedReturn.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideSameReturn.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideSameReturn.il new file mode 100644 index 00000000000000..044215d4630e80 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideSameReturn.il @@ -0,0 +1,462 @@ +// 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 ReOverrideSameReturn { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== + +.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 + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit GenDerivedTestType extends class GenTestType +{ + .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 DerivedTestType.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 DerivedTestType.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 DerivedTestType.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 DerivedTestType.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 DerivedTestType.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 DerivedTestType.NewFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.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 DerivedTestType.NewFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance object class GenBaseType::MyFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenRetType DerivedTestType.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 DerivedTestType.NewFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::MyFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "C DerivedTestType.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 DerivedTestType.NewGenFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerive3 DerivedTestType.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 DerivedTestType.NewGenFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenericDerived4 DerivedTestType.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 DerivedTestType.GenToNonGenOverride()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenToNonGen3 DerivedTestType.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 DerivedTestType.NonGenThroughGenFunc()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenDerivedTestType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenThroughGen4 DerivedTestType.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/OverrideSameReturn.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideSameReturn.ilproj new file mode 100644 index 00000000000000..c2be2cd6a5b067 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/OverrideSameReturn.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + 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..53e7a1fb2bf9d8 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.il @@ -0,0 +1,568 @@ +// 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 System.Private.CoreLib { } +.assembly extern mscorlib { } +.assembly UnitTest { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== + +.class public auto ansi beforefieldinit GenMiddleType extends class GenBaseType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenBaseType::.ctor() + ret + } + + .method public hidebysig newslot virtual instance class NonGenThroughGen2 NonGenThroughGenOverride_Middle(string& res) + { + .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> GenToNonGenOverride_Middle(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldarg.1 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived1 NewGenFunc1_Middle(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "NonGenericDerived1 GenMiddleType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive1> NewGenFunc2_Middle(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldarg.1 + ldstr "GenDerive1> GenMiddleType.NewGenFunc2()" + stind.ref + ldnull + ret + } + +} + + +// ======================================================================================== +.class public auto ansi beforefieldinit GenTestType extends class GenMiddleType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 GenMiddleType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + // ============== Test using GenTestType ============== // + .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::.ctor() + ldloca.s 0 + callvirt instance object class 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::.ctor() + ldloca.s 0 + callvirt instance class B class 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::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class 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::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class 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::.ctor() + ldloca.s 0 + callvirt instance class B class 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::.ctor() + ldloca.s 0 + callvirt instance class B class 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 + } + + // ============== Test using GenMiddleType ============== // + .method public static bool RunTest_Middle1() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenDerive1> GenMiddleType.NewGenFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerive1> GenMiddleType.NewGenFunc2()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest_Middle2() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: NonGenericDerived1 GenMiddleType.NewGenFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenericDerived1 GenMiddleType.NewGenFunc1()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest_Middle3() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenToNonGen1> GenMiddleType.GenToNonGenOverride()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGenOverride()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest_Middle4() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenThroughGen2 GenMiddleType.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 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 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..8f3457cf99bda9 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + 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..6d26c58e02d19b --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.il @@ -0,0 +1,425 @@ +// 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 UnitTestDelegates { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + + +.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 + } +} + + + + +.class public auto ansi sealed ReturnObjDel extends [System.Runtime]System.MulticastDelegate +{ + // We can use a delegate with signature 'object Invoke(string&)' for all methods here since they all return a reference type + + .method public hidebysig specialname rtspecialname instance void .ctor (object 'object', native int 'method') runtime managed { } + .method public hidebysig newslot virtual instance class [System.Runtime]System.IAsyncResult BeginInvoke (string& res, class [System.Runtime]System.AsyncCallback callback, object 'object') runtime managed { } + .method public hidebysig newslot virtual instance object Invoke (string& res) runtime managed { } + .method public hidebysig newslot virtual instance object EndInvoke (string& res, class [System.Runtime]System.IAsyncResult result) runtime managed { } +} + +.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::.ctor() + dup + ldvirtftn instance object class GenBaseType::MyFunc(string&) + newobj instance void class ReturnObjDel::.ctor(object, native int) + + ldloca.s 0 + callvirt instance object class ReturnObjDel::Invoke(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::.ctor() + dup + ldvirtftn instance class B class GenBaseType::MyFunc(string&) + newobj instance void class ReturnObjDel::.ctor(object, native int) + + ldloca.s 0 + callvirt instance object class ReturnObjDel::Invoke(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::.ctor() + dup + ldvirtftn instance class GenRetType> class GenBaseType::MyGenFunc(string&) + newobj instance void class ReturnObjDel::.ctor(object, native int) + + ldloca.s 0 + callvirt instance object class ReturnObjDel::Invoke(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::.ctor() + dup + ldvirtftn instance class GenRetType class GenBaseType::MyGenFunc(string&) + newobj instance void class ReturnObjDel::.ctor(object, native int) + + ldloca.s 0 + callvirt instance object class ReturnObjDel::Invoke(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::.ctor() + dup + ldvirtftn instance class B class GenBaseType::GenToNonGen(string&) + newobj instance void class ReturnObjDel::.ctor(object, native int) + + ldloca.s 0 + callvirt instance object class ReturnObjDel::Invoke(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::.ctor() + dup + ldvirtftn instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + newobj instance void class ReturnObjDel::.ctor(object, native int) + + ldloca.s 0 + callvirt instance object class ReturnObjDel::Invoke(string&) + 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/UnitTestDelegates.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.ilproj new file mode 100644 index 00000000000000..baa0fd4674967e --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestDelegates.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + 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..990f46ff75f4ca --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTestMultiModule.ilproj @@ -0,0 +1,35 @@ + + + Exe + BuildAndRun + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..a1f5a598025dda --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.il @@ -0,0 +1,723 @@ +// 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 System.Private.CoreLib { } +.assembly extern mscorlib { } +.assembly UnitTest_GVM { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } +.class public auto ansi beforefieldinit NonGenericDerived5 extends class NonGenericDerived1 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } +.class public auto ansi beforefieldinit NonGenThroughGen5 extends class NonGenThroughGen2 { } + + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== + +.class public auto ansi beforefieldinit GenMiddleType extends class GenBaseType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenBaseType::.ctor() + ret + } + + .method public hidebysig newslot virtual instance class NonGenThroughGen2 NonGenThroughGenOverride_Middle(string& res) + { + .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> GenToNonGenOverride_Middle(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen<[1]>(string& res) + ldarg.1 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived1 NewGenFunc1_Middle(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "NonGenericDerived1 GenMiddleType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive2 NewGenFunc2_Middle(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "GenDerive2 GenMiddleType.NewGenFunc2()" + stind.ref + ldnull + ret + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit GenTestType extends class GenMiddleType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .method public hidebysig newslot virtual instance class NonGenThroughGen5 NonGenThroughGenOverride(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 GenToNonGenOverride(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen<[1]>(string& res) + ldarg.1 + ldstr "GenToNonGen3 TestType.GenToNonGenOverride()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class NonGenericDerived5 NewGenFunc1(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "NonGenericDerived5 TestType.NewGenFunc1()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenDerive2 NewGenFunc2(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc<[1]>(string& res) + ldarg.1 + ldstr "GenDerive2 TestType.NewGenFunc2()" + stind.ref + ldnull + ret + } + + .method public hidebysig newslot virtual instance class GenRetType NewFunc1(string& res) + { + .override method instance object class GenBaseType::MyFunc<[1]>(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<[1]>(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 GenMiddleType::.ctor() + ret + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit Invalid1 extends class GenMiddleType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + // 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 + } +} +.class public auto ansi beforefieldinit Invalid2 extends class GenMiddleType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + // 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 + } +} +.class public auto ansi beforefieldinit Invalid3 extends class GenMiddleType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + // 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 + } +} +.class public auto ansi beforefieldinit Invalid4 extends class GenMiddleType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + // 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 + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + // ============== Test using GenTestType ============== // + .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::.ctor() + ldloca.s 0 + callvirt instance object class 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::.ctor() + ldloca.s 0 + callvirt instance class B class 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: GenDerive2 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::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerive2 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: NonGenericDerived5 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::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenericDerived5 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::.ctor() + ldloca.s 0 + callvirt instance class B class 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: NonGenThroughGen5 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::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenThroughGen5 TestType.NonGenThroughGenFunc()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + // ============== Test using GenMiddleType ============== // + .method public static bool RunTest_Middle1() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenDerive2 GenMiddleType.NewGenFunc2()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType> class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenDerive2 GenMiddleType.NewGenFunc2()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest_Middle2() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: NonGenericDerived1 GenMiddleType.NewGenFunc1()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class GenRetType class GenBaseType::MyGenFunc(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenericDerived1 GenMiddleType.NewGenFunc1()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest_Middle3() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: GenToNonGen1> GenMiddleType.GenToNonGenOverride()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::GenToNonGen(string&) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "GenToNonGen1> GenMiddleType.GenToNonGenOverride()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + .method public static bool RunTest_Middle4() noinlining + { + .locals init (string res, bool flag) + + ldstr "EXPECTED: NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + call void [System.Console]System.Console::WriteLine(object) + ldstr "ACTUAL : " + call void [System.Console]System.Console::Write(object) + + newobj instance void class GenMiddleType::.ctor() + ldloca.s 0 + callvirt instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + pop + + ldloc.0 + call void [System.Console]System.Console::WriteLine(object) + + ldloc.0 + ldstr "NonGenThroughGen2 GenMiddleType.NonGenThroughGenFunc()" + call bool [System.Runtime]System.String::op_Equality(string, string) + ret + } + + // ===================================================================================== // + .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..4d57a6f1c738b4 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/UnitTest/UnitTest_GVM.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/IncompatibleReturnNoValidation.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/IncompatibleReturnNoValidation.il new file mode 100644 index 00000000000000..1dea0cc7577e3a --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/IncompatibleReturnNoValidation.il @@ -0,0 +1,366 @@ +// 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.Private.CoreLib { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly IncompatibleReturnNoValidation { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== + +.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 + } +} + +// ======================================================================================== + +// ======================================================================================== +// The following types are overriding base type methods that have already been overridden +// with covariant return types, but the return type here is not compatible (return type is +// a base type of the covariant return type of existing overrides). Validation is only +// triggered by the presense of the ValidateMethodImplRemainsInEffect attribute, so the +// following types should successfully load since they do not have the attribute. +// ======================================================================================== +.class public auto ansi beforefieldinit IncompatibleButValid1 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class B NonGenThroughGenOverride_IncompatibleButValid(string& res) + { + .override method instance class B class GenBaseType::NonGenThroughGenFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit IncompatibleButValid2 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class B GenToNonGenOverride_IncompatibleButValid(string& res) + { + .override method instance class B class GenBaseType::GenToNonGen(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit IncompatibleButValid3 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class GenRetType NewGenFunc1_IncompatibleButValid(string& res) + { + .override method instance class GenRetType class GenBaseType::MyGenFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit IncompatibleButValid4 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class GenRetType> NewGenFunc2_IncompatibleButValid(string& res) + { + .override method instance class GenRetType> class GenBaseType::MyGenFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit IncompatibleButValid5 extends class GenTestType +{ + .method public hidebysig newslot virtual instance object NewFunc1_IncompatibleButValid(string& res) + { + .override method instance object class GenBaseType::MyFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit IncompatibleButValid6 extends class GenTestType +{ + .method public hidebysig newslot virtual instance class B NewFunc2_IncompatibleButValid(string& res) + { + .override method instance class B class GenBaseType::MyFunc(string& res) + ldnull + ret + } + + .method public hidebysig specialname rtspecialname instance void .ctor() cil managed + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit CMain extends [mscorlib]System.Object +{ + .method public static void RunTest1() noinlining + { + newobj instance void class IncompatibleButValid1::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest2() noinlining + { + newobj instance void class IncompatibleButValid2::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest3() noinlining + { + newobj instance void class IncompatibleButValid3::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest4() noinlining + { + newobj instance void class IncompatibleButValid4::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest5() noinlining + { + newobj instance void class IncompatibleButValid5::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public static void RunTest6() noinlining + { + newobj instance void class IncompatibleButValid6::.ctor() + call void [System.Console]System.Console::WriteLine(object) + ret + } + + .method public hidebysig static int32 Main( string[] args) cil managed + { + .entrypoint + .maxstack 2 + + // No exception should be thrown here. + call void CMain::RunTest1() + call void CMain::RunTest2() + call void CMain::RunTest3() + call void CMain::RunTest4() + call void CMain::RunTest5() + call void CMain::RunTest6() + + 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/Validation/IncompatibleReturnNoValidation.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/IncompatibleReturnNoValidation.ilproj new file mode 100644 index 00000000000000..3d2e01fb5d250d --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/IncompatibleReturnNoValidation.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + diff --git a/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/OverrideSameSigAsDecl.il b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/OverrideSameSigAsDecl.il new file mode 100644 index 00000000000000..857bb81acf8040 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/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.Private.CoreLib { } +.assembly extern System.Runtime { } +.assembly extern mscorlib { } +.assembly OverrideSameSigAsDecl { } + +.class public auto ansi beforefieldinit A { } +.class public auto ansi beforefieldinit B extends A { } +.class public auto ansi beforefieldinit C extends B { } + +.class public auto ansi beforefieldinit GenRetType { } +.class public auto ansi beforefieldinit Dictionary { } + +.class public auto ansi beforefieldinit GenDerive1 extends class GenRetType { } +.class public auto ansi beforefieldinit GenDerive2 extends class GenDerive1> { } +.class public auto ansi beforefieldinit GenDerive3 extends class GenDerive2 { } + +.class public auto ansi beforefieldinit NonGenericDerived1 extends class GenRetType { } +.class public auto ansi beforefieldinit NonGenericDerived2 extends class NonGenericDerived1 { } +.class public auto ansi beforefieldinit NonGenericDerived3 extends class NonGenericDerived2 { } +.class public auto ansi beforefieldinit NonGenericDerived4 extends NonGenericDerived3 { } + +.class public auto ansi beforefieldinit GenToNonGen1 extends C { } +.class public auto ansi beforefieldinit GenToNonGen2 extends class GenToNonGen1> { } +.class public auto ansi beforefieldinit GenToNonGen3 extends class GenToNonGen2 { } + + +.class public auto ansi beforefieldinit NonGenThroughGen1 extends C { } +.class public auto ansi beforefieldinit NonGenThroughGen2 extends class NonGenThroughGen1> { } +.class public auto ansi beforefieldinit NonGenThroughGen3 extends class NonGenThroughGen2 { } +.class public auto ansi beforefieldinit NonGenThroughGen4 extends NonGenThroughGen3 { } + +.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.0 + ldstr "object GenBaseType.MyFunc()" + stind.ref + newobj instance void A::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B MyFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.MyFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B GenToNonGen(string& res) + { + ldarg.0 + ldstr "B GenBaseType.GenToNonGen()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class B NonGenThroughGenFunc(string& res) + { + ldarg.0 + ldstr "B GenBaseType.NonGenThroughGenFunc()" + stind.ref + newobj instance void B::.ctor() + ret + } + .method public hidebysig newslot virtual instance class GenRetType MyGenFunc(string& res) + { + ldarg.0 + 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.0 + 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.0 + ldstr "GenRetType GenBaseType.TestNonGenericDerived()" + stind.ref + newobj instance void class GenRetType::.ctor() + ret + } +} + + +// ======================================================================================== + +.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 + } +} + +// ======================================================================================== + +.class public auto ansi beforefieldinit Invalid1 extends class GenTestType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit Invalid2 extends class GenTestType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit Invalid3 extends class GenTestType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit Invalid4 extends class GenTestType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit Invalid5 extends class GenTestType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + ret + } +} + +.class public auto ansi beforefieldinit Invalid6 extends class GenTestType +{ + .custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.ValidateMethodImplRemainsInEffectAttribute::.ctor() = (01 00 00 00) + + .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 + { + .maxstack 8 + ldarg.0 + call instance void class GenTestType::.ctor() + 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/Validation/OverrideSameSigAsDecl.ilproj b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/OverrideSameSigAsDecl.ilproj new file mode 100644 index 00000000000000..7bf8afb159d367 --- /dev/null +++ b/src/coreclr/tests/src/Loader/classloader/MethodImpl/CovariantReturns/Validation/OverrideSameSigAsDecl.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 1 + + + + + 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 4e8a39bf297b81..a952df253606ce 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 @@ -631,6 +631,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValidateMethodImplRemainsInEffectAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValidateMethodImplRemainsInEffectAttribute.cs new file mode 100644 index 00000000000000..2da77ceb45fe9f --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ValidateMethodImplRemainsInEffectAttribute.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.Class, AllowMultiple = false, Inherited = false)] + public sealed class ValidateMethodImplRemainsInEffectAttribute : Attribute + { + } +}