Repository: dotnet/runtime
File: src/coreclr/vm/class.cpp (C++)

Code before:
        return;

    // Step 1: Validate compatibility of return types on overriding methods
    if (pMT->GetClass()->HasCovariantOverride() && !pMT->GetModule()->SkipTypeValidation())
    {
        for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++)
        {
            if (pMT->GetRestoredSlot(i) == pParentMT->GetRestoredSlot(i))
            {
                // The real check is that the MethodDesc's must not match, but a simple VTable check will
                // work most of the time, and is far faster than the GetMethodDescForSlot method.
                _ASSERTE(pMT->GetMethodDescForSlot_NoThrow(i) == pParentMT->GetMethodDescForSlot_NoThrow(i));
                continue;
            }
            MethodDesc* pMD = pMT->GetMethodDescForSlot(i);
            MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i);

            if (pMD == pParentMD)
                continue;

            if (!pMD->RequiresCovariantReturnTypeChecking() && !pParentMD->RequiresCovariantReturnTypeChecking())
                continue;

            // Skip validation for async variant methods, as they have different signatures by design
            // to support the async calling convention
            if (pMD->IsAsyncVariantMethod() || pParentMD->IsAsyncVariantMethod())
                continue;

            // Locate the MethodTable defining the pParentMD.
            MethodTable* pDefinitionParentMT = pParentMT;
            while (pDefinitionParentMT->GetCanonicalMethodTable() != pParentMD->GetMethodTable())
            {
                pDefinitionParentMT = pDefinitionParentMT->GetParentMethodTable();
            }

            SigTypeContext context1(pDefinitionParentMT->GetInstantiation(), pMD->GetMethodInstantiation());
            MetaSig methodSig1(pParentMD);
            TypeHandle hType1 = methodSig1.GetReturnProps().GetTypeHandleThrowing(pParentMD->GetModule(), &context1, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS);

            SigTypeContext context2(pMT->GetInstantiation(), pMD->GetMethodInstantiation());
            MetaSig methodSig2(pMD);
            TypeHandle hType2 = methodSig2.GetReturnProps().GetTypeHandleThrowing(pMD->GetModule(), &context2, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS);

            if (!IsCompatibleWith(hType1, hType2))
            {
                SString strAssemblyName;
                pMD->GetAssembly()->GetDisplayName(strAssemblyName);

                SString strInvalidTypeName;
                TypeString::AppendType(strInvalidTypeName, TypeHandle(pMD->GetMethodTable()));


Review comment (suggestion):
AsyncVariantMethods should be only overriding AsyncVariantMethods. It should be sufficient to check `pMD` only, and this check can be right after `MethodDesc* pMD = pMT->GetMethodDescForSlot(i);` to save us resolving `pParentMD`

@copilot 

Code after:
        return;

    // Step 1: Validate compatibility of return types on overriding methods
    if (pMT->GetClass()->HasCovariantOverride() && !pMT->GetModule()->SkipTypeValidation())
    {
        for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++)
        {
            if (pMT->GetRestoredSlot(i) == pParentMT->GetRestoredSlot(i))
            {
                // The real check is that the MethodDesc's must not match, but a simple VTable check will
                // work most of the time, and is far faster than the GetMethodDescForSlot method.
                _ASSERTE(pMT->GetMethodDescForSlot_NoThrow(i) == pParentMT->GetMethodDescForSlot_NoThrow(i));
                continue;
            }
            MethodDesc* pMD = pMT->GetMethodDescForSlot(i);

            // Skip validation for async variant methods, as they have different signatures by design
            // to support the async calling convention
            if (pMD->IsAsyncVariantMethod())
                continue;

            MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i);

            if (pMD == pParentMD)
                continue;

            if (!pMD->RequiresCovariantReturnTypeChecking() && !pParentMD->RequiresCovariantReturnTypeChecking())
                continue;

            // Locate the MethodTable defining the pParentMD.
            MethodTable* pDefinitionParentMT = pParentMT;
            while (pDefinitionParentMT->GetCanonicalMethodTable() != pParentMD->GetMethodTable())
            {
                pDefinitionParentMT = pDefinitionParentMT->GetParentMethodTable();
            }

            SigTypeContext context1(pDefinitionParentMT->GetInstantiation(), pMD->GetMethodInstantiation());
            MetaSig methodSig1(pParentMD);
            TypeHandle hType1 = methodSig1.GetReturnProps().GetTypeHandleThrowing(pParentMD->GetModule(), &context1, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS);

            SigTypeContext context2(pMT->GetInstantiation(), pMD->GetMethodInstantiation());
            MetaSig methodSig2(pMD);
            TypeHandle hType2 = methodSig2.GetReturnProps().GetTypeHandleThrowing(pMD->GetModule(), &context2, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS);

            if (!IsCompatibleWith(hType1, hType2))
            {
                SString strAssemblyName;
                pMD->GetAssembly()->GetDisplayName(strAssemblyName);

                SString strInvalidTypeName;
                TypeString::AppendType(strInvalidTypeName, TypeHandle(pMD->GetMethodTable()));