Skip to content

Commit

Permalink
Add callvirt support for implicit interface method implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
puff committed Oct 6, 2023
1 parent ac3fb60 commit 231ec22
Showing 1 changed file with 35 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ public class CallVirtHandler : CallHandlerBase
var declaringType = baseMethod.DeclaringType!;
while (type is not null && !Comparer.Equals(type, declaringType))
{
// Prioritize explicit interface implementations.
// Prioritize interface implementations.
if (declaringType.IsInterface)
implementation = TryFindExplicitInterfaceImplementationInType(type, baseMethod);
implementation = TryFindExplicitInterfaceImplementationInType(type, baseMethod)
?? TryFindImplicitInterfaceImplementationInType(type, baseMethod);

// Try find any implicit implementations.
// Try to find other implicit implementations.
implementation ??= TryFindImplicitImplementationInType(type, baseMethod);

if (implementation is not null)
Expand Down Expand Up @@ -97,6 +98,37 @@ public class CallVirtHandler : CallHandlerBase
return null;
}

private static MethodDefinition? TryFindImplicitInterfaceImplementationInType(TypeDefinition type, MethodDefinition baseMethod)
{
// Find the correct interface implementation and instantiate any generics.
MethodSignature? baseMethodSig = null;
foreach (var interfaceImpl in type.Interfaces)
{
if (Comparer.Equals(interfaceImpl.Interface?.ToTypeSignature().GetUnderlyingTypeDefOrRef(), baseMethod.DeclaringType))
{
baseMethodSig = baseMethod.Signature?.InstantiateGenericTypes(GenericContext.FromType(interfaceImpl.Interface!));
break;
}
}
if (baseMethodSig is null)
return null;

// Find implemented method in type.
for (int i = 0; i < type.Methods.Count; i++)
{
var method = type.Methods[i];
// Only public virtual instance methods can implicity implement interface methods. (ECMA-335, 6th edition, II.12.2)
if (method.IsPublic
&& method.IsVirtual
&& !method.IsStatic
&& method.Name == baseMethod.Name
&& Comparer.Equals(method.Signature, baseMethodSig))
return method;
}

return null;
}

private static MethodDefinition? TryFindExplicitInterfaceImplementationInType(TypeDefinition type, MethodDefinition baseMethod)
{
for (int i = 0; i < type.MethodImplementations.Count; i++)
Expand Down

0 comments on commit 231ec22

Please sign in to comment.