|
35 | 35 | using System.Diagnostics;
|
36 | 36 | using System.Diagnostics.CodeAnalysis;
|
37 | 37 | using System.Linq;
|
38 |
| -using System.Reflection.Metadata.Ecma335; |
39 | 38 | using System.Reflection.Runtime.TypeParsing;
|
40 |
| -using System.Runtime.CompilerServices; |
41 | 39 | using System.Text.RegularExpressions;
|
42 | 40 | using ILCompiler.DependencyAnalysisFramework;
|
43 | 41 | using ILLink.Shared;
|
@@ -718,33 +716,25 @@ void MarkMethodIfNeededByBaseMethod (MethodDefinition method, MessageOrigin orig
|
718 | 716 | /// or if any marked interface implementations on <paramref name="type"/> are interfaces that implement <paramref name="interfaceType"/> and that interface implementation is marked
|
719 | 717 | /// </summary>
|
720 | 718 | bool IsInterfaceImplementationMarkedRecursively (TypeDefinition type, TypeDefinition interfaceType)
|
| 719 | + => IsInterfaceImplementationMarkedRecursively (type, interfaceType, Context); |
| 720 | + |
| 721 | + /// <summary> |
| 722 | + /// Returns true if <paramref name="type"/> implements <paramref name="interfaceType"/> and the interface implementation is marked, |
| 723 | + /// or if any marked interface implementations on <paramref name="type"/> are interfaces that implement <paramref name="interfaceType"/> and that interface implementation is marked |
| 724 | + /// </summary> |
| 725 | + internal static bool IsInterfaceImplementationMarkedRecursively (TypeDefinition type, TypeDefinition interfaceType, LinkContext context) |
721 | 726 | {
|
722 | 727 | if (type.HasInterfaces) {
|
723 | 728 | foreach (var intf in type.Interfaces) {
|
724 |
| - TypeDefinition? resolvedInterface = Context.Resolve (intf.InterfaceType); |
| 729 | + TypeDefinition? resolvedInterface = context.Resolve (intf.InterfaceType); |
725 | 730 | if (resolvedInterface == null)
|
726 | 731 | continue;
|
727 |
| - |
728 |
| - if (Annotations.IsMarked (intf) && RequiresInterfaceRecursively (resolvedInterface, interfaceType)) |
729 |
| - return true; |
730 |
| - } |
731 |
| - } |
732 |
| - |
733 |
| - return false; |
734 |
| - } |
735 |
| - |
736 |
| - bool RequiresInterfaceRecursively (TypeDefinition typeToExamine, TypeDefinition interfaceType) |
737 |
| - { |
738 |
| - if (typeToExamine == interfaceType) |
739 |
| - return true; |
740 |
| - |
741 |
| - if (typeToExamine.HasInterfaces) { |
742 |
| - foreach (var iface in typeToExamine.Interfaces) { |
743 |
| - var resolved = Context.TryResolve (iface.InterfaceType); |
744 |
| - if (resolved == null) |
| 732 | + if (!context.Annotations.IsMarked (intf)) |
745 | 733 | continue;
|
746 | 734 |
|
747 |
| - if (RequiresInterfaceRecursively (resolved, interfaceType)) |
| 735 | + if (resolvedInterface == interfaceType) |
| 736 | + return true; |
| 737 | + if (IsInterfaceImplementationMarkedRecursively (resolvedInterface, interfaceType, context)) |
748 | 738 | return true;
|
749 | 739 | }
|
750 | 740 | }
|
@@ -3197,8 +3187,12 @@ protected virtual void ProcessMethod (MethodDefinition method, in DependencyInfo
|
3197 | 3187 | Context.Resolve (@base) is MethodDefinition baseDefinition
|
3198 | 3188 | && baseDefinition.DeclaringType.IsInterface && baseDefinition.IsStatic && method.IsStatic)
|
3199 | 3189 | continue;
|
| 3190 | + // Instance methods can have overrides on public implementation methods in IL, but C# will usually only have them for private explicit interface implementations. |
| 3191 | + // It is valid IL for a public method to override an interface method and only be called directly. In this case it would be safe to skip marking the .override method. |
| 3192 | + // However, in most cases, the C# compiler will only generate .override for instance methods when it's a private explicit interface implementations which can only be called through the interface. |
| 3193 | + // We can just take a short cut and mark all the overrides on instance methods. We shouldn't miss out on size savings for code generated by Roslyn. |
3200 | 3194 | MarkMethod (@base, new DependencyInfo (DependencyKind.MethodImplOverride, method), methodOrigin);
|
3201 |
| - MarkExplicitInterfaceImplementation (method, @base); |
| 3195 | + MarkRuntimeInterfaceImplementation (method, @base); |
3202 | 3196 | }
|
3203 | 3197 | }
|
3204 | 3198 |
|
@@ -3314,22 +3308,21 @@ protected virtual void MarkRequirementsForInstantiatedTypes (TypeDefinition type
|
3314 | 3308 | DoAdditionalInstantiatedTypeProcessing (type);
|
3315 | 3309 | }
|
3316 | 3310 |
|
3317 |
| - void MarkExplicitInterfaceImplementation (MethodDefinition method, MethodReference ov) |
| 3311 | + void MarkRuntimeInterfaceImplementation (MethodDefinition method, MethodReference ov) |
3318 | 3312 | {
|
3319 | 3313 | if (Context.Resolve (ov) is not MethodDefinition resolvedOverride)
|
3320 | 3314 | return;
|
| 3315 | + if (!resolvedOverride.DeclaringType.IsInterface) |
| 3316 | + return; |
| 3317 | + var interfaceToBeImplemented = ov.DeclaringType; |
3321 | 3318 |
|
3322 |
| - if (resolvedOverride.DeclaringType.IsInterface) { |
3323 |
| - foreach (var ifaceImpl in method.DeclaringType.Interfaces) { |
3324 |
| - var resolvedInterfaceType = Context.Resolve (ifaceImpl.InterfaceType); |
3325 |
| - if (resolvedInterfaceType == null) { |
3326 |
| - continue; |
3327 |
| - } |
3328 |
| - |
3329 |
| - if (resolvedInterfaceType == resolvedOverride.DeclaringType) { |
3330 |
| - MarkInterfaceImplementation (ifaceImpl, new MessageOrigin (method.DeclaringType)); |
3331 |
| - return; |
3332 |
| - } |
| 3319 | + var ifaces = Annotations.GetRecursiveInterfaces (method.DeclaringType); |
| 3320 | + if (ifaces is null) |
| 3321 | + return; |
| 3322 | + foreach (var iface in ifaces) { |
| 3323 | + if (TypeReferenceEqualityComparer.AreEqual (iface.InterfaceType, interfaceToBeImplemented, Context)) { |
| 3324 | + MarkInterfaceImplementationList (iface.ImplementationChain, new MessageOrigin (method.DeclaringType)); |
| 3325 | + return; |
3333 | 3326 | }
|
3334 | 3327 | }
|
3335 | 3328 | }
|
|
0 commit comments