Skip to content

Commit

Permalink
[Release/5.0] Fix covariant returns when overriding method of non-par…
Browse files Browse the repository at this point in the history
…ent ancestor (#47937)

There is a problem in the
ClassLoader::ValidateMethodsWithCovariantReturnTypes that results in
failed verification of valid override in case the return type of the
method being overriden is generic in canonical form and it is defined
in an ancestor class that is not the parent.

The problem is that we attempt to use instantiation of the parent class
instead of the ancestor class that contains definition of the method
being overriden.

This change fixes it by locating the proper ancestor MethodTable and
using it.
  • Loading branch information
janvorli authored Feb 11, 2021
1 parent bf52923 commit 9f4253b
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/coreclr/src/vm/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,12 @@ void ClassLoader::ValidateMethodsWithCovariantReturnTypes(MethodTable* pMT)
if (!pMD->RequiresCovariantReturnTypeChecking() && !pParentMD->RequiresCovariantReturnTypeChecking())
continue;

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

SigTypeContext context1(pParentMT->GetInstantiation(), pMD->GetMethodInstantiation());
MetaSig methodSig1(pParentMD);
TypeHandle hType1 = methodSig1.GetReturnProps().GetTypeHandleThrowing(pParentMD->GetModule(), &context1, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS);
Expand Down
39 changes: 39 additions & 0 deletions src/tests/Regressions/coreclr/GitHub_45053/test45053.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;

public abstract class T<TR>
{
public abstract TR GetA();
}

// This abstract causes the error - not overriding the base method cause the runtime to crash
public abstract class TA : T<A> { }

// This works
// public abstract class TA : T<A>
// {
// // Overriding in between fixes the problem
// public override A GetA() => new ();
// }

// Overriden here, in the grandson
public class TB : TA
{
public override B GetA() => new ();
}
public class A { }

public class B : A { }

class Program
{
static int Main()
{
System.Console.WriteLine((new TB() as T<A>).GetA().GetType().FullName);

return 100;
}
}
10 changes: 10 additions & 0 deletions src/tests/Regressions/coreclr/GitHub_45053/test45053.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<CLRTestKind>BuildAndRun</CLRTestKind>
<CLRTestPriority>1</CLRTestPriority>
</PropertyGroup>
<ItemGroup>
<Compile Include="test45053.cs" />
</ItemGroup>
</Project>

0 comments on commit 9f4253b

Please sign in to comment.