diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index b390f3b911cf2f..156444dfeb8952 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -646,6 +646,8 @@ enum CorInfoHelpFunc CORINFO_HELP_VALIDATE_INDIRECT_CALL, // CFG: Validate function pointer CORINFO_HELP_DISPATCH_INDIRECT_CALL, // CFG: Validate and dispatch to pointer + CORINFO_HELP_STATIC_VIRTUAL_AMBIGUOUS_RESOLUTION, // Throw AmbiguousResolutionException for failed static virtual method resolution + CORINFO_HELP_COUNT, }; diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 2ba380c7f7b145..54bef5a7bdbb97 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -339,6 +339,8 @@ JITHELPER(CORINFO_HELP_DISPATCH_INDIRECT_CALL, NULL, CORINFO_HELP_SIG_REG_ONLY) #endif + JITHELPER(CORINFO_HELP_STATIC_VIRTUAL_AMBIGUOUS_RESOLUTION, JIT_StaticVirtualAmbiguousResolution, CORINFO_HELP_SIG_REG_ONLY) + #undef JITHELPER #undef DYNAMICJITHELPER #undef JITHELPER diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 8fc870a55d4a85..41e8879a1e27aa 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -9455,7 +9455,6 @@ var_types Compiler::impImportCall(OPCODE opcode, switch (callInfo->kind) { - case CORINFO_VIRTUALCALL_STUB: { assert(!(mflags & CORINFO_FLG_STATIC)); // can't call a static method diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 2c2d3b9a3048eb..9fe9d2b9b95e42 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -3375,6 +3375,34 @@ NOINLINE HCIMPL3(CORINFO_MethodPtr, JIT_VirtualFunctionPointer_Framed, Object * } HCIMPLEND +HCIMPL3(void, JIT_StaticVirtualAmbiguousResolution, + MethodDesc *method, + MethodTable *interfaceType, + MethodTable *targetType) +{ + FCALL_CONTRACT; + + SString strMethodName; + SString strInterfaceName; + SString strTargetClassName; + + HELPER_METHOD_FRAME_BEGIN_0(); // Set up a frame + + TypeString::AppendMethod(strMethodName, method, method->GetMethodInstantiation()); + TypeString::AppendType(strInterfaceName, TypeHandle(interfaceType)); + TypeString::AppendType(strTargetClassName, targetType); + + HELPER_METHOD_FRAME_END(); // Set up a frame + + FCThrowExVoid( + kAmbiguousImplementationException, + IDS_CLASSLOAD_AMBIGUOUS_OVERRIDE, + strMethodName, + strInterfaceName, + strTargetClassName); +} +HCIMPLEND + HCIMPL1(Object*, JIT_GetRuntimeFieldStub, CORINFO_FIELD_HANDLE field) { FCALL_CONTRACT; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 804ee2e274fe37..ca92f3f44d0321 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -2910,6 +2910,7 @@ void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entr MethodDesc* pContextMD = GetMethodFromContext(pResolvedToken->tokenContext); MethodTable* pContextMT = pContextMD->GetMethodTable(); + bool isStaticVirtual = (pConstrainedResolvedToken != nullptr && pContextMD != nullptr && pContextMD->IsStatic()); // There is a pathological case where invalid IL refereces __Canon type directly, but there is no dictionary availabled to store the lookup. if (!pContextMD->IsSharedByGenericInstantiations()) @@ -4842,6 +4843,8 @@ void CEEInfo::getCallInfo( constrainedType = TypeHandle(pConstrainedResolvedToken->hClass); } + BOOL fIsStaticVirtualMethod = (pConstrainedResolvedToken != NULL && pMD->IsInterface() && pMD->IsStatic()); + BOOL fResolvedConstraint = FALSE; BOOL fForceUseRuntimeLookup = FALSE; @@ -4921,14 +4924,28 @@ void CEEInfo::getCallInfo( exactType = constrainedType; } +#ifdef FEATURE_DEFAULT_INTERFACES + else if (directMethod && pMD->IsStatic()) + { + // Default interface implementation of static virtual method + pMDAfterConstraintResolution = directMethod; + fResolvedConstraint = TRUE; + pResult->thisTransform = CORINFO_NO_THIS_TRANSFORM; + exactType = directMethod->GetMethodTable(); + } +#endif else if (constrainedType.IsValueType()) { pResult->thisTransform = CORINFO_BOX_THIS; } - else + else if (!fIsStaticVirtualMethod) { pResult->thisTransform = CORINFO_DEREF_THIS; } + else + { + pResult->thisTransform = CORINFO_NO_THIS_TRANSFORM; + } } // @@ -4938,10 +4955,15 @@ void CEEInfo::getCallInfo( MethodDesc * pTargetMD = pMDAfterConstraintResolution; DWORD dwTargetMethodAttrs = pTargetMD->GetAttrs(); + pResult->exactContextNeedsRuntimeLookup = (!constrainedType.IsNull() && constrainedType.IsCanonicalSubtype()); + if (pTargetMD->HasMethodInstantiation()) { pResult->contextHandle = MAKE_METHODCONTEXT(pTargetMD); - pResult->exactContextNeedsRuntimeLookup = pTargetMD->GetMethodTable()->IsSharedByGenericInstantiations() || TypeHandle::IsCanonicalSubtypeInstantiation(pTargetMD->GetMethodInstantiation()); + if (pTargetMD->GetMethodTable()->IsSharedByGenericInstantiations() || TypeHandle::IsCanonicalSubtypeInstantiation(pTargetMD->GetMethodInstantiation())) + { + pResult->exactContextNeedsRuntimeLookup = TRUE; + } } else { @@ -4955,7 +4977,10 @@ void CEEInfo::getCallInfo( } pResult->contextHandle = MAKE_CLASSCONTEXT(exactType.AsPtr()); - pResult->exactContextNeedsRuntimeLookup = exactType.IsSharedByGenericInstantiations(); + if (exactType.IsSharedByGenericInstantiations()) + { + pResult->exactContextNeedsRuntimeLookup = TRUE; + } // Use main method as the context as long as the methods are called on the same type if (pResult->exactContextNeedsRuntimeLookup && @@ -4978,7 +5003,7 @@ void CEEInfo::getCallInfo( bool directCall = false; bool resolvedCallVirt = false; - if (flags & CORINFO_CALLINFO_LDFTN) + if ((flags & CORINFO_CALLINFO_LDFTN) && (!fIsStaticVirtualMethod || fResolvedConstraint)) { // Since the ldvirtftn instruction resolves types // at run-time we do this earlier than ldftn. The @@ -5003,12 +5028,12 @@ void CEEInfo::getCallInfo( } else // Static methods are always direct calls - if (pTargetMD->IsStatic()) + if (pTargetMD->IsStatic() && (!fIsStaticVirtualMethod || fResolvedConstraint)) { directCall = true; } else - if (!(flags & CORINFO_CALLINFO_CALLVIRT) || fResolvedConstraint) + if ((!fIsStaticVirtualMethod && !(flags & CORINFO_CALLINFO_CALLVIRT)) || fResolvedConstraint) { directCall = true; } @@ -5136,13 +5161,13 @@ void CEEInfo::getCallInfo( // All virtual calls which take method instantiations must // currently be implemented by an indirect call via a runtime-lookup // function pointer - else if (pTargetMD->HasMethodInstantiation()) + else if (pTargetMD->HasMethodInstantiation() && !fIsStaticVirtualMethod) { pResult->kind = CORINFO_VIRTUALCALL_LDVIRTFTN; // stub dispatch can't handle generic method calls yet pResult->nullInstanceCheck = TRUE; } // Non-interface dispatches go through the vtable. - else if (!pTargetMD->IsInterface()) + else if (!pTargetMD->IsInterface() && !fIsStaticVirtualMethod) { pResult->kind = CORINFO_VIRTUALCALL_VTABLE; pResult->nullInstanceCheck = TRUE; @@ -5155,6 +5180,10 @@ void CEEInfo::getCallInfo( pResult->kind = CORINFO_VIRTUALCALL_LDVIRTFTN; #else // STUB_DISPATCH_PORTABLE pResult->kind = CORINFO_VIRTUALCALL_STUB; + if (fIsStaticVirtualMethod) + { + pResult->kind = CORINFO_CALL_CODE_POINTER; + } // We can't make stub calls when we need exact information // for interface calls from shared code. @@ -5163,9 +5192,9 @@ void CEEInfo::getCallInfo( { _ASSERTE(!m_pMethodBeingCompiled->IsDynamicMethod()); - ComputeRuntimeLookupForSharedGenericToken(DispatchStubAddrSlot, + ComputeRuntimeLookupForSharedGenericToken(fIsStaticVirtualMethod ? ConstrainedMethodEntrySlot : DispatchStubAddrSlot, pResolvedToken, - NULL, + pConstrainedResolvedToken, pMD, &pResult->stubLookup); } @@ -5390,6 +5419,30 @@ void CEEInfo::getCallInfo( signatureKind = SK_CALLSITE; } getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL, signatureKind); + if (fIsStaticVirtualMethod && !fResolvedConstraint) + { + if (pResult->exactContextNeedsRuntimeLookup) + { + // Runtime lookup for static virtual methods always returns exact call addresses not requiring the instantiation argument + pResult->sig.callConv = (CorInfoCallConv)(pResult->sig.callConv & ~CORINFO_CALLCONV_PARAMTYPE); + } + else + { + // Unresolved static virtual method in the absence of shared generics means + // that the runtime needs to throw when reaching the call. SVM resolution within + // shared generics is covered by the ConstrainedMethodEntrySlot dictionary entry. + pResult->kind = CORINFO_CALL; + pResult->accessAllowed = CORINFO_ACCESS_ILLEGAL; + pResult->callsiteCalloutHelper.helperNum = CORINFO_HELP_STATIC_VIRTUAL_AMBIGUOUS_RESOLUTION; + pResult->callsiteCalloutHelper.numArgs = 3; + pResult->callsiteCalloutHelper.args[0].methodHandle = (CORINFO_METHOD_HANDLE)pMD; + pResult->callsiteCalloutHelper.args[0].argType = CORINFO_HELPER_ARG_TYPE_Method; + pResult->callsiteCalloutHelper.args[1].classHandle = (CORINFO_CLASS_HANDLE)th.AsMethodTable(); + pResult->callsiteCalloutHelper.args[1].argType = CORINFO_HELPER_ARG_TYPE_Class; + pResult->callsiteCalloutHelper.args[2].classHandle = (CORINFO_CLASS_HANDLE)constrainedType.AsMethodTable(); + pResult->callsiteCalloutHelper.args[2].argType = CORINFO_HELPER_ARG_TYPE_Class; + } + } if (flags & CORINFO_CALLINFO_VERIFICATION) { diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 5aae97dd5cb67d..9e30c3782076a9 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -5510,58 +5510,65 @@ namespace MethodDesc *pMD = methodIt.GetMethodDesc(); int targetSlot = interfaceMD->GetSlot(); - // If this is not a MethodImpl, it can't be implementing the method we're looking for - if (!pMD->IsMethodImpl()) - continue; - - // We have a MethodImpl - iterate over all the declarations it's implementing, - // looking for the interface method we need. - MethodImpl::Iterator it(pMD); - for (; it.IsValid() && candidateMaybe == NULL; it.Next()) + if (pMD->IsMethodImpl()) { - MethodDesc *pDeclMD = it.GetMethodDesc(); - - // Is this the right slot? - if (pDeclMD->GetSlot() != targetSlot) - continue; - - // Is this the right interface? - if (!pDeclMD->HasSameMethodDefAs(interfaceMD)) - continue; - - if (interfaceMD->HasClassInstantiation()) + // We have a MethodImpl with slots - iterate over all the declarations it's implementing, + // looking for the interface method we need. + MethodImpl::Iterator it(pMD); + for (; it.IsValid() && candidateMaybe == NULL; it.Next()) { - // pInterfaceMD will be in the canonical form, so we need to check the specific - // instantiation against pInterfaceMT. - // - // The parent of pDeclMD is unreliable for this purpose because it may or - // may not be canonicalized. Let's go from the metadata. - - SigTypeContext typeContext = SigTypeContext(pMT); - - mdTypeRef tkParent; - IfFailThrow(pMD->GetModule()->GetMDImport()->GetParentToken(it.GetToken(), &tkParent)); - - MethodTable *pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing( - pMD->GetModule(), - tkParent, - &typeContext).AsMethodTable(); - - // We do CanCastToInterface to also cover variance. - // We already know this is a method on the same type definition as the (generic) - // interface but we need to make sure the instantiations match. - if ((allowVariance && pDeclMT->CanCastToInterface(interfaceMT)) - || pDeclMT == interfaceMT) + MethodDesc *pDeclMD = it.GetMethodDesc(); + + // Is this the right slot? + if (pDeclMD->GetSlot() != targetSlot) + continue; + + // Is this the right interface? + if (!pDeclMD->HasSameMethodDefAs(interfaceMD)) + continue; + + if (interfaceMD->HasClassInstantiation()) { - // We have a match + // pInterfaceMD will be in the canonical form, so we need to check the specific + // instantiation against pInterfaceMT. + // + // The parent of pDeclMD is unreliable for this purpose because it may or + // may not be canonicalized. Let's go from the metadata. + + SigTypeContext typeContext = SigTypeContext(pMT); + + mdTypeRef tkParent; + IfFailThrow(pMD->GetModule()->GetMDImport()->GetParentToken(it.GetToken(), &tkParent)); + + MethodTable *pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing( + pMD->GetModule(), + tkParent, + &typeContext).AsMethodTable(); + + // We do CanCastToInterface to also cover variance. + // We already know this is a method on the same type definition as the (generic) + // interface but we need to make sure the instantiations match. + if ((allowVariance && pDeclMT->CanCastToInterface(interfaceMT)) + || pDeclMT == interfaceMT) + { + // We have a match + candidateMaybe = pMD; + } + } + else + { + // No generics involved. If the method definitions match, it's a match. candidateMaybe = pMD; } } - else - { - // No generics involved. If the method definitions match, it's a match. - candidateMaybe = pMD; - } + } + else if (pMD->IsStatic() && pMD->HasMethodImplSlot()) + { + // Static virtual methods don't record MethodImpl slots so they need special handling + candidateMaybe = pMT->TryResolveVirtualStaticMethodOnThisType( + interfaceMT, + interfaceMD, + /* verifyImplemented */ FALSE); } } } @@ -5750,8 +5757,8 @@ BOOL MethodTable::FindDefaultInterfaceImplementation( pBestCandidateMD = candidates[i].pMD; // If this is a second pass lookup, we know this is a variant match. As such - // we pick the first result as the winner and don't look for a conflict. - if (allowVariance) + // we pick the first result as the winner and don't look for a conflict for instance methods. + if (allowVariance && !pInterfaceMD->IsStatic()) break; } else if (pBestCandidateMT != candidates[i].pMT) @@ -5759,7 +5766,7 @@ BOOL MethodTable::FindDefaultInterfaceImplementation( if (throwOnConflict) ThrowExceptionForConflictingOverride(this, pInterfaceMT, pInterfaceMD); - *ppDefaultMethod = NULL; + *ppDefaultMethod = pBestCandidateMD; RETURN(FALSE); } } @@ -7983,8 +7990,18 @@ MethodDesc *MethodTable::GetDefaultConstructor(BOOL forceBoxedEntryPoint /* = FA //========================================================================================== // Finds the (non-unboxing) MethodDesc that implements the interface virtual static method pInterfaceMD. MethodDesc * -MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL verifyImplemented, BOOL allowVariantMatches) +MethodTable::ResolveVirtualStaticMethod( + MethodTable* pInterfaceType, + MethodDesc* pInterfaceMD, + BOOL allowNullResult, + BOOL verifyImplemented, + BOOL allowVariantMatches, + BOOL* uniqueResolution) { + if (uniqueResolution != nullptr) + { + *uniqueResolution = TRUE; + } if (!pInterfaceMD->IsSharedByGenericMethodInstantiations() && !pInterfaceType->IsSharedByGenericInstantiations()) { // Check that there is no implementation of the interface on this type which is the canonical interface for a shared generic. If so, that indicates that @@ -8064,6 +8081,22 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* } } } + + BOOL haveUniqueDefaultImplementation = pMT->FindDefaultInterfaceImplementation( + pInterfaceMD, + pInterfaceType, + &pMD, + /* allowVariance */ allowVariantMatches, + /* throwOnConflict */ uniqueResolution == nullptr); + if (haveUniqueDefaultImplementation || (pMD != nullptr && (verifyImplemented || uniqueResolution != nullptr))) + { + // We tolerate conflicts upon verification of implemented SVMs so that they only blow up when actually called at execution time. + if (uniqueResolution != nullptr) + { + *uniqueResolution = haveUniqueDefaultImplementation; + } + return pMD; + } } } @@ -8244,9 +8277,20 @@ MethodTable::VerifyThatAllVirtualStaticMethodsAreImplemented() for (MethodIterator it(pInterfaceMT); it.IsValid(); it.Next()) { MethodDesc *pMD = it.GetMethodDesc(); + // This flag is not really used, passing its address to ResolveVirtualStaticMethod just suppresses + // the ambiguous resolution exception throw as we should delay the exception until we actually hit + // the ambiguity at execution time. + BOOL uniqueResolution; if (pMD->IsVirtual() && pMD->IsStatic() && - (pMD->IsAbstract() && !ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* verifyImplemented */ TRUE, /* allowVariantMatches */ FALSE))) + (pMD->IsAbstract() && + !ResolveVirtualStaticMethod( + pInterfaceMT, + pMD, + /* allowNullResult */ TRUE, + /* verifyImplemented */ TRUE, + /* allowVariantMatches */ FALSE, + /* uniqueResolution */ &uniqueResolution))) { IMDInternalImport* pInternalImport = GetModule()->GetMDImport(); GetModule()->GetAssembly()->ThrowTypeLoadException(pInternalImport, GetCl(), pMD->GetName(), IDS_CLASSLOAD_STATICVIRTUAL_NOTIMPL); @@ -8279,10 +8323,18 @@ MethodTable::TryResolveConstraintMethodApprox( { _ASSERTE(!thInterfaceType.IsTypeDesc()); _ASSERTE(thInterfaceType.IsInterface()); - MethodDesc *result = ResolveVirtualStaticMethod(thInterfaceType.GetMethodTable(), pInterfaceMD, pfForceUseRuntimeLookup != NULL); - if (result == NULL) + BOOL uniqueResolution; + MethodDesc *result = ResolveVirtualStaticMethod( + thInterfaceType.GetMethodTable(), + pInterfaceMD, + /* allowNullResult */pfForceUseRuntimeLookup != NULL, + /* verifyImplemented */ FALSE, + /* allowVariantMatches */ TRUE, + &uniqueResolution); + if (result == NULL || !uniqueResolution) { *pfForceUseRuntimeLookup = TRUE; + result = NULL; } return result; } diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 48ef1cd6894392..4b1d4cbd6e6979 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2092,7 +2092,15 @@ class MethodTable // Specify allowNullResult to return NULL instead of throwing if the there is no implementation // Specify verifyImplemented to verify that there is a match, but do not actually return a final usable MethodDesc // Specify allowVariantMatches to permit generic interface variance - MethodDesc *ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL verifyImplemented = FALSE, BOOL allowVariantMatches = TRUE); + // Specify uniqueResolution to store the flag saying whether the resolution was unambiguous; + // when NULL, throw an AmbiguousResolutionException upon hitting ambiguous SVM resolution. + MethodDesc *ResolveVirtualStaticMethod( + MethodTable* pInterfaceType, + MethodDesc* pInterfaceMD, + BOOL allowNullResult, + BOOL verifyImplemented = FALSE, + BOOL allowVariantMatches = TRUE, + BOOL *uniqueResolution = NULL); // Try a partial resolve of the constraint call, up to generic code sharing. // diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 78e26991bcf4a0..9f02e5d5e8f776 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -2935,7 +2935,7 @@ MethodTableBuilder::EnumerateClassMethods() { BuildMethodTableThrowException(BFA_AB_METHOD_IN_AB_CLASS); } - if(!IsMdVirtual(dwMemberAttrs)) + if(!IsMdVirtual(dwMemberAttrs) && !IsMdStatic(dwMemberAttrs)) { BuildMethodTableThrowException(BFA_NONVIRT_AB_METHOD); } @@ -4829,8 +4829,8 @@ VOID MethodTableBuilder::TestMethodImpl( BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL); } - // Interface method body that has methodimpl should always be final - if (IsInterface() && !IsMdFinal(dwImplAttrs)) + // Non-static interface method body that has methodimpl should always be final + if (IsInterface() && !IsMdStatic(dwDeclAttrs) && !IsMdFinal(dwImplAttrs)) { BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL); } diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 400f3f2a1c61fd..c849a0a53d5eb3 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -1079,7 +1079,12 @@ extern "C" MethodDesc* QCALLTYPE RuntimeTypeHandle_GetInterfaceMethodImplementat if (pMD->IsStatic()) { - pResult = typeHandle.GetMethodTable()->ResolveVirtualStaticMethod(thOwnerOfMD.GetMethodTable(), pMD, /* allowNullResult */ TRUE, /* verifyImplemented*/ FALSE, /*allowVariantMatches */ TRUE); + pResult = typeHandle.GetMethodTable()->ResolveVirtualStaticMethod( + thOwnerOfMD.GetMethodTable(), + pMD, + /* allowNullResult */ TRUE, + /* verifyImplemented*/ FALSE, + /*allowVariantMatches */ TRUE); } else { diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp index e7eacb9c2ff85f..af91c3dd03e89e 100644 --- a/src/coreclr/vm/typedesc.cpp +++ b/src/coreclr/vm/typedesc.cpp @@ -1607,7 +1607,8 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra MethodDesc *pMD = it.GetMethodDesc(); if (pMD->IsVirtual() && pMD->IsStatic() && - (pMD->IsAbstract() && !thElem.AsMethodTable()->ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* verifyImplemented */ TRUE))) + (pMD->IsAbstract() && !thElem.AsMethodTable()->ResolveVirtualStaticMethod( + pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* verifyImplemented */ TRUE))) { virtualStaticResolutionCheckFailed = true; break; diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape.cs b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape.cs new file mode 100644 index 00000000000000..0d7287f40af8c5 --- /dev/null +++ b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape.cs @@ -0,0 +1,558 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +interface IFoo +{ + virtual static int Foo(int a) + { + return a; + } +} + +interface IFoo2 : IFoo +{ + static int IFoo.Foo(int a) + { + Console.WriteLine("At IFoo2.Foo"); + return a + 1; + } +} + +interface IFooEx : IFoo +{ + static int IFoo.Foo(int a) + { + Console.WriteLine("At IFooEx.Foo"); + return a + 2; + } +} + +interface IFooExReabstract : IFooEx +{ + abstract static int IFoo.Foo(int a); +} + +class FooClass : IFoo2, IFoo, IFooEx +{ +} + +class FooClassReabstract : IFoo2, IFoo, IFooExReabstract +{ +} + +struct FooStruct : IFoo2, IFoo, IFooEx +{ +} + +interface I1 +{ + static int Func(int a); +} + +interface I2 : I1 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I2.Func"); + return a + 2; + } +} + +interface I3 : I1 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I3.Func"); + return a + 3; + } +} + +interface I4 : I2, I1, I3 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I4.Func"); + return a + 4; + } +} + +interface I4Reabstract : I4 +{ + abstract static int I1.Func(int a); +} + +interface I4Reimplement : I4Reabstract +{ + static int I1.Func(int a) + { + Console.WriteLine("At I4Reimplement.Func"); + return a + 17; + } +} + +class I4Class : I4, I2, I1, I3 +{ +} + +class I4ReimplementClass : I4Reimplement, I2, I1, I3 +{ +} + +struct I4Struct : I4, I2, I1, I3 +{ +} + +interface I5 : I1 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I5.Func"); + return a + 5; + } +} + +interface I6 : I1 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I6.Func"); + return a + 6; + } +} + +interface I7 : I5, I6 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I7.Func"); + return a + 7; + } +} + +interface I8 : I4, I2, I1, I3, I7, I5, I6 +{ + static int I1.Func(int a) + { + Console.WriteLine("At I8.Func"); + return a + 8; + } +} + +class I47Class : I4, I2, I1, I3, I7, I5, I6 +{ +} + +struct I47Struct : I4, I2, I1, I3, I7, I5, I6 +{ +} + +class I8Class : I8, I4, I2, I1, I3, I7, I5, I6 +{ +} + +struct I8Struct : I8, I4, I2, I1, I3, I7, I5, I6 +{ +} + +interface GI1 +{ + static int Func(out Type[] types); +} + +interface GI2 : GI1 +{ + static int GI1.Func(out Type[] types) + { + Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI2"); + types = new Type[] { typeof(T), typeof(S) }; + return 2; + } + +} + +interface GI3 : GI1 +{ + static int GI1.Func(out Type[] types) + { + Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI3"); + types = new Type[] { typeof(T), typeof(S) }; + return 3; + } +} + +interface GI4 : GI2, GI1, GI3 +{ + static int GI1.Func(out Type[] types) + { + Console.WriteLine(typeof(T) + ", " + typeof(S) + ", GI4"); + types = new Type[] { typeof(T), typeof(S) }; + return 4; + } +} + +class GI23Class : GI2, GI1, GI3 +{ +} + +struct GI23Struct : GI2, GI1, GI3 +{ +} + +class GI4Class : GI4, GI2, GI1, GI3 +{ +} + +struct GI4Struct : GI4, GI2, GI1, GI3 +{ +} + +interface IResolutionAtRuntime +{ + virtual abstract static int Func(int a); +} + +class ResolutionAtRuntimeBase : IResolutionAtRuntime, IResolutionAtRuntime +{ + static int IResolutionAtRuntime.Func(int a) + { + Console.WriteLine("At ResolutionAtRuntimeBase.FuncObject"); + return a + 19; + } + + static int IResolutionAtRuntime.Func(int a) + { + Console.WriteLine("At ResolutionAtRuntimeBase.FuncString"); + return a + 23; + } +} + +class ResolutionAtRuntimeThisObj : T is IResolutionAtRuntime +{ + public int RuntimeResolvedFunc(int a) + { + Console.WriteLine("At ResolutionAtRuntimeThisObj.RuntimeResolvedFunc"); + return T.Func(a); + } +} + +class ResolutionAtRuntimeClassParam : T is IResolutionAtRuntime +{ + public static int RuntimeResolvedFunc(int a) + { + Console.WriteLine("At ResolutionAtRuntimeClassParam.RuntimeResolvedFunc"); + return T.Func(a); + } +} + +class ResolutionAtRuntimeMethodParam +{ + public static int RuntimeResolvedFunc(int a) + : T is IResolutionAtRuntime + { + Console.WriteLine("At ResolutionAtRuntimeMethodParam.RuntimeResolvedFunc"); + return T.Func(a); + } +} + +class Program +{ + private static void CallFoo(int value) + : T is IFoo + { + T.Foo(value); + } + + private static Func GetFooDelegate() + { + return new Func(T.Foo); + } + + private static void CallI1Func(int value) + : T is I1 + { + T.Func(value); + } + + private static Func GetI1FuncDelegate() + : T is I1 + { + return new Func(T.Func); + } + + private static void CallGI1Func(out Type[] types) + : T is GI1 + { + T.Func(out types); + } + + private delegate static int GI1Delegate(out Type[]); + + private static GI1Delegate GetGI1FuncDelegate() + : T is GI1 + { + return T.Func; + } + + public static void Negative() + { + Console.WriteLine("Calling IFoo.Foo on FooClass - expecting exception."); + try + { + CallFoo(10); + Test.Assert(false, "Expecting exception on FooClass"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Resolving delegate IFoo.Foo on FooClass - expecting exception."); + try + { + GetFooDelegate(); + Test.Assert(false, "Expecting exception on FooClass"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Calling IFoo.Foo on FooClassReabstract - expecting exception."); + try + { + CallFoo(10); + Test.Assert(false, "Expecting exception on FooClassReabstract"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Calling IFoo.Foo on FooStruct - expecting exception."); + try + { + CallFoo(10); + Test.Assert(false, "Expecting exception on FooStruct"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Resolving delegate IFoo.Foo on FooStruct - expecting exception."); + try + { + GetFooDelegate(); + Test.Assert(false, "Expecting exception on FooStruct"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Calling I1.Func on I47Class - expecting exception"); + try + { + CallI1Func(10); + Test.Assert(false, "Expecting exception on I47Class"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Resolving delegate I1.Func on I47Class - expecting exception"); + try + { + GetI1FuncDelegate(); + Test.Assert(false, "Expecting exception on I47Class"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Calling I1.Func on I47Struct - expecting exception"); + try + { + CallI1Func(10); + Test.Assert(false, "Expecting exception on I47Struct"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Resolving delegate I1.Func on I47Struct - expecting exception"); + try + { + GetI1FuncDelegate(); + Test.Assert(false, "Expecting exception on I47Struct"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Calling GI1.Func on GI23Class - expecting exception"); + try + { + Type[] types; + CallGI1Func, GT1, string>(out types); + Test.Assert(false, "Expecting exception on GI23Class"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Resolving delegate GI1.Func on GI23Class - expecting exception"); + try + { + GetGI1FuncDelegate, GT1, string>(); + Test.Assert(false, "Expecting exception on GI23Class"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Calling GI1.Func on GI23Struct - expecting exception"); + try + { + Type[] types; + CallGI1Func, GT1, string>(out types); + Test.Assert(false, "Expecting exception on GI23Struct"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + + Console.WriteLine("Resolving delegate GI1.Func on GI23Struct - expecting exception"); + try + { + GetGI1FuncDelegate, GT1, string>(); + Test.Assert(false, "Expecting exception on GI23Struct"); + } + catch(Exception ex) + { + Console.WriteLine("Exception caught: " + ex.ToString()); + } + } + + public static void Positive() + { + Console.WriteLine("Calling I1.Func on I4Class - expecting I4.Func"); + + Test.Assert(CallI1Func(10) == 14, "Expecting I1.Func to land on I4.Func"); + + Console.WriteLine("Calling I1.Func on I4ReimplementClass - expecting I4Reimplement.Func"); + + Test.Assert(CallI1Func(10) == 27, "Expecting I1.Func to land on I4Reimplement.Func"); + + Console.WriteLine("Calling I1.Func on I4Class as a delegate - expecting I4.Func"); + + Test.Assert(GetI1FuncDelegate()(10) == 14, "Expecting I1.Func to land on I4.Func"); + + Console.WriteLine("Calling I1.Func on I4Struct - expecting I4.Func"); + + Test.Assert(CallI1Func(10) == 14, "Expecting I1.Func to land on I4.Func"); + + Console.WriteLine("Calling I1.Func on I4Struct as a delegate - expecting I4.Func"); + + Test.Assert(GetI1FuncDelegate()(10) == 14, "Expecting I1.Func to land on I4.Func"); + + Console.WriteLine("Calling I1.Func on I8Class - expecting I8.Func"); + + Test.Assert(CallI1Func(10) == 18, "Expecting I1.Func to land on I8.Func"); + + Console.WriteLine("Calling I1.Func on I8Class as a delegate - expecting I8.Func"); + + Test.Assert(GetI1FuncDelegate()(10) == 18, "Expecting I1.Func to land on I8.Func"); + + Console.WriteLine("Calling I1.Func on I8Struct - expecting I8.Func"); + + Test.Assert(CallI1Func(10) == 18, "Expecting I1.Func to land on I8.Func"); + + Console.WriteLine("Calling I1.Func on I8Struct as a delegate - expecting I8.Func"); + + Test.Assert(GetI1FuncDelegate()(10) == 18, "Expecting I1.Func to land on I8.Func"); + + Type[] types; + + Console.WriteLine("Calling GI1.Func on GI4Class - expecting GI4.Func"); + + Test.Assert(CallGI1Func, GI1, string>(out types) == 4, "Expecting GI1.Func to land on GII4.Func"); + Test.Assert(types[0] == typeof(object), "T must be object"); + Test.Assert(types[1] == typeof(string), "S must be string"); + + Console.WriteLine("Calling GI1.Func on GI4Class as a delegate - expecting GI4.Func"); + + Test.Assert(GetGI1FuncDelegate, GI1, string>()(out types) == 4, "Expecting GI1.Func to land on GII4.Func"); + Test.Assert(types[0] == typeof(object), "T must be object"); + Test.Assert(types[1] == typeof(string), "S must be string"); + + Console.WriteLine("Calling GI1.Func on GI4Struct - expecting GI4.Func"); + + Test.Assert(CallGI1Func, GI1, string>(out types) == 4, "Expecting GI1.Func to land on GII4.Func"); + Test.Assert(types[0] == typeof(object), "T must be object"); + Test.Assert(types[1] == typeof(string), "S must be string"); + + Console.WriteLine("Calling GI1.Func on GI4Struct as a delegate - expecting GI4.Func"); + + Test.Assert(GetGI1FuncDelegate, GI1, string>()(out types) == 4, "Expecting GI1.Func to land on GII4.Func"); + Test.Assert(types[0] == typeof(object), "T must be object"); + Test.Assert(types[1] == typeof(string), "S must be string"); + + Console.WriteLine("Calling ResolutionAtRuntimeThisObj::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncObject"); + Test.Assert(new ResolutionAtRuntimeThisObj().RuntimeResolvedFunc(200) == 219, "Expecting ResolutionAtRuntimeThisObj::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncObject"); + + Console.WriteLine("Calling ResolutionAtRuntimeThisObj::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncString"); + Test.Assert(new ResolutionAtRuntimeThisObj().RuntimeResolvedFunc(200) == 223, "Expecting ResolutionAtRuntimeThisObj::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncString"); + + Console.WriteLine("Calling ResolutionAtRuntimeClassParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncObject"); + Test.Assert(ResolutionAtRuntimeClassParam.RuntimeResolvedFunc(200) == 219, "Expecting ResolutionAtRuntimeClassParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncObject"); + + Console.WriteLine("Calling ResolutionAtRuntimeClassParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncString"); + Test.Assert(ResolutionAtRuntimeClassParam.RuntimeResolvedFunc(200) == 223, "Expecting ResolutionAtRuntimeClassParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncString"); + + Console.WriteLine("Calling ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncObject"); + Test.Assert(ResolutionAtRuntimeClassParam.RuntimeResolvedFunc(100) == 119, "Expecting ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncObject"); + + Console.WriteLine("Calling ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncString"); + Test.Assert(ResolutionAtRuntimeClassParam.RuntimeResolvedFunc(100) == 123, "Expecting ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncString"); + } + + public static int Main() + { + Negative(); + Positive(); + return Test.Ret(); + } +} + +class Test +{ + private static bool Pass = true; + + public static int Ret() + { + return Pass ? 100 : 101; + } + + public static void Assert(bool cond, string msg) + { + if (cond) + { + Console.WriteLine("PASS"); + } + else + { + Console.WriteLine("FAIL: " + msg); + Pass = false; + } + } +} diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape.il b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape.il new file mode 100644 index 00000000000000..50c83313560ff8 --- /dev/null +++ b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape.il @@ -0,0 +1,1642 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Microsoft (R) .NET Framework IL Disassembler. Version 4.6.1055.0 +// Copyright (c) Microsoft Corporation. All rights reserved. + + + +// Metadata version: v4.0.30319 +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + .ver 4:0:0:0 +} +.assembly extern xunit.core {} +// TODO: use the contract once this is exposed from contracts +.assembly extern System.Runtime { } + +.assembly svm_diamondshape +{ + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) + .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx + 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows. + + // --- The following custom attribute is added automatically, do not uncomment ------- + // .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 ) + + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +// MVID: {25B467F3-D284-4DB6-BAD4-C7EAC75CF064} +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000001 // ILONLY +// Image base: 0x010B0000 + + +// =============== CLASS MEMBERS DECLARATION =================== + +.class interface private abstract auto ansi IFoo +{ + .method public hidebysig newslot virtual + static int32 Foo(int32 a) cil managed + { + // Code size 7 (0x7) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: br.s IL_0005 + + IL_0005: ldloc.0 + IL_0006: ret + } // end of method IFoo::Foo + +} // end of class IFoo + +.class interface private abstract auto ansi IFoo2 + implements IFoo +{ + .method public hidebysig + static int32 Foo(int32 a) cil managed + { + .override method int32 IFoo::Foo(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IFoo2.Foo" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.1 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method IFoo2::IFoo.Foo + +} // end of class IFoo2 + +.class interface private abstract auto ansi IFooEx + implements IFoo +{ + .method public hidebysig + static int32 IFoo.Foo(int32 a) cil managed + { + .override method int32 IFoo::Foo(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At IFooEx.Foo" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.2 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method IFooEx::IFoo.Foo +} // end of class IFooEx + +.class interface private abstract auto ansi IFooExReabstract + implements IFooEx +{ + .method public hidebysig abstract final + static int32 IFoo.Foo(int32 a) cil managed + { + } // end of method IFooExReabstract::Func + +} + +.class private auto ansi beforefieldinit FooClass + extends [mscorlib]System.Object + implements IFoo2, + IFoo, + IFooEx +{ +} // end of class FooClass + +.class private auto ansi beforefieldinit FooClassReabstract + extends [mscorlib]System.Object + implements IFoo2, + IFoo, + IFooExReabstract +{ +} // end of class FooClassReabstract + +.class private auto ansi sealed beforefieldinit FooStruct + extends [mscorlib]System.ValueType + implements IFoo2, + IFoo, + IFooEx +{ +} // end of class FooStruct + +.class interface private abstract auto ansi I1 +{ + .method public hidebysig newslot abstract virtual + static int32 Func(int32 a) cil managed + { + } // end of method I1::Func + +} // end of class I1 + +.class interface private abstract auto ansi I2 + implements I1 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I2.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.2 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I2::I1.Func +} // end of class I2 + +.class interface private abstract auto ansi I3 + implements I1 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I3.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.3 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I3::I1.Func +} // end of class I3 + +.class interface private abstract auto ansi I4 + implements I2, + I1, + I3 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I4.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.4 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I4::I1.Func +} // end of class I4 + +.class interface private abstract auto ansi I4Reabstract + implements I4 +{ + .method private hidebysig abstract + static int32 Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + } // end of I4Reabstract::Func +} // end of class I4Reabstract + +.class interface private abstract auto ansi I4Reimplement + implements I4Reabstract +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I4Reimplement.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.s 17 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I4Reimplement::I1.Func +} // end of class I4Reimplement + +.class private auto ansi beforefieldinit I4Class + extends [mscorlib]System.Object + implements I4, + I2, + I1, + I3 +{ +} // end of class I4Class + +.class private auto ansi beforefieldinit I4ReimplementClass + extends [mscorlib]System.Object + implements I4Reimplement, + I2, + I1, + I3 +{ +} // end of class I4ReimplementClass + +.class private auto ansi sealed beforefieldinit I4Struct + extends [mscorlib]System.ValueType + implements I4, + I2, + I1, + I3 +{ +} // end of class I4Struct + +.class interface private abstract auto ansi I5 + implements I1 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I5.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.5 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I5::I1.Func +} // end of class I5 + +.class interface private abstract auto ansi I6 + implements I1 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I6.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.6 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I6::I1.Func +} // end of class I6 + +.class interface private abstract auto ansi I7 + implements I5, + I1, + I6 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I7.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.7 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I7::I1.Func +} // end of class I7 + +.class interface private abstract auto ansi I8 + implements I4, + I2, + I1, + I3, + I7, + I5, + I6 +{ + .method private hidebysig + static int32 I1.Func(int32 a) cil managed + { + .override method int32 I1::Func(int32) + // Code size 20 (0x14) + .maxstack 2 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldstr "At I8.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_000c: ldarg.0 + IL_000d: ldc.i4.8 + IL_000e: add + IL_000f: stloc.0 + IL_0010: br.s IL_0012 + + IL_0012: ldloc.0 + IL_0013: ret + } // end of method I8::I1.Func +} // end of class I8 + +.class private auto ansi beforefieldinit I47Class + extends [mscorlib]System.Object + implements I4, + I2, + I1, + I3, + I7, + I5, + I6 +{ +} // end of class I47Class + +.class private auto ansi sealed beforefieldinit I47Struct + extends [mscorlib]System.ValueType + implements I4, + I2, + I1, + I3, + I7, + I5, + I6 +{ +} // end of class I47Struct + +.class private auto ansi beforefieldinit I8Class + extends [mscorlib]System.Object + implements I8, + I4, + I2, + I1, + I3, + I7, + I5, + I6 +{ +} // end of class I8Class + +.class private auto ansi sealed beforefieldinit I8Struct + extends [mscorlib]System.ValueType + implements I8, + I4, + I2, + I1, + I3, + I7, + I5, + I6 +{ +} // end of class I8Struct + +.class interface private abstract auto ansi GI1`1 +{ + .method public hidebysig newslot abstract virtual + static int32 Func([out] class [mscorlib]System.Type[]& types) cil managed + { + } // end of method GI1`1::'GI1.Func' + +} // end of class GI1`1 + +.class interface private abstract auto ansi GI2`1 + implements class GI1`1 +{ +.method private hidebysig + static int32 'GI1.Func'([out] class [mscorlib]System.Type[]& types) cil managed + { + .override method int32 class GI1`1::Func<[1]>(class [mscorlib]System.Type[]&) + // Code size 100 (0x64) + .maxstack 5 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Object + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldtoken !T + IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0013: stelem.ref + IL_0014: dup + IL_0015: ldc.i4.1 + IL_0016: ldstr ", " + IL_001b: stelem.ref + IL_001c: dup + IL_001d: ldc.i4.2 + IL_001e: ldtoken !!S + IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0028: stelem.ref + IL_0029: dup + IL_002a: ldc.i4.3 + IL_002b: ldstr ", GI2" + IL_0030: stelem.ref + IL_0031: call string [mscorlib]System.String::Concat(object[]) + IL_0036: call void [mscorlib]System.Console::WriteLine(string) + IL_003b: nop + IL_003c: ldarg.0 + IL_003d: ldc.i4.2 + IL_003e: newarr [mscorlib]System.Type + IL_0043: dup + IL_0044: ldc.i4.0 + IL_0045: ldtoken !T + IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_004f: stelem.ref + IL_0050: dup + IL_0051: ldc.i4.1 + IL_0052: ldtoken !!S + IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_005c: stelem.ref + IL_005d: stind.ref + IL_005e: ldc.i4.2 + IL_005f: stloc.0 + IL_0060: br.s IL_0062 + + IL_0062: ldloc.0 + IL_0063: ret + } // end of method G2`1::'GI1.Func' +} // end of class GI2`1 + +.class interface private abstract auto ansi GI3`1 + implements class GI1`1 +{ +.method private hidebysig + static int32 'GI1.Func'([out] class [mscorlib]System.Type[]& types) cil managed + { + .override method int32 class GI1`1::Func<[1]>(class [mscorlib]System.Type[]&) + // Code size 100 (0x64) + .maxstack 5 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Object + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldtoken !T + IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0013: stelem.ref + IL_0014: dup + IL_0015: ldc.i4.1 + IL_0016: ldstr ", " + IL_001b: stelem.ref + IL_001c: dup + IL_001d: ldc.i4.2 + IL_001e: ldtoken !!S + IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0028: stelem.ref + IL_0029: dup + IL_002a: ldc.i4.3 + IL_002b: ldstr ", GI3" + IL_0030: stelem.ref + IL_0031: call string [mscorlib]System.String::Concat(object[]) + IL_0036: call void [mscorlib]System.Console::WriteLine(string) + IL_003b: nop + IL_003c: ldarg.0 + IL_003d: ldc.i4.2 + IL_003e: newarr [mscorlib]System.Type + IL_0043: dup + IL_0044: ldc.i4.0 + IL_0045: ldtoken !T + IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_004f: stelem.ref + IL_0050: dup + IL_0051: ldc.i4.1 + IL_0052: ldtoken !!S + IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_005c: stelem.ref + IL_005d: stind.ref + IL_005e: ldc.i4.3 + IL_005f: stloc.0 + IL_0060: br.s IL_0062 + + IL_0062: ldloc.0 + IL_0063: ret + } // end of method GI3`1::'GI1.Func' +} // end of class GI3`1 + +.class interface private abstract auto ansi GI4`1 + implements class GI2`1, + class GI1`1, + class GI3`1 +{ + .method private hidebysig + static int32 'GI1.Func'([out] class [mscorlib]System.Type[]& types) cil managed + { + .override method int32 class GI1`1::Func<[1]>(class [mscorlib]System.Type[]&) + // Code size 100 (0x64) + .maxstack 5 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldc.i4.4 + IL_0002: newarr [mscorlib]System.Object + IL_0007: dup + IL_0008: ldc.i4.0 + IL_0009: ldtoken !T + IL_000e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0013: stelem.ref + IL_0014: dup + IL_0015: ldc.i4.1 + IL_0016: ldstr ", " + IL_001b: stelem.ref + IL_001c: dup + IL_001d: ldc.i4.2 + IL_001e: ldtoken !!S + IL_0023: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_0028: stelem.ref + IL_0029: dup + IL_002a: ldc.i4.3 + IL_002b: ldstr ", GI4" + IL_0030: stelem.ref + IL_0031: call string [mscorlib]System.String::Concat(object[]) + IL_0036: call void [mscorlib]System.Console::WriteLine(string) + IL_003b: nop + IL_003c: ldarg.0 + IL_003d: ldc.i4.2 + IL_003e: newarr [mscorlib]System.Type + IL_0043: dup + IL_0044: ldc.i4.0 + IL_0045: ldtoken !T + IL_004a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_004f: stelem.ref + IL_0050: dup + IL_0051: ldc.i4.1 + IL_0052: ldtoken !!S + IL_0057: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_005c: stelem.ref + IL_005d: stind.ref + IL_005e: ldc.i4.4 + IL_005f: stloc.0 + IL_0060: br.s IL_0062 + + IL_0062: ldloc.0 + IL_0063: ret + } // end of method GI4`1::'GI1.Func' +} // end of class GI4`1 + +.class private auto ansi beforefieldinit GI23Class`1 + extends [mscorlib]System.Object + implements class GI2`1, + class GI1`1, + class GI3`1 +{ +} // end of class GI23Class`1 + +.class private auto ansi sealed beforefieldinit GI23Struct`1 + extends [mscorlib]System.ValueType + implements class GI2`1, + class GI1`1, + class GI3`1 +{ +} // end of class GI23Struct`1 + +.class private auto ansi beforefieldinit GI4Class`1 + extends [mscorlib]System.Object + implements class GI4`1, + class GI2`1, + class GI1`1, + class GI3`1 +{ +} // end of class GI4Class`1 + +.class private auto ansi sealed beforefieldinit GI4Struct`1 + extends [mscorlib]System.ValueType + implements class GI4`1, + class GI2`1, + class GI1`1, + class GI3`1 +{ +} // end of class GI4Struct`1 + +.class interface private abstract auto ansi IResolutionAtRuntime`1 +{ + .method public hidebysig newslot abstract virtual static int32 Func(int32 arg) cil managed + { + } // end of method IResolutionAtRuntime`1::Func + +} // end of class GI1`1 + +.class private auto ansi beforefieldinit ResolutionAtRuntimeBase + implements class IResolutionAtRuntime`1, + class IResolutionAtRuntime`1 +{ + .method private hidebysig static int32 FuncObject(int32 arg) cil managed + { + .override method int32 class IResolutionAtRuntime`1::Func(int32) + ldstr "At ResolutionAtRuntimeBase.FuncObject" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldarg.0 + ldc.i4.s 19 + add + ret + } + + .method private hidebysig static int32 FuncString(int32 arg) cil managed + { + .override method int32 class IResolutionAtRuntime`1::Func(int32) + ldstr "At ResolutionAtRuntimeBase.FuncString" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldarg.0 + ldc.i4.s 23 + add + ret + } +} + +.class private auto ansi beforefieldinit ResolutionAtRuntimeThisObj`2<(class IResolutionAtRuntime`1) T, V> + extends [mscorlib]System.Object +{ + .method public hidebysig specialname rtspecialname + instance void .ctor() il managed + { + ldarg.0 + call instance void [mscorlib]System.Object::.ctor() + ret + } // end of method 'Test::.ctor' + + + .method public hidebysig instance int32 RuntimeResolvedFunc(int32 arg) + { + ldstr "At ResolutionAtRuntimeThisObj::RuntimeResolvedFunc" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldarg.1 + constrained. !T + call int32 class [svm_diamondshape]IResolutionAtRuntime`1::Func(int32) + ret + } + +} // end of class ResolutionAtRuntimeThisObj + + +.class private auto ansi beforefieldinit ResolutionAtRuntimeClassParam`2<(class IResolutionAtRuntime`1) T, V> +{ + .method public hidebysig static int32 RuntimeResolvedFunc(int32 arg) + { + ldstr "At ResolutionAtRuntimeClassParam::RuntimeResolvedFunc" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldarg.0 + constrained. !T + call int32 class [svm_diamondshape]IResolutionAtRuntime`1::Func(int32) + ret + } + +} // end of class ResolutionAtRuntimeClassParam + +.class private auto ansi beforefieldinit ResolutionAtRuntimeMethodParam +{ + .method public hidebysig static int32 RuntimeResolvedFunc`2<(class IResolutionAtRuntime`1) T, V>(int32 arg) + { + ldstr "At ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldarg.0 + constrained. !!T + call int32 class [svm_diamondshape]IResolutionAtRuntime`1::Func(int32) + ret + } + +} // end of class ResolutionAtRuntimeMethodParam + +.class private auto ansi beforefieldinit Program + extends [mscorlib]System.Object +{ + .method public hidebysig static void Negative() cil managed + { + // Code size 225 (0xe1) + .maxstack 10 + .locals init ( + class [mscorlib]System.Exception V_6, + class [mscorlib]System.Exception V_7, + class [mscorlib]System.Type[] V_8, + class [mscorlib]System.Exception V_9) + IL_0000: nop + IL_0009: ldstr "Calling IFoo.Foo on FooClass - expecting exception." + IL_000e: call void [mscorlib]System.Console::WriteLine(string) + IL_0013: nop + .try + { + IL_0014: nop + IL_0016: ldc.i4.s 10 + constrained. class [svm_diamondshape]FooClass + IL_0018: call int32 IFoo::Foo(int32) + IL_001d: pop + IL_001e: ldc.i4.0 + IL_001f: ldstr "Expecting exception on FooClass" + IL_0024: call void Test::Assert(bool, + string) + IL_0029: nop + IL_002a: nop + IL_002b: leave.s IL_004aa + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + IL_002d: stloc.s V_6 + IL_002f: nop + IL_0030: ldstr "Exception caught: " + IL_0035: ldloc.s V_6 + IL_0037: callvirt instance string [mscorlib]System.Object::ToString() + IL_003c: call string [mscorlib]System.String::Concat(string, + string) + IL_0041: call void [mscorlib]System.Console::WriteLine(string) + IL_0046: nop + IL_0047: nop + IL_0048: leave.s IL_004aa + + } // end handler + + IL_004aa: ldstr "Resolving delegate IFoo.Foo on FooClass - expecting exception." + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. class [svm_diamondshape]FooClass + ldftn int32 IFoo::Foo(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on FooClass" + call void Test::Assert(bool, string) + nop + leave.s IL_004ab + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_6 + nop + ldstr "Exception caught: " + ldloc.s V_6 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, string) + call void [mscorlib]System.Console::WriteLine(string) + nop + leave.s IL_004ab + + } // end handler + + IL_004ab: nop + ldstr "Calling IFoo.Foo on FooClassReabstract - expecting exception." + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. class [svm_diamondshape]FooClassReabstract + call int32 IFoo::Foo(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on FooClassReabstract" + call void Test::Assert(bool, + string) + nop + leave.s IL_004ac + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_6 + nop + ldstr "Exception caught: " + ldloc.s V_6 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, + string) + call void [mscorlib]System.Console::WriteLine(string) + nop + leave.s IL_004ac + + } // end handler + + IL_004ac: nop + ldstr "Calling IFoo.Foo on FooStruct - expecting exception." + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. valuetype [svm_diamondshape]FooStruct + call int32 IFoo::Foo(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on FooStruct" + call void Test::Assert(bool, + string) + nop + leave.s IL_004ad + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_6 + nop + ldstr "Exception caught: " + ldloc.s V_6 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, + string) + call void [mscorlib]System.Console::WriteLine(string) + nop + leave.s IL_004ad + + } // end handler + + IL_004ad: nop + ldstr "Resolving delegate IFoo.Foo on FooStruct - expecting exception." + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. valuetype [svm_diamondshape]FooStruct + ldftn int32 IFoo::Foo(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on FooStruct" + call void Test::Assert(bool, + string) + nop + leave.s IL_004a + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_6 + nop + ldstr "Exception caught: " + ldloc.s V_6 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, + string) + call void [mscorlib]System.Console::WriteLine(string) + nop + leave.s IL_004a + + } // end handler + + IL_004a: ldstr "Calling I1.Func on I47Class - expecting exception" + IL_0057: call void [mscorlib]System.Console::WriteLine(string) + IL_005c: nop + .try + { + IL_005d: nop + IL_005f: ldc.i4.s 10 + constrained. class [svm_diamondshape]I47Class + IL_0061: call int32 I1::Func(int32) + IL_0066: pop + IL_0067: ldc.i4.0 + IL_0068: ldstr "Expecting exception on I47Class" + IL_006d: call void Test::Assert(bool, + string) + IL_0072: nop + IL_0073: nop + IL_0074: leave.s IL_0093a + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + IL_0076: stloc.s V_7 + IL_0078: nop + IL_0079: ldstr "Exception caught: " + IL_007e: ldloc.s V_7 + IL_0080: callvirt instance string [mscorlib]System.Object::ToString() + IL_0085: call string [mscorlib]System.String::Concat(string, + string) + IL_008a: call void [mscorlib]System.Console::WriteLine(string) + IL_008f: nop + IL_0090: nop + IL_0091: leave.s IL_0093a + + } // end handler + + IL_0093a: ldstr "Resolving delegate I1.Func on I47Class - expecting exception" + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. class [svm_diamondshape]I47Class + ldftn int32 I1::Func(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on I47Class" + call void Test::Assert(bool, string) + nop + nop + leave.s IL_0093b + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_7 + nop + ldstr "Exception caught: " + ldloc.s V_7 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, string) + call void [mscorlib]System.Console::WriteLine(string) + nop + nop + leave.s IL_0093b + + } // end handler + + IL_0093b: ldstr "Calling I1.Func on I47Struct - expecting exception" + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. valuetype [svm_diamondshape]I47Struct + call int32 I1::Func(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on I47Struct" + call void Test::Assert(bool, string) + nop + nop + leave.s IL_0093c + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_7 + nop + ldstr "Exception caught: " + ldloc.s V_7 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, string) + call void [mscorlib]System.Console::WriteLine(string) + nop + nop + leave.s IL_0093c + + } // end handler + + IL_0093c: ldstr "Resolving delegate I1.Func on I47Struct - expecting exception" + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldc.i4.s 10 + constrained. valuetype [svm_diamondshape]I47Struct + ldftn int32 I1::Func(int32) + pop + ldc.i4.0 + ldstr "Expecting exception on I47Struct" + call void Test::Assert(bool, string) + nop + nop + leave.s IL_0093 + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_7 + nop + ldstr "Exception caught: " + ldloc.s V_7 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, string) + call void [mscorlib]System.Console::WriteLine(string) + nop + nop + leave.s IL_0093 + + } // end handler + + IL_0093: ldstr "Calling GI1.Func on GI23Class - expecting exception" + IL_00a3: call void [mscorlib]System.Console::WriteLine(string) + IL_00a8: nop + .try + { + IL_00a9: nop + IL_00ac: ldloca.s V_8 + constrained. class [svm_diamondshape]GI23Class`1 + IL_00ae: call int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + IL_00b3: pop + IL_00b4: ldc.i4.0 + IL_00b5: ldstr "Expecting exception on GI23Class" + IL_00ba: call void Test::Assert(bool, string) + IL_00bf: nop + IL_00c0: nop + IL_00c1: leave.s IL_00e0a + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + IL_00c3: stloc.s V_9 + IL_00c5: nop + IL_00c6: ldstr "Exception caught: " + IL_00cb: ldloc.s V_9 + IL_00cd: callvirt instance string [mscorlib]System.Object::ToString() + IL_00d2: call string [mscorlib]System.String::Concat(string, string) + IL_00d7: call void [mscorlib]System.Console::WriteLine(string) + IL_00dc: nop + IL_00de: leave.s IL_00e0a + + } // end handler + + IL_00e0a: ldstr "Resolving delegate GI1.Func on GI23Class - expecting exception" + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldloca.s V_8 + constrained. class [svm_diamondshape]GI23Class`1 + ldftn int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + pop + ldc.i4.0 + ldstr "Expecting exception on GI23Class" + call void Test::Assert(bool, + string) + nop + leave.s IL_00e0b + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_9 + nop + ldstr "Exception caught: " + ldloc.s V_9 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, + string) + call void [mscorlib]System.Console::WriteLine(string) + nop + nop + leave.s IL_00e0b + + } // end handler + + IL_00e0b: ldstr "Calling GI1.Func on GI23Struct - expecting exception" + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldloca.s V_8 + constrained. valuetype [svm_diamondshape]GI23Struct`1 + call int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + pop + ldc.i4.0 + ldstr "Expecting exception on GI23Class" + call void Test::Assert(bool, + string) + nop + leave.s IL_00e0c + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_9 + nop + ldstr "Exception caught: " + ldloc.s V_9 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, + string) + call void [mscorlib]System.Console::WriteLine(string) + nop + nop + leave.s IL_00e0c + + } // end handler + + IL_00e0c: ldstr "Resolving delegate GI1.Func on GI23Struct - expecting exception" + call void [mscorlib]System.Console::WriteLine(string) + nop + .try + { + nop + ldloca.s V_8 + constrained. valuetype [svm_diamondshape]GI23Struct`1 + ldftn int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + pop + ldc.i4.0 + ldstr "Expecting exception on GI23Class" + call void Test::Assert(bool, + string) + nop + leave.s IL_00e0 + + } // end .try + catch [System.Runtime]System.Runtime.AmbiguousImplementationException + { + stloc.s V_9 + nop + ldstr "Exception caught: " + ldloc.s V_9 + callvirt instance string [mscorlib]System.Object::ToString() + call string [mscorlib]System.String::Concat(string, + string) + call void [mscorlib]System.Console::WriteLine(string) + nop + nop + leave.s IL_00e0 + + } // end handler + + IL_00e0: ret + } // end of method Program::Negative + + .method public hidebysig static void Positive() cil managed + { + // Code size 189 (0xbd) + .maxstack 10 + .locals init (class [mscorlib]System.Type[] V_4) + IL_0000: nop + IL_0001: ldstr "Calling I1.Func on I4Class - expecting I4.Func" + IL_0006: call void [mscorlib]System.Console::WriteLine(string) + IL_000b: nop + IL_0015: ldc.i4.s 10 + constrained. class I4Class + IL_0017: call int32 I1::Func(int32) + IL_001c: ldc.i4.s 14 + IL_001e: ceq + IL_0020: ldstr "Expecting I1.Func to land on I4.Func" + IL_0025: call void Test::Assert(bool, string) + IL_002a: nop + + ldstr "Calling I1.Func on I4ReimplementClass - expecting I4Reimplement.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. class I4ReimplementClass + call int32 I1::Func(int32) + ldc.i4.s 27 + ceq + ldstr "Expecting I1.Func to land on I4Reimplement.Func" + call void Test::Assert(bool, string) + nop + + ldstr "Calling I1.Func on I4Class as a delegate - expecting I4.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. class I4Class + ldftn int32 I1::Func(int32) + calli int32(int32) + ldc.i4.s 14 + ceq + ldstr "Expecting I1.Func to land on I4.Func" + call void Test::Assert(bool, string) + nop + + ldstr "Calling I1.Func on I4Struct - expecting I4.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. valuetype I4Struct + call int32 I1::Func(int32) + ldc.i4.s 14 + ceq + ldstr "Expecting I1.Func to land on I4.Func" + call void Test::Assert(bool, string) + nop + + ldstr "Calling I1.Func on I4Struct as a delegate - expecting I4.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. valuetype I4Struct + ldftn int32 I1::Func(int32) + calli int32(int32) + ldc.i4.s 14 + ceq + ldstr "Expecting I1.Func to land on I4.Func" + call void Test::Assert(bool, string) + nop + + IL_002b: ldstr "Calling I1.Func on I8Class - expecting I8.Func" + IL_0030: call void [mscorlib]System.Console::WriteLine(string) + IL_0035: nop + IL_003f: ldc.i4.s 10 + constrained. class [svm_diamondshape]I8Class + IL_0041: call int32 I1::Func(int32) + IL_0046: ldc.i4.s 18 + IL_0048: ceq + IL_004a: ldstr "Expecting I1.Func to land on I8.Func" + IL_004f: call void Test::Assert(bool, string) + IL_0054: nop + + ldstr "Calling I1.Func on I8Class as a delegate - expecting I8.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. class [svm_diamondshape]I8Class + ldftn int32 I1::Func(int32) + calli int32(int32) + ldc.i4.s 18 + ceq + ldstr "Expecting I1.Func to land on I8.Func" + call void Test::Assert(bool, string) + nop + + ldstr "Calling I1.Func on I8Struct - expecting I8.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. valuetype [svm_diamondshape]I8Struct + call int32 I1::Func(int32) + ldc.i4.s 18 + ceq + ldstr "Expecting I1.Func to land on I8.Func" + call void Test::Assert(bool, string) + nop + + ldstr "Calling I1.Func on I8Struct as a delegate - expecting I8.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 10 + constrained. valuetype [svm_diamondshape]I8Struct + ldftn int32 I1::Func(int32) + calli int32(int32) + ldc.i4.s 18 + ceq + ldstr "Expecting I1.Func to land on I8.Func" + call void Test::Assert(bool, string) + nop + + IL_0055: ldstr "Calling GI1.Func on GI4Class - expecting GI4.Func" + IL_005a: call void [mscorlib]System.Console::WriteLine(string) + IL_005f: nop + IL_006b: ldloca.s V_4 + constrained. class [svm_diamondshape]GI4Class`1 + IL_006d: call int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + IL_0072: ldc.i4.4 + IL_0073: ceq + IL_0075: ldstr "Expecting GI1.Func to land on GII4.Func" + IL_007a: call void Test::Assert(bool, string) + IL_007f: nop + + ldloc.s V_4 + ldc.i4.0 + ldelem.ref + ldtoken [mscorlib]System.Object + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + ldstr "T must be object" + call void Test::Assert(bool, string) + nop + ldloc.s V_4 + ldc.i4.1 + ldelem.ref + ldtoken [mscorlib]System.String + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + ldstr "S must be string" + call void Test::Assert(bool, string) + nop + + ldstr "Calling GI1.Func on GI4Class as a delegate - expecting GI4.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldloca.s V_4 + constrained. class [svm_diamondshape]GI4Class`1 + ldftn int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + calli int32(class [mscorlib]System.Type[]&) + ldc.i4.4 + ceq + ldstr "Expecting GI1.Func to land on GII4.Func" + call void Test::Assert(bool, string) + nop + + ldloc.s V_4 + ldc.i4.0 + ldelem.ref + ldtoken [mscorlib]System.Object + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + ldstr "T must be object" + call void Test::Assert(bool, string) + nop + ldloc.s V_4 + ldc.i4.1 + ldelem.ref + ldtoken [mscorlib]System.String + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + ldstr "S must be string" + call void Test::Assert(bool, string) + nop + + ldstr "Calling GI1.Func on GI4Struct - expecting GI4.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldloca.s V_4 + constrained. valuetype [svm_diamondshape]GI4Struct`1 + call int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + ldc.i4.4 + ceq + ldstr "Expecting GI1.Func to land on GII4.Func" + call void Test::Assert(bool, string) + nop + + IL_0080: ldloc.s V_4 + IL_0082: ldc.i4.0 + IL_0083: ldelem.ref + IL_0084: ldtoken [mscorlib]System.Object + IL_0089: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_008e: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + IL_0093: ldstr "T must be object" + IL_0098: call void Test::Assert(bool, string) + IL_009d: nop + IL_009e: ldloc.s V_4 + IL_00a0: ldc.i4.1 + IL_00a1: ldelem.ref + IL_00a2: ldtoken [mscorlib]System.String + IL_00a7: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + IL_00ac: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + IL_00b1: ldstr "S must be string" + IL_00b6: call void Test::Assert(bool, string) + IL_00bb: nop + + ldstr "Calling GI1.Func on GI4Struct as a delegate - expecting GI4.Func" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldloca.s V_4 + constrained. valuetype [svm_diamondshape]GI4Struct`1 + ldftn int32 class GI1`1::Func(class [mscorlib]System.Type[]&) + calli int32(class [mscorlib]System.Type[]&) + ldc.i4.4 + ceq + ldstr "Expecting GI1.Func to land on GII4.Func" + call void Test::Assert(bool, string) + nop + + ldloc.s V_4 + ldc.i4.0 + ldelem.ref + ldtoken [mscorlib]System.Object + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + ldstr "T must be object" + call void Test::Assert(bool, string) + nop + ldloc.s V_4 + ldc.i4.1 + ldelem.ref + ldtoken [mscorlib]System.String + call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle) + call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type) + ldstr "S must be string" + call void Test::Assert(bool, string) + nop + + ldstr "Calling ResolutionAtRuntimeThisObj::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncObject" + call void [mscorlib]System.Console::WriteLine(string) + nop + newobj instance void class ResolutionAtRuntimeThisObj`2::.ctor() + ldc.i4.s 200 + call instance int32 class ResolutionAtRuntimeThisObj`2::RuntimeResolvedFunc(int32) + ldc.i4.s 219 + ceq + ldstr "Expecting ResolutionAtRuntimeThisObj::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncObject" + call void Test::Assert(bool, string) + + ldstr "Calling ResolutionAtRuntimeThisObj::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncString" + call void [mscorlib]System.Console::WriteLine(string) + nop + newobj instance void class ResolutionAtRuntimeThisObj`2::.ctor() + ldc.i4.s 200 + call instance int32 class ResolutionAtRuntimeThisObj`2::RuntimeResolvedFunc(int32) + ldc.i4.s 223 + ceq + ldstr "Expecting ResolutionAtRuntimeThisObj::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncString" + call void Test::Assert(bool, string) + + + ldstr "Calling ResolutionAtRuntimeClassParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncObject" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 200 + call int32 class ResolutionAtRuntimeClassParam`2::RuntimeResolvedFunc(int32) + ldc.i4.s 219 + ceq + ldstr "Expecting ResolutionAtRuntimeClassParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncObject" + call void Test::Assert(bool, string) + + ldstr "Calling ResolutionAtRuntimeClassParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncString" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 200 + call int32 class ResolutionAtRuntimeClassParam`2::RuntimeResolvedFunc(int32) + ldc.i4.s 223 + ceq + ldstr "Expecting ResolutionAtRuntimeClassParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncString" + call void Test::Assert(bool, string) + + + ldstr "Calling ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncObject" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 100 + call int32 class ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc`2(int32) + ldc.i4.s 119 + ceq + ldstr "Expecting ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncObject" + call void Test::Assert(bool, string) + + ldstr "Calling ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc - expecting ResolutionAtRuntimeBase.FuncString" + call void [mscorlib]System.Console::WriteLine(string) + nop + ldc.i4.s 100 + call int32 class ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc`2(int32) + ldc.i4.s 123 + ceq + ldstr "Expecting ResolutionAtRuntimeMethodParam::RuntimeResolvedFunc to land on ResolutionAtRuntimeBase.FuncString" + call void Test::Assert(bool, string) + + IL_00bc: ret + } // end of method Program::Positive + + .method public hidebysig static int32 Main() cil managed + { + .custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = ( + 01 00 00 00 + ) + .entrypoint + // Code size 23 (0x17) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: call void Program::Negative() + IL_0006: nop + IL_0007: call void Program::Positive() + IL_000c: nop + IL_000d: call int32 Test::Ret() + IL_0012: stloc.0 + IL_0013: br.s IL_0015 + + IL_0015: ldloc.0 + IL_0016: ret + } // end of method Program::Main + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method Program::.ctor + +} // end of class Program + +.class private auto ansi beforefieldinit Test + extends [mscorlib]System.Object +{ + .field private static bool Pass + .method public hidebysig static int32 Ret() cil managed + { + // Code size 19 (0x13) + .maxstack 1 + .locals init (int32 V_0) + IL_0000: nop + IL_0001: ldsfld bool Test::Pass + IL_0006: brtrue.s IL_000c + + IL_0008: ldc.i4.s 101 + IL_000a: br.s IL_000e + + IL_000c: ldc.i4.s 100 + IL_000e: stloc.0 + IL_000f: br.s IL_0011 + + IL_0011: ldloc.0 + IL_0012: ret + } // end of method Test::Ret + + .method public hidebysig static void Assert(bool cond, + string msg) cil managed + { + // Code size 47 (0x2f) + .maxstack 2 + .locals init (bool V_0) + IL_0000: nop + IL_0001: ldarg.0 + IL_0002: stloc.0 + IL_0003: ldloc.0 + IL_0004: brfalse.s IL_0015 + + IL_0006: nop + IL_0007: ldstr "PASS" + IL_000c: call void [mscorlib]System.Console::WriteLine(string) + IL_0011: nop + IL_0012: nop + IL_0013: br.s IL_002e + + IL_0015: nop + IL_0016: ldstr "FAIL: " + IL_001b: ldarg.1 + IL_001c: call string [mscorlib]System.String::Concat(string, + string) + IL_0021: call void [mscorlib]System.Console::WriteLine(string) + IL_0026: nop + IL_0027: ldc.i4.0 + IL_0028: stsfld bool Test::Pass + IL_002d: nop + IL_002e: ret + } // end of method Test::Assert + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 8 (0x8) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: nop + IL_0007: ret + } // end of method Test::.ctor + + .method private hidebysig specialname rtspecialname static + void .cctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld bool Test::Pass + IL_0006: ret + } // end of method Test::.cctor + +} // end of class Test + + +// ============================================================= + +// *********** DISASSEMBLY COMPLETE *********************** +// WARNING: Created Win32 resource file diamondshape.res diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_d.ilproj b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_d.ilproj new file mode 100644 index 00000000000000..5a90175fe318f9 --- /dev/null +++ b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_d.ilproj @@ -0,0 +1,11 @@ + + + Exe + + + Full + + + + + diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj new file mode 100644 index 00000000000000..f036395dbd3f95 --- /dev/null +++ b/src/tests/Loader/classloader/StaticVirtualMethods/DiamondShape/svm_diamondshape_r.ilproj @@ -0,0 +1,11 @@ + + + Exe + + + + + + + +