Skip to content

Commit b99bfd7

Browse files
MichalStrehovskytannergooding
authored andcommitted
Add default method support to virtual statics (#69783)
Corresponds to #64717 that I somehow missed, despite commenting on it. We still don't allow interfaces to implement methods of other interfaces. The CLR VM doesn't allow either.
1 parent 3a46868 commit b99bfd7

File tree

5 files changed

+19
-4
lines changed

5 files changed

+19
-4
lines changed

src/coreclr/tools/Common/Compiler/TypeExtensions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,16 @@ public static MethodDesc TryResolveConstraintMethodApprox(this TypeDesc constrai
562562
method = null;
563563
}
564564

565+
// Default implementation logic, which only kicks in for default implementations when looking up on an exact interface target
566+
if (isStaticVirtualMethod && method == null && !genInterfaceMethod.IsAbstract && !constrainedType.IsCanonicalSubtype(CanonicalFormKind.Any))
567+
{
568+
MethodDesc exactInterfaceMethod = genInterfaceMethod;
569+
if (genInterfaceMethod.OwningType != interfaceType)
570+
exactInterfaceMethod = context.GetMethodForInstantiatedType(
571+
genInterfaceMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceType);
572+
method = exactInterfaceMethod;
573+
}
574+
565575
if (method == null)
566576
{
567577
// Fall back to VSD

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,10 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo
14381438
if (instantiatedConstrainedMethod.Signature.IsStatic)
14391439
{
14401440
implMethod = instantiatedConstraintType.GetClosestDefType().ResolveVariantInterfaceMethodToStaticVirtualMethodOnType(instantiatedConstrainedMethod);
1441+
if (implMethod == null && !instantiatedConstrainedMethod.IsAbstract)
1442+
{
1443+
implMethod = instantiatedConstrainedMethod;
1444+
}
14411445
}
14421446
else
14431447
{
@@ -1451,7 +1455,6 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo
14511455

14521456
// AOT use of this generic lookup is restricted to finding methods on valuetypes (runtime usage of this slot in universal generics is more flexible)
14531457
Debug.Assert(instantiatedConstraintType.IsValueType || (instantiatedConstrainedMethod.OwningType.IsInterface && instantiatedConstrainedMethod.Signature.IsStatic));
1454-
Debug.Assert(!instantiatedConstraintType.IsValueType || implMethod.OwningType == instantiatedConstraintType);
14551458

14561459
if (implMethod.Signature.IsStatic)
14571460
{

src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ private void ImportCall(ILOpcode opcode, int token)
424424

425425
methodAfterConstraintResolution = directMethod;
426426

427-
Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface);
427+
Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface
428+
|| methodAfterConstraintResolution.Signature.IsStatic);
428429
resolvedConstraint = true;
429430

430431
exactType = constrained;

src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,8 @@ private void getCallInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_RESO
12031203

12041204
methodAfterConstraintResolution = directMethod;
12051205

1206-
Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface);
1206+
Debug.Assert(!methodAfterConstraintResolution.OwningType.IsInterface
1207+
|| methodAfterConstraintResolution.Signature.IsStatic);
12071208
resolvedConstraint = true;
12081209
pResult->thisTransform = CORINFO_THIS_TRANSFORM.CORINFO_NO_THIS_TRANSFORM;
12091210

src/coreclr/vm/methodtable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8067,7 +8067,7 @@ MethodTable::ResolveVirtualStaticMethod(MethodTable* pInterfaceType, MethodDesc*
80678067
}
80688068
}
80698069

8070-
// Default implementation logic, which only kicks in for default implementations when lookin up on an exact interface target
8070+
// Default implementation logic, which only kicks in for default implementations when looking up on an exact interface target
80718071
if (!pInterfaceMD->IsAbstract() && !(this == g_pCanonMethodTableClass) && !IsSharedByGenericInstantiations())
80728072
{
80738073
return pInterfaceMD->FindOrCreateAssociatedMethodDesc(pInterfaceMD, pInterfaceType, FALSE, pInterfaceMD->GetMethodInstantiation(), FALSE);

0 commit comments

Comments
 (0)