Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/coreclr/tools/Common/Compiler/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,9 @@ public static MethodDesc TryResolveConstraintMethodApprox(this TypeDesc constrai
}
}

Debug.Assert(potentialMatchingInterfaces != 0);
Debug.Assert(potentialMatchingInterfaces != 0
// We didn't consider default-implemented methods above and we're fine taking the !(potentialMatchingInterfaces > 1) path below.
|| (isStaticVirtualMethod && !interfaceMethod.IsAbstract));

if (potentialMatchingInterfaces > 1)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -936,26 +936,36 @@ public override DefaultInterfaceMethodResolution ResolveVariantInterfaceMethodTo

public static DefaultInterfaceMethodResolution ResolveVariantInterfaceMethodToDefaultImplementationOnType(MethodDesc interfaceMethod, MetadataType currentType, out MethodDesc impl)
{
MetadataType interfaceType = (MetadataType)interfaceMethod.OwningType;
bool foundInterface = IsInterfaceImplementedOnType(currentType, interfaceType);
DefaultInterfaceMethodResolution resolution = ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, currentType, out impl);
if (resolution != DefaultInterfaceMethodResolution.None)
return resolution;

if (foundInterface)
DefType[] consideredInterfaces;
if (!currentType.IsInterface)
{
DefaultInterfaceMethodResolution resolution = ResolveInterfaceMethodToDefaultImplementationOnType(interfaceMethod, currentType, out impl);
if (resolution != DefaultInterfaceMethodResolution.None)
return resolution;
// If this is not an interface, only things on the interface list could provide
// default implementations.
consideredInterfaces = currentType.RuntimeInterfaces;
}
else
{
// If we're asking about an interface, include the interface in the list.
consideredInterfaces = new DefType[currentType.RuntimeInterfaces.Length + 1];
consideredInterfaces[0] = currentType.IsGenericDefinition ? (DefType)currentType.InstantiateAsOpen() : currentType;
Array.Copy(currentType.RuntimeInterfaces, 0, consideredInterfaces, 1, currentType.RuntimeInterfaces.Length);
}

MetadataType interfaceType = (MetadataType)interfaceMethod.OwningType;
MethodDesc interfaceMethodDefinition = interfaceMethod.GetMethodDefinition();
foreach (TypeDesc iface in currentType.RuntimeInterfaces)
foreach (TypeDesc iface in consideredInterfaces)
{
if (iface.HasSameTypeDefinition(interfaceType) && iface.CanCastTo(interfaceType))
{
MethodDesc variantMethod = iface.FindMethodOnTypeWithMatchingTypicalMethod(interfaceMethodDefinition);
Debug.Assert(variantMethod != null);
if (interfaceMethod != interfaceMethodDefinition)
variantMethod = variantMethod.MakeInstantiatedMethod(interfaceMethod.Instantiation);
DefaultInterfaceMethodResolution resolution = ResolveInterfaceMethodToDefaultImplementationOnType(variantMethod, currentType, out impl);
resolution = ResolveInterfaceMethodToDefaultImplementationOnType(variantMethod, currentType, out impl);
if (resolution != DefaultInterfaceMethodResolution.None)
return resolution;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Xunit;

namespace SimpleStaticVirtual
{
public class Tests
{
[Fact]
public static void TestEntryPoint()
{
Assert.Equal(nameof(IGetter), Get<IGetter>());
Assert.Equal("Object", GetVariant<IGetter<object>, string>());
}

static string Get<T>() where T : IGetter => T.Get();
static string GetVariant<T, U>() where T : IGetter<U> => T.Get();
}

interface IGetter
{
static virtual string Get() => nameof(IGetter);
}

interface IGetter<in T>
{
static virtual string Get() => typeof(T).Name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DebugType>Full</DebugType>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileName).cs" />
</ItemGroup>
</Project>
Loading