@@ -5658,6 +5658,22 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited, const
5658
5658
5659
5659
}
5660
5660
5661
+ // Validate implementation of virtual static methods on all implemented interfaces unless:
5662
+ // 1) The type resides in a module where sanity checks are disabled (such as System.Private.CoreLib, or an
5663
+ // R2R module with type checks disabled)
5664
+ // 2) There are no virtual static methods defined on any of the interfaces implemented by this type;
5665
+ // 3) The type is abstract in which case it's allowed to leave some virtual static methods unimplemented
5666
+ // akin to equivalent behavior of virtual instance method overriding in abstract classes;
5667
+ // 4) The type is a not the typical type definition. (The typical type is always checked)
5668
+
5669
+ if (fNeedsSanityChecks &&
5670
+ IsTypicalTypeDefinition() &&
5671
+ !IsAbstract())
5672
+ {
5673
+ if (HasVirtualStaticMethods())
5674
+ VerifyThatAllVirtualStaticMethodsAreImplemented();
5675
+ }
5676
+
5661
5677
if (locals.fBailed)
5662
5678
{
5663
5679
// We couldn't complete security checks on some dependency because it is already being processed by one of our callers.
@@ -5671,22 +5687,6 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited, const
5671
5687
}
5672
5688
else
5673
5689
{
5674
- // Validate implementation of virtual static methods on all implemented interfaces unless:
5675
- // 1) The type resides in the system module (System.Private.CoreLib); we own this module and ensure
5676
- // its consistency by other means not requiring runtime checks;
5677
- // 2) There are no virtual static methods defined on any of the interfaces implemented by this type;
5678
- // 3) The method is abstract in which case it's allowed to leave some virtual static methods unimplemented
5679
- // akin to equivalent behavior of virtual instance method overriding in abstract classes;
5680
- // 4) The type is a shared generic in which case we generally don't have enough information to perform
5681
- // the validation.
5682
- if (!GetModule()->IsSystem() &&
5683
- HasVirtualStaticMethods() &&
5684
- !IsAbstract() &&
5685
- !IsSharedByGenericInstantiations())
5686
- {
5687
- VerifyThatAllVirtualStaticMethodsAreImplemented();
5688
- }
5689
-
5690
5690
// Finally, mark this method table as fully loaded
5691
5691
SetIsFullyLoaded();
5692
5692
}
@@ -9201,7 +9201,7 @@ MethodDesc *MethodTable::GetDefaultConstructor(BOOL forceBoxedEntryPoint /* = FA
9201
9201
//==========================================================================================
9202
9202
// Finds the (non-unboxing) MethodDesc that implements the interface virtual static method pInterfaceMD.
9203
9203
MethodDesc *
9204
- MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL checkDuplicates , BOOL allowVariantMatches)
9204
+ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL allowNullResult, BOOL verifyImplemented , BOOL allowVariantMatches)
9205
9205
{
9206
9206
if (!pInterfaceMD->IsSharedByGenericMethodInstantiations() && !pInterfaceType->IsSharedByGenericInstantiations())
9207
9207
{
@@ -9231,7 +9231,7 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc*
9231
9231
// Search for match on a per-level in the type hierarchy
9232
9232
for (MethodTable* pMT = this; pMT != nullptr; pMT = pMT->GetParentMethodTable())
9233
9233
{
9234
- MethodDesc* pMD = pMT->TryResolveVirtualStaticMethodOnThisType(pInterfaceType, pInterfaceMD, checkDuplicates );
9234
+ MethodDesc* pMD = pMT->TryResolveVirtualStaticMethodOnThisType(pInterfaceType, pInterfaceMD, verifyImplemented );
9235
9235
if (pMD != nullptr)
9236
9236
{
9237
9237
return pMD;
@@ -9273,7 +9273,7 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc*
9273
9273
{
9274
9274
// Variant or equivalent matching interface found
9275
9275
// Attempt to resolve on variance matched interface
9276
- pMD = pMT->TryResolveVirtualStaticMethodOnThisType(it.GetInterface(), pInterfaceMD, checkDuplicates );
9276
+ pMD = pMT->TryResolveVirtualStaticMethodOnThisType(it.GetInterface(), pInterfaceMD, verifyImplemented );
9277
9277
if (pMD != nullptr)
9278
9278
{
9279
9279
return pMD;
@@ -9295,7 +9295,7 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc*
9295
9295
// Try to locate the appropriate MethodImpl matching a given interface static virtual method.
9296
9296
// Returns nullptr on failure.
9297
9297
MethodDesc*
9298
- MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL checkDuplicates )
9298
+ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType, MethodDesc* pInterfaceMD, BOOL verifyImplemented )
9299
9299
{
9300
9300
HRESULT hr = S_OK;
9301
9301
IMDInternalImport* pMDInternalImport = GetMDImport();
@@ -9347,13 +9347,39 @@ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType
9347
9347
{
9348
9348
continue;
9349
9349
}
9350
- MethodDesc *pMethodDecl = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(
9350
+ MethodDesc *pMethodDecl;
9351
+
9352
+ if ((TypeFromToken(methodDecl) == mdtMethodDef) || pInterfaceMT->IsFullyLoaded())
9353
+ {
9354
+ pMethodDecl = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(
9351
9355
GetModule(),
9352
9356
methodDecl,
9353
9357
&sigTypeContext,
9354
9358
/* strictMetadataChecks */ FALSE,
9355
9359
/* allowInstParam */ FALSE,
9356
9360
/* owningTypeLoadLevel */ CLASS_LOAD_EXACTPARENTS);
9361
+ }
9362
+ else if (TypeFromToken(methodDecl) == mdtMemberRef)
9363
+ {
9364
+ LPCUTF8 szMember;
9365
+ PCCOR_SIGNATURE pSig;
9366
+ DWORD cSig;
9367
+
9368
+ IfFailThrow(pMDInternalImport->GetNameAndSigOfMemberRef(methodDecl, &pSig, &cSig, &szMember));
9369
+
9370
+ // Do a quick name check to avoid excess use of FindMethod
9371
+ if (strcmp(szMember, pInterfaceMD->GetName()) != 0)
9372
+ {
9373
+ continue;
9374
+ }
9375
+
9376
+ pMethodDecl = MemberLoader::FindMethod(pInterfaceMT, szMember, pSig, cSig, GetModule());
9377
+ }
9378
+ else
9379
+ {
9380
+ COMPlusThrow(kTypeLoadException, E_FAIL);
9381
+ }
9382
+
9357
9383
if (pMethodDecl == nullptr)
9358
9384
{
9359
9385
COMPlusThrow(kTypeLoadException, E_FAIL);
@@ -9369,13 +9395,11 @@ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType
9369
9395
COMPlusThrow(kTypeLoadException, E_FAIL);
9370
9396
}
9371
9397
9372
- MethodDesc *pMethodImpl = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec (
9398
+ MethodDesc *pMethodImpl = MemberLoader::GetMethodDescFromMethodDef (
9373
9399
GetModule(),
9374
9400
methodBody,
9375
- &sigTypeContext,
9376
- /* strictMetadataChecks */ FALSE,
9377
- /* allowInstParam */ FALSE,
9378
- /* owningTypeLoadLevel */ CLASS_LOAD_EXACTPARENTS);
9401
+ FALSE,
9402
+ CLASS_LOAD_EXACTPARENTS);
9379
9403
if (pMethodImpl == nullptr)
9380
9404
{
9381
9405
COMPlusThrow(kTypeLoadException, E_FAIL);
@@ -9388,7 +9412,7 @@ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType
9388
9412
COMPlusThrow(kTypeLoadException, E_FAIL);
9389
9413
}
9390
9414
9391
- if (pInterfaceMD->HasMethodInstantiation() || pMethodImpl->HasMethodInstantiation() || HasInstantiation() )
9415
+ if (!verifyImplemented )
9392
9416
{
9393
9417
pMethodImpl = pMethodImpl->FindOrCreateAssociatedMethodDesc(
9394
9418
pMethodImpl,
@@ -9398,11 +9422,11 @@ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType
9398
9422
/* allowInstParam */ FALSE,
9399
9423
/* forceRemotableMethod */ FALSE,
9400
9424
/* allowCreate */ TRUE,
9401
- /* level */ CLASS_LOAD_EXACTPARENTS );
9425
+ /* level */ CLASS_LOADED );
9402
9426
}
9403
9427
if (pMethodImpl != nullptr)
9404
9428
{
9405
- if (!checkDuplicates )
9429
+ if (!verifyImplemented )
9406
9430
{
9407
9431
return pMethodImpl;
9408
9432
}
@@ -9432,7 +9456,7 @@ MethodTable::VerifyThatAllVirtualStaticMethodsAreImplemented()
9432
9456
MethodDesc *pMD = it.GetMethodDesc();
9433
9457
if (pMD->IsVirtual() &&
9434
9458
pMD->IsStatic() &&
9435
- !ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* checkDuplicates */ TRUE, /* allowVariantMatches */ FALSE))
9459
+ !ResolveVirtualStaticMethod(pInterfaceMT, pMD, /* allowNullResult */ TRUE, /* verifyImplemented */ TRUE, /* allowVariantMatches */ FALSE))
9436
9460
{
9437
9461
IMDInternalImport* pInternalImport = GetModule()->GetMDImport();
9438
9462
GetModule()->GetAssembly()->ThrowTypeLoadException(pInternalImport, GetCl(), pMD->GetName(), IDS_CLASSLOAD_STATICVIRTUAL_NOTIMPL);
0 commit comments