Skip to content

Commit

Permalink
Use method signature comparisons to disambiguate during explicit inte…
Browse files Browse the repository at this point in the history
…rface inference (#350)
  • Loading branch information
ds5678 authored Oct 25, 2024
1 parent 03b6607 commit 02545f5
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -562,9 +562,6 @@ private static void InferExplicitInterfaceImplementations(TypeDefinition type, R
if (Utf8String.IsNullOrEmpty(method.Name))
continue;

// Explicit interface implementation
// Note: This does not handle all cases.
// Specifically, it does not handle the case where the interface has multiple methods with the same name.
var periodLastIndex = method.Name.LastIndexOf('.');
if (periodLastIndex < 0 || !method.IsPrivate || !method.IsVirtual || !method.IsFinal || !method.IsNewSlot)
{
Expand All @@ -578,21 +575,46 @@ private static void InferExplicitInterfaceImplementations(TypeDefinition type, R
: [];
var interfaceType = AsmResolverUtils.TryLookupTypeSignatureByName(interfaceName, genericParameterNames);

if (interfaceType is null)
continue;

var ambiguous = false;
IMethodDefOrRef? interfaceMethod = null;
var underlyingInterface = interfaceType?.GetUnderlyingTypeDefOrRef();
var underlyingInterface = interfaceType.GetUnderlyingTypeDefOrRef();
foreach (var interfaceMethodDef in (underlyingInterface as TypeDefinition)?.Methods ?? [])
{
if (interfaceMethodDef.Name != methodName)
continue;

if (interfaceMethod is not null)
{
// Ambiguity. Checking the method signature would be required to disambiguate.
// Ambiguity. Checking the method signature will be required to disambiguate.
interfaceMethod = null;
ambiguous = true;
break;
}

interfaceMethod = new MemberReference(interfaceType?.ToTypeDefOrRef(), interfaceMethodDef.Name, interfaceMethodDef.Signature);
// This has the implicit assumption that the method signatures match.
// This is a reasonable assumption because there's no other method to match (with this name).
interfaceMethod = new MemberReference(interfaceType.ToTypeDefOrRef(), interfaceMethodDef.Name, interfaceMethodDef.Signature);
}

if (ambiguous)
{
// Ambiguities are very rare, so we only bother signature checking when we have to.

var genericContext = GenericContext.FromType(interfaceType);
foreach (var interfaceMethodDef in (underlyingInterface as TypeDefinition)?.Methods ?? [])
{
if (interfaceMethodDef.Name != methodName)
continue;

if (SignatureComparer.Default.Equals(method.Signature, interfaceMethodDef.Signature?.InstantiateGenericTypes(genericContext)))
{
interfaceMethod = new MemberReference(interfaceType?.ToTypeDefOrRef(), interfaceMethodDef.Name, interfaceMethodDef.Signature);
break;
}
}
}

if (interfaceMethod != null)
Expand All @@ -601,5 +623,4 @@ private static void InferExplicitInterfaceImplementations(TypeDefinition type, R
}
}
}

}

0 comments on commit 02545f5

Please sign in to comment.