From 69426524a6fcc4e2c51135ec011824a109491570 Mon Sep 17 00:00:00 2001 From: David Wrighton Date: Tue, 11 May 2021 14:46:14 -0700 Subject: [PATCH] Add support for interface variance - Fix incorrect details in interface variance test - Add loop over actually implemented interfaces to try and find possible matches in a way which matches the behavior of normal interface variance matching --- src/coreclr/vm/methodtable.cpp | 33 +++++++++++++++++-- .../InterfaceVariance/InterfaceVariance.il | 15 +++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 9084c3fe5c20eb..a4020a875afb84 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -9208,6 +9208,37 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc* { return pMD; } + + if (pInterfaceType->HasVariance()) + { + // Variant interface dispatch + MethodTable::InterfaceMapIterator it = IterateInterfaceMap(); + while (it.Next()) + { + if (it.GetInterface() == pInterfaceType) + { + // This is the variant interface check logic, skip the + continue; + } + + if (!it.GetInterface()->HasSameTypeDefAs(pInterfaceType)) + { + // Variance matches require a typedef match + continue; + } + + if (it.GetInterface()->CanCastTo(pInterfaceType, NULL)) + { + // Variant matching interface found + // Attempt to resolve on variance matched interface + pMD = pMT->TryResolveVirtualStaticMethodOnThisType(it.GetInterface(), pInterfaceMD); + if (pMD != nullptr) + { + return pMD; + } + } + } + } } } } @@ -9238,8 +9269,6 @@ MethodTable::TryResolveVirtualStaticMethodOnThisType(MethodTable* pInterfaceType // This gets the count out of the metadata interface. uint32_t dwNumberMethodImpls = hEnumMethodImpl.EnumMethodImplGetCount(); - // TODO: support type-equivalent interface type matches and variant interface scenarios - // Iterate through each MethodImpl declared on this class for (uint32_t i = 0; i < dwNumberMethodImpls; i++) { diff --git a/src/tests/Loader/classloader/StaticVirtualMethods/InterfaceVariance/InterfaceVariance.il b/src/tests/Loader/classloader/StaticVirtualMethods/InterfaceVariance/InterfaceVariance.il index 88cc8638c5da48..63eeb79f937ab9 100644 --- a/src/tests/Loader/classloader/StaticVirtualMethods/InterfaceVariance/InterfaceVariance.il +++ b/src/tests/Loader/classloader/StaticVirtualMethods/InterfaceVariance/InterfaceVariance.il @@ -12,7 +12,8 @@ .method public newslot virtual abstract static int32 Method() cil managed noinlining { } // end of method Method -} // end of class InterfaceScenario1 +} // end of class InterfaceScenario1`1 + .class interface public abstract auto ansi InterfaceScenario2`1<- T> { .method public newslot virtual abstract static int32 Method() cil managed noinlining @@ -43,7 +44,7 @@ .class public auto ansi BaseScenario2 extends [System.Runtime]System.Object - implements class InterfaceScenario1`1, class InterfaceScenario1`1 + implements class InterfaceScenario2`1, class InterfaceScenario2`1 { // NOTE: The order of the methods in this .il file is important as it controls the MethodImpl record creation order .method public static int32 Method() cil managed noinlining @@ -77,18 +78,18 @@ { .method public static int32 Method() cil managed noinlining { - .override method int32 class InterfaceScenario2`1::Method() + .override method int32 class InterfaceScenario2`1::Method() ldc.i4 6 ret } // end of method Method .method public static int32 Method2() cil managed noinlining { - .override method int32 class InterfaceScenario2`1::Method2() + .override method int32 class InterfaceScenario2`1::Method2() ldc.i4 7 ret } // end of method Method -} // end of class DerivedScenario1 +} // end of class DerivedScenario2 .class public auto ansi TestEntrypoint @@ -106,7 +107,7 @@ ret } // end of method Test_Scenario1 - .method public static string Test_Scenario2_1) ImplType>() cil managed noinlining + .method public static string Test_Scenario2_1) ImplType>() cil managed noinlining { // Variant dispatch to method on base type .locals init (int32 V_1) @@ -118,7 +119,7 @@ ret } // end of method Test_Scenario1 - .method public static string Test_Scenario2_2) ImplType>() cil managed noinlining + .method public static string Test_Scenario2_2) ImplType>() cil managed noinlining { // Variant dispatch to method on base type .locals init (int32 V_1)