Skip to content

Commit

Permalink
Merge pull request #134 from puff/fix/callvirt-implicit-interface-met…
Browse files Browse the repository at this point in the history
…hod-impls

Add callvirt support for implicit interface method implementations
  • Loading branch information
Washi1337 committed Nov 19, 2023
2 parents ac3fb60 + 231ec22 commit bb175d0
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 bb175d0

Please sign in to comment.