Skip to content

Commit

Permalink
Look on base types and interfaces for interfaceImpl
Browse files Browse the repository at this point in the history
  • Loading branch information
jtschuster committed Feb 23, 2024
1 parent 9addd27 commit 81ebc93
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
37 changes: 37 additions & 0 deletions src/tools/illink/src/linker/Linker/InterfaceImplementor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Mono.Cecil;

Expand All @@ -27,5 +30,39 @@ public InterfaceImplementor (TypeDefinition implementor, InterfaceImplementation
InterfaceImplementation = interfaceImplementation;
InterfaceType = interfaceType;
}

public static InterfaceImplementor Create(TypeDefinition implementor, TypeDefinition interfaceType, IMetadataResolver resolver)
{
foreach(InterfaceImplementation iface in implementor.Interfaces) {
if (resolver.Resolve(iface.InterfaceType) == interfaceType) {
return new InterfaceImplementor(implementor, iface, interfaceType);
}
}
var baseTypeRef = implementor.BaseType;
while (baseTypeRef is not null) {
var baseType = resolver.Resolve (baseTypeRef);
foreach(InterfaceImplementation iface in baseType.Interfaces) {
if (resolver.Resolve(iface.InterfaceType) == interfaceType) {
return new InterfaceImplementor(implementor, iface, interfaceType);
}
}
baseTypeRef = baseType.BaseType;
}

Queue<TypeDefinition> ifacesToCheck = new ();
ifacesToCheck.Enqueue(implementor);
while (ifacesToCheck.Count > 0) {
var myFace = ifacesToCheck.Dequeue ();

foreach(InterfaceImplementation ifaceImpl in myFace.Interfaces) {
var iface = resolver.Resolve (ifaceImpl.InterfaceType);
if (iface == interfaceType) {
return new InterfaceImplementor(implementor, ifaceImpl, interfaceType);
}
ifacesToCheck.Enqueue (iface);
}
}
throw new InvalidOperationException ($"Type '{implementor.FullName}' does not implement interface '{interfaceType.FullName}' directly or through any base types or interfaces");
}
}
}
16 changes: 5 additions & 11 deletions src/tools/illink/src/linker/Linker/TypeMapInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Mono.Cecil;

namespace Mono.Linker
Expand Down Expand Up @@ -222,21 +224,13 @@ void MapOverrides (MethodDefinition method)
MethodDefinition? baseMethod = context.TryResolve (baseMethodRef);
if (baseMethod == null)
continue;
if (baseMethod.DeclaringType.IsInterface)
if (!baseMethod.DeclaringType.IsInterface)
{
// Find the matching interface implementation if the base is an interface method
foreach (var iface in method.DeclaringType.Interfaces)
{
if (context.TryResolve (iface.InterfaceType) == baseMethod.DeclaringType)
{
AnnotateMethods (baseMethod, method, new InterfaceImplementor (method.DeclaringType, iface, baseMethod.DeclaringType));
break;
}
}
AnnotateMethods (baseMethod, method);
}
else
{
AnnotateMethods (baseMethod, method);
AnnotateMethods (baseMethod, method, InterfaceImplementor.Create (method.DeclaringType, baseMethod.DeclaringType, context));
}
}
}
Expand Down

0 comments on commit 81ebc93

Please sign in to comment.