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

Code before:
                    {
                        break;
                    }

                    pCheckMT = pCheckMT->GetParentMethodTable();
                }

                if (pCheckMT == nullptr)
                {
                    pImplMethodRuntime = NULL;
                }
                else if (IsMdFinal(pDeclMethod->GetAttrs()))
                {
                    pImplMethodRuntime = pDeclMethod;
                }
                else
                {
                    _ASSERTE(slot < pBaseMT->GetNumVirtuals());
                    pImplMethodRuntime = thImpl.GetMethodTable()->GetMethodDescForSlot(slot);
                }
            }

            // Strip off method instantiation for comparison if the method is generic virtual.
            if (pImplMethodCompiler != NULL && pDeclMethod->HasMethodInstantiation())
            {
                pImplMethodCompiler = pImplMethodCompiler->StripMethodInstantiation();
            }

            if (pImplMethodRuntime != pImplMethodCompiler)
            {
                if (kind == READYTORUN_FIXUP_Check_VirtualFunctionOverride)
                {
                    return FALSE;
                }
                else
                {
                    // Verification failures are failfast events
                    DefineFullyQualifiedNameForClass();
                    SString methodNameDecl;
                    SString methodNameImplRuntime(W("(NULL)"));
                    SString methodNameImplCompiler(W("(NULL)"));

                    pDeclMethod->GetFullMethodInfo(methodNameDecl);

                    if (pImplMethodRuntime != NULL)
                    {
                        methodNameImplRuntime.Clear();
                        pImplMethodRuntime->GetFullMethodInfo(methodNameImplRuntime);
                    }

                    if (pImplMethodCompiler != NULL)

Review comment (bug):
When the decl method is final (line 14290-14292), `pImplMethodRuntime` is set to `pDeclMethod`, which may have a method instantiation. In this case, we should also strip the method instantiation from `pImplMethodRuntime` before comparison, not just from `pImplMethodCompiler`. The current code only strips from `pImplMethodCompiler` (line 14304), but if `pImplMethodRuntime == pDeclMethod` and `pDeclMethod` has an instantiation, the comparison at line 14307 may incorrectly detect a mismatch.
```suggestion
            if (pDeclMethod->HasMethodInstantiation())
            {
                if (pImplMethodRuntime != NULL)
                {
                    pImplMethodRuntime = pImplMethodRuntime->StripMethodInstantiation();
                }

                if (pImplMethodCompiler != NULL)
                {
                    pImplMethodCompiler = pImplMethodCompiler->StripMethodInstantiation();
                }
```

Code after:
                    {
                        break;
                    }

                    pCheckMT = pCheckMT->GetParentMethodTable();
                }

                if (pCheckMT == nullptr)
                {
                    pImplMethodRuntime = NULL;
                }
                else if (IsMdFinal(pDeclMethod->GetAttrs()))
                {
                    pImplMethodRuntime = pDeclMethod;
                }
                else
                {
                    _ASSERTE(slot < pBaseMT->GetNumVirtuals());
                    pImplMethodRuntime = thImpl.GetMethodTable()->GetMethodDescForSlot(slot);
                }
            }

            // Strip off method instantiation for comparison if the method is generic virtual.
            if (pDeclMethod->HasMethodInstantiation())
            {
                if (pImplMethodRuntime != NULL)
                {
                    pImplMethodRuntime = pImplMethodRuntime->StripMethodInstantiation();
                }

                if (pImplMethodCompiler != NULL)
                {
                    pImplMethodCompiler = pImplMethodCompiler->StripMethodInstantiation();
                }
            }

            if (pImplMethodRuntime != pImplMethodCompiler)
            {
                if (kind == READYTORUN_FIXUP_Check_VirtualFunctionOverride)
                {
                    return FALSE;
                }
                else
                {
                    // Verification failures are failfast events
                    DefineFullyQualifiedNameForClass();
                    SString methodNameDecl;
                    SString methodNameImplRuntime(W("(NULL)"));
                    SString methodNameImplCompiler(W("(NULL)"));

                    pDeclMethod->GetFullMethodInfo(methodNameDecl);