diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp index 167ccf0f55127d..8521a80c0eb305 100644 --- a/src/coreclr/vm/typedesc.cpp +++ b/src/coreclr/vm/typedesc.cpp @@ -1903,6 +1903,30 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra // if a concrete type can be cast to the constraint, then this constraint will be satisifed if (thElem.CanCastTo(thConstraint)) { + // Static virtual methods need an extra check when an abstract type is used for instantiation + // to ensure that the implementation of the constraint is complete + if (!thElem.IsTypeDesc() && + thElem.AsMethodTable()->IsAbstract() && + thConstraint.IsInterface() && + thConstraint.AsMethodTable()->HasVirtualStaticMethods()) + { + MethodTable *pInterfaceMT = thConstraint.AsMethodTable(); + bool virtualStaticResolutionCheckFailed = false; + for (MethodTable::MethodIterator it(pInterfaceMT); it.IsValid(); it.Next()) + { + MethodDesc *pMD = it.GetMethodDesc(); + if (pMD->IsVirtual() && + pMD->IsStatic() && + !thElem.AsMethodTable()->ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* checkDuplicates */ TRUE)) + { + virtualStaticResolutionCheckFailed = true; + break; + } + } + + if (virtualStaticResolutionCheckFailed) + continue; + } fCanCast = TRUE; break; } diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/NegativeTestCases/UnimplementedAbstractMethodOnAbstractClass.il b/src/tests/Loader/classloader/StaticVirtualMethods/NegativeTestCases/UnimplementedAbstractMethodOnAbstractClass.il index 8155c485e3a105..a4109f46a74704 100644 --- a/src/tests/Loader/classloader/StaticVirtualMethods/NegativeTestCases/UnimplementedAbstractMethodOnAbstractClass.il +++ b/src/tests/Loader/classloader/StaticVirtualMethods/NegativeTestCases/UnimplementedAbstractMethodOnAbstractClass.il @@ -131,14 +131,14 @@ ConstrainedCallOnAbstractClassToAbstractMethodOnSharedGenericDone: nop .try { call void TestEntrypoint::TestScenario2Wrapper() ldstr "ConstraintCheckShouldFail" - ldstr "TypeLoadException" + ldstr "VerificationException" ldstr "Did not throw exception" call void [TypeHierarchyCommonCs]Statics::CheckForFailure(string,string,string) leave.s ConstraintCheckShouldFailDone } catch [System.Runtime]System.Exception { stloc.0 ldstr "ConstraintCheckShouldFail" - ldstr "TypeLoadException" + ldstr "VerificationException" ldloc.0 callvirt instance class [System.Runtime]System.Type [System.Runtime]System.Exception::GetType() callvirt instance string [System.Runtime]System.Reflection.MemberInfo::get_Name()