Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJackson Schuster <36744439+jtschuster@users.noreply.github.com>2022-08-11 23:37:57 +0300
committerGitHub <noreply@github.com>2022-08-11 23:37:57 +0300
commite45a9356e779e457edf335ea9c34e6c9c49330f6 (patch)
treef22dc02f9bd5c9a720cad3ddd7c78ee8222a5cf8
parent6e8e139a484f74c524c821c7a4a08287d77257a4 (diff)
Process static interface methods as virtual methods (#2926)
Static methods implementing static interface methods are not marked as virtual and were not checked for matching RUC and DAM annotations. This change adds all base methods to the _virtual_methods list to be checked for matching DAM and RUC annotations. This may cause extra/unnecessary warnings for mismatched annotations even a method is removed by the linker.
-rw-r--r--src/linker/Linker.Steps/MarkStep.cs10
-rw-r--r--src/linker/Linker/Annotations.cs18
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/StaticInterfaceMethods.cs6
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/Library.cs66
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs215
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs89
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs43
7 files changed, 433 insertions, 14 deletions
diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs
index e3bf8e8e2..ba5798d81 100644
--- a/src/linker/Linker.Steps/MarkStep.cs
+++ b/src/linker/Linker.Steps/MarkStep.cs
@@ -3166,6 +3166,7 @@ namespace Mono.Linker.Steps
}
MarkMethodSpecialCustomAttributes (method);
+
if (method.IsVirtual)
_virtual_methods.Add ((method, ScopeStack.CurrentScope));
@@ -3345,8 +3346,15 @@ namespace Mono.Linker.Steps
return;
foreach (MethodDefinition base_method in base_methods) {
- if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface)
+ // We should add all interface base methods to _virtual_methods for virtual override annotation validation
+ // Interfaces from preserved scope will be missed if we don't add them here
+ // This will produce warnings for all interface methods and virtual methods regardless of whether the interface, interface implementation, or interface method is kept or not.
+ if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface) {
+ // These are all virtual, no need to check IsVirtual before adding to list
+ _virtual_methods.Add ((base_method, ScopeStack.CurrentScope));
+ // _virtual_methods is a list and might have duplicates, but it's mostly just used for override validation, so it shouldn't matter
continue;
+ }
MarkMethod (base_method, new DependencyInfo (DependencyKind.BaseMethod, method), ScopeStack.CurrentScope.Origin);
MarkBaseMethods (base_method);
diff --git a/src/linker/Linker/Annotations.cs b/src/linker/Linker/Annotations.cs
index c5ceeabe9..227468101 100644
--- a/src/linker/Linker/Annotations.cs
+++ b/src/linker/Linker/Annotations.cs
@@ -608,7 +608,7 @@ namespace Mono.Linker
/// <summary>
/// Determines if a member requires unreferenced code (and thus any usage of such method should be warned about).
/// </summary>
- /// <remarks>Unlike <see cref="IsInRequiresUnreferencedCodeScope(MethodDefinition)"/> only static methods
+ /// <remarks>Unlike <see cref="IsInRequiresUnreferencedCodeScope(MethodDefinition)"/> only static methods
/// and .ctors are reported as requiring unreferenced code when the declaring type has RUC on it.</remarks>
internal bool DoesMemberRequireUnreferencedCode (IMemberDefinition member, [NotNullWhen (returnValue: true)] out RequiresUnreferencedCodeAttribute? attribute)
{
@@ -673,11 +673,27 @@ namespace Mono.Linker
return TryGetLinkerAttribute (field.DeclaringType, out attribute);
}
+ /// <Summary>
+ /// Adds a virtual method to the queue if it is annotated and must have matching annotations on its bases and overrides. It does not check if the method is marked before producing a warning about mismatched annotations.
+ /// </summary>
public void EnqueueVirtualMethod (MethodDefinition method)
{
if (!method.IsVirtual)
return;
+ // Implementations of static interface methods are not virtual and won't reach here
+ // We'll search through the implementations of static interface methods to find if any need to be enqueued
+ if (method.IsStatic) {
+ Debug.Assert (method.DeclaringType.IsInterface);
+ var overrides = GetOverrides (method);
+ if (overrides is not null) {
+ foreach (var @override in overrides) {
+ if (FlowAnnotations.RequiresVirtualMethodDataFlowAnalysis (@override.Override) || HasLinkerAttribute<RequiresUnreferencedCodeAttribute> (@override.Override))
+ VirtualMethodsWithAnnotationsToValidate.Add (@override.Override);
+ }
+ }
+ }
+
if (FlowAnnotations.RequiresVirtualMethodDataFlowAnalysis (method) || HasLinkerAttribute<RequiresUnreferencedCodeAttribute> (method))
VirtualMethodsWithAnnotationsToValidate.Add (method);
}
diff --git a/test/ILLink.RoslynAnalyzer.Tests/StaticInterfaceMethods.cs b/test/ILLink.RoslynAnalyzer.Tests/StaticInterfaceMethods.cs
index 13bc1d587..77e6421a9 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/StaticInterfaceMethods.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/StaticInterfaceMethods.cs
@@ -11,6 +11,12 @@ namespace ILLink.RoslynAnalyzer.Tests.Inheritance.Interfaces
protected override string TestSuiteName => "Inheritance.Interfaces.StaticInterfaceMethods";
[Fact]
+ public Task BaseProvidesInterfaceMethod ()
+ {
+ return RunTest (allowMissingWarnings: false);
+ }
+
+ [Fact]
public Task StaticAbstractInterfaceMethods ()
{
return RunTest (allowMissingWarnings: false);
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/Library.cs b/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/Library.cs
new file mode 100644
index 000000000..9e649d8b0
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/Dependencies/Library.cs
@@ -0,0 +1,66 @@
+// 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.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Mono.Linker.Tests.Cases.DataFlow.Dependencies
+{
+ public class Library
+ {
+ public interface IAnnotatedMethods
+ {
+ static abstract void GenericWithMethodsStatic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ();
+
+ static abstract void ParamWithMethodsStatic ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t);
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ static abstract Type ReturnWithMethodsStatic ();
+
+ void GenericWithMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ();
+
+ void ParamWithMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t);
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type ReturnWithMethods ();
+ }
+
+ public interface IUnannotatedMethods
+ {
+ static abstract void GenericStatic<T> ();
+
+ static abstract void ParamStatic (Type t);
+
+ static abstract Type ReturnStatic ();
+
+ void Generic<T> ();
+
+ void Param (Type t);
+
+ Type Return ();
+ }
+
+ public abstract class AnnotatedMethods
+ {
+ public abstract void GenericWithMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> ();
+
+ public abstract void ParamWithMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t);
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public abstract Type ReturnWithMethods ();
+ }
+
+ public abstract class UnannotatedMethods
+ {
+ public abstract void Generic<T> ();
+
+ public abstract void Param (Type t);
+
+ public abstract Type Return ();
+ }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs b/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs
index 51a561feb..ced70e08f 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/VirtualMethodHierarchyDataflowAnnotationValidation.cs
@@ -5,13 +5,17 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
+using Mono.Linker.Tests.Cases.DataFlow.Dependencies;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Helpers;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
namespace Mono.Linker.Tests.Cases.DataFlow
{
[SkipKeptItemsValidation]
[SandboxDependency ("Dependencies/TestSystemTypeBase.cs")]
+ [SetupCompileBefore ("skiplibrary.dll", new[] { "Dependencies/Library.cs" })]
+ [SetupLinkerAction ("skip", "skiplibrary")]
// Suppress warnings about accessing methods with annotations via reflection - the test below does that a LOT
// (The test accessed these methods through DynamicallyAccessedMembers annotations which is effectively the same reflection access)
@@ -43,6 +47,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
RequirePublicMethods (typeof (ITwoInterfacesImplementedByOneMethod_One));
RequirePublicMethods (typeof (ITwoInterfacesImplementedByOneMethod_Two));
RequirePublicMethods (typeof (ImplementationOfTwoInterfacesWithOneMethod));
+ StaticInterfaceMethods.Test ();
+ BaseInPreservedScope.Test ();
}
static void RequirePublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
@@ -623,22 +629,22 @@ namespace Mono.Linker.Tests.Cases.DataFlow
class ImplIDamOnAllMissing : IDamOnAll
{
- [ExpectedWarning ("IL2092", ProducedBy = ProducedBy.Analyzer)] // PR: https://github.com/dotnet/linker/pull/2926
- [ExpectedWarning ("IL2093", ProducedBy = ProducedBy.Analyzer)]
- [ExpectedWarning ("IL2095", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2092")]
+ [ExpectedWarning ("IL2093")]
+ [ExpectedWarning ("IL2095")]
public static Type AbstractMethod<T> (Type type) => null;
- [ExpectedWarning ("IL2092", ProducedBy = ProducedBy.Analyzer)] // PR: https://github.com/dotnet/linker/pull/2926
- [ExpectedWarning ("IL2093", ProducedBy = ProducedBy.Analyzer)]
- [ExpectedWarning ("IL2095", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2092")]
+ [ExpectedWarning ("IL2093")]
+ [ExpectedWarning ("IL2095")]
public static Type VirtualMethod<T> (Type type) => null;
}
class ImplIDamOnAllMismatch : IDamOnAll
{
- [ExpectedWarning ("IL2092", ProducedBy = ProducedBy.Analyzer)] // PR: https://github.com/dotnet/linker/pull/2926
- [ExpectedWarning ("IL2093", ProducedBy = ProducedBy.Analyzer)]
- [ExpectedWarning ("IL2095", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2092")]
+ [ExpectedWarning ("IL2093")]
+ [ExpectedWarning ("IL2095")]
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
public static Type AbstractMethod
<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
@@ -647,9 +653,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
Type type)
{ return null; }
- [ExpectedWarning ("IL2092", ProducedBy = ProducedBy.Analyzer)] // PR: https://github.com/dotnet/linker/pull/2926
- [ExpectedWarning ("IL2093", ProducedBy = ProducedBy.Analyzer)]
- [ExpectedWarning ("IL2095", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2092")]
+ [ExpectedWarning ("IL2093")]
+ [ExpectedWarning ("IL2095")]
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
public static Type VirtualMethod
<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
@@ -677,6 +683,191 @@ namespace Mono.Linker.Tests.Cases.DataFlow
Type type)
{ return null; }
}
+
+ interface IDamOnNone
+ {
+ static virtual Type VirtualMethod<T> (Type t) { return null; }
+ static abstract Type AbstractMethod<T> (Type t);
+ }
+
+ class ImplIDamOnNoneMatch : IDamOnNone
+ {
+ public static Type VirtualMethod<T> (Type t) { return null; }
+ public static Type AbstractMethod<T> (Type t) { return null; }
+ }
+
+ class ImplIDamOnNoneMismatch : IDamOnNone
+ {
+ [ExpectedWarning ("IL2092")]
+ [ExpectedWarning ("IL2093")]
+ [ExpectedWarning ("IL2095")]
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
+ public static Type AbstractMethod
+ <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ T> (
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
+ Type type)
+ { return null; }
+
+ [ExpectedWarning ("IL2092")]
+ [ExpectedWarning ("IL2093")]
+ [ExpectedWarning ("IL2095")]
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
+ public static Type VirtualMethod
+ <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ T> (
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
+ Type type)
+ { return null; }
+ }
+
+
+ public static void Test ()
+ {
+ typeof (ImplIDamOnAllMatch).RequiresPublicMethods ();
+ typeof (ImplIDamOnAllMismatch).RequiresPublicMethods ();
+ typeof (ImplIDamOnAllMissing).RequiresPublicMethods ();
+ typeof (IDamOnAll).RequiresPublicMethods ();
+ typeof (ImplIDamOnNoneMatch).RequiresPublicMethods ();
+ typeof (ImplIDamOnNoneMismatch).RequiresPublicMethods ();
+ typeof (IDamOnNone).RequiresPublicMethods ();
+
+ }
+ }
+
+ class BaseInPreservedScope
+ {
+ class ImplIAnnotatedMethodsMismatch : Library.IAnnotatedMethods
+ {
+ [ExpectedWarning ("IL2095")]
+ public static void GenericWithMethodsStatic<T> () { }
+
+ [ExpectedWarning ("IL2092")]
+ public static void ParamWithMethodsStatic (Type t) { }
+
+ [ExpectedWarning ("IL2093")]
+ public static Type ReturnWithMethodsStatic () => typeof (int);
+
+ [ExpectedWarning ("IL2095")]
+ public void GenericWithMethods<T> () { }
+
+ [ExpectedWarning ("IL2092")]
+ public void ParamWithMethods (Type t) { }
+
+ [ExpectedWarning ("IL2093")]
+ public Type ReturnWithMethods () => typeof (int);
+ }
+
+ class ImplIUnannotatedMethodsMismatch : Library.IUnannotatedMethods
+ {
+ [ExpectedWarning ("IL2095")]
+ public static void GenericStatic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { }
+
+ [ExpectedWarning ("IL2092")]
+ public static void ParamStatic ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
+
+ [ExpectedWarning ("IL2093")]
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public static Type ReturnStatic () => typeof (int);
+
+ [ExpectedWarning ("IL2095")]
+ public void Generic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { }
+
+ [ExpectedWarning ("IL2092")]
+ public void Param ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
+
+ [ExpectedWarning ("IL2093")]
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public Type Return () => typeof (int);
+ }
+
+ class DerivedFromUnannotatedMismatch : Library.UnannotatedMethods
+ {
+ [ExpectedWarning ("IL2095")]
+ public override void Generic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { }
+
+ [ExpectedWarning ("IL2092")]
+ public override void Param ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
+
+ [ExpectedWarning ("IL2093")]
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public override Type Return () => typeof (int);
+ }
+
+ class DerivedFromAnnotatedMismatch : Library.AnnotatedMethods
+ {
+ [ExpectedWarning ("IL2095")]
+ public override void GenericWithMethods<T> () { }
+
+ [ExpectedWarning ("IL2092")]
+ public override void ParamWithMethods (Type t) { }
+
+ [ExpectedWarning ("IL2093")]
+ public override Type ReturnWithMethods () => typeof (int);
+ }
+
+ class ImplIUnannotatedMethodsMatch : Library.IUnannotatedMethods
+ {
+ public static void GenericStatic<T> () { }
+
+ public static void ParamStatic (Type t) { }
+
+ public static Type ReturnStatic () => typeof (int);
+
+ public void Generic<T> () { }
+
+ public void Param (Type t) { }
+
+ public Type Return () => typeof (int);
+ }
+
+ class ImplIAnnotatedMethodsMatch : Library.IAnnotatedMethods
+ {
+ public static void GenericWithMethodsStatic<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { }
+
+ public static void ParamWithMethodsStatic ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public static Type ReturnWithMethodsStatic () => typeof (int);
+
+ public void GenericWithMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { }
+
+ public void ParamWithMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public Type ReturnWithMethods () => typeof (int);
+ }
+
+ class DerivedFromAnnotatedMatch : Library.AnnotatedMethods
+ {
+ public override void GenericWithMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () { }
+
+ public override void ParamWithMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ public override Type ReturnWithMethods () => typeof (int);
+ }
+
+ class DerivedFromUnannotatedMatch : Library.UnannotatedMethods
+ {
+ public override void Generic<T> () { }
+
+ public override void Param (Type t) { }
+
+ public override Type Return () => typeof (int);
+ }
+
+ public static void Test ()
+ {
+ typeof (ImplIUnannotatedMethodsMismatch).RequiresPublicMethods ();
+ typeof (ImplIAnnotatedMethodsMismatch).RequiresPublicMethods ();
+ typeof (DerivedFromAnnotatedMismatch).RequiresPublicMethods ();
+ typeof (DerivedFromUnannotatedMismatch).RequiresPublicMethods ();
+ typeof (ImplIUnannotatedMethodsMatch).RequiresPublicMethods ();
+ typeof (ImplIAnnotatedMethodsMatch).RequiresPublicMethods ();
+ typeof (DerivedFromAnnotatedMatch).RequiresPublicMethods ();
+ typeof (DerivedFromUnannotatedMatch).RequiresPublicMethods ();
+ }
}
}
}
diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs
index 9ab783533..4faf621c6 100644
--- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs
+++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresAttributeMismatch.cs
@@ -62,6 +62,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
typeof (ExplicitImplementationClassWithoutRequires).RequiresPublicMethods ();
typeof (ImplementationClassWithoutRequiresInSource).RequiresPublicMethods ();
typeof (ImplementationClassWithRequiresInSource).RequiresPublicMethods ();
+ typeof (StaticInterfaceMethods).RequiresPublicMethods ();
}
class BaseClassWithRequires
@@ -451,5 +452,93 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
[RequiresAssemblyFiles ("Message")]
public string PropertyAnnotationInProperty { get; set; }
}
+
+
+ class StaticInterfaceMethods
+ {
+ [ExpectedWarning ("IL2026")]
+ [ExpectedWarning ("IL2026")]
+ [ExpectedWarning ("IL2026")]
+ [ExpectedWarning ("IL2026")]
+ [ExpectedWarning ("IL2026")]
+ [ExpectedWarning ("IL2026")]
+ public static void Test ()
+ {
+ typeof (IRequires).RequiresPublicMethods ();
+ typeof (INoRequires).RequiresPublicMethods ();
+ typeof (ImplINoRequiresMatching).RequiresPublicMethods ();
+ typeof (ImplINoRequiresMismatching).RequiresPublicMethods ();
+ typeof (ImplIRequiresMismatching).RequiresPublicMethods ();
+ typeof (ImplIRequiresMatching).RequiresPublicMethods ();
+ }
+ interface IRequires
+ {
+ [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.IRequires.VirtualMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.IRequires.VirtualMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaceMethods.IRequires.VirtualMethod--")]
+ static virtual void VirtualMethod () { }
+ [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.IRequires.AbstractMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.IRequires.AbstractMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaceMethods.IRequires.AbstractMethod--")]
+ static abstract void AbstractMethod ();
+ }
+
+ interface INoRequires
+ {
+ static virtual void VirtualMethod () { }
+ static abstract void AbstractMethod ();
+ }
+
+ class ImplIRequiresMatching : IRequires
+ {
+ [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplIRequiresMatching.VirtualMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplIRequiresMatching.VirtualMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplIRequiresMatching.VirtualMethod--")]
+ public static void VirtualMethod () { }
+
+ [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplIRequiresMatching.AbstractMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplIRequiresMatching.AbstractMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplIRequiresMatching.AbstractMethod--")]
+ public static void AbstractMethod () { }
+ }
+
+ class ImplIRequiresMismatching : IRequires
+ {
+ [ExpectedWarning ("IL2046", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod")]
+ [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.VirtualMethod", "IRequires.VirtualMethod", ProducedBy = ProducedBy.Analyzer)]
+ public static void VirtualMethod () { }
+
+ [ExpectedWarning ("IL2046", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod")]
+ [ExpectedWarning ("IL3003", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3051", "ImplIRequiresMismatching.AbstractMethod", "IRequires.AbstractMethod", ProducedBy = ProducedBy.Analyzer)]
+ public static void AbstractMethod () { }
+ }
+ class ImplINoRequiresMatching : INoRequires
+ {
+ public static void VirtualMethod () { }
+
+ public static void AbstractMethod () { }
+ }
+
+ class ImplINoRequiresMismatching : INoRequires
+ {
+ [ExpectedWarning ("IL2046", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod")]
+ [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.VirtualMethod", "INoRequires.VirtualMethod", ProducedBy = ProducedBy.Analyzer)]
+ [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.VirtualMethod--")]
+ public static void VirtualMethod () { }
+
+ [ExpectedWarning ("IL2046", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod")]
+ [ExpectedWarning ("IL3003", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3051", "ImplINoRequiresMismatching.AbstractMethod", "INoRequires.AbstractMethod", ProducedBy = ProducedBy.Analyzer)]
+ [RequiresUnreferencedCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaceMethods.ImplINoRequiresMatching.AbstractMethod--")]
+ public static void AbstractMethod () { }
+ }
+ }
}
}
diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs
index bcafdf40f..31c43de7e 100644
--- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs
+++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnVirtualsAndInterfaces.cs
@@ -26,6 +26,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
TestCovariantReturnCallOnDerived ();
CovariantReturnViaLdftn.Test ();
NewSlotVirtual.Test ();
+ StaticInterfaces.Test ();
}
class BaseType
@@ -230,5 +231,47 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
typeof (Derived).RequiresPublicMethods ();
}
}
+
+ class StaticInterfaces
+ {
+ interface IRequires
+ {
+ [RequiresUnreferencedCode ("Message for --StaticInterfaces.IRequires.VirtualMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaces.IRequires.VirtualMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaces.IRequires.VirtualMethod--")]
+ static virtual void VirtualMethod () { }
+ [RequiresUnreferencedCode ("Message for --StaticInterfaces.IRequires.AbstractMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaces.IRequires.AbstractMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaces.IRequires.AbstractMethod--")]
+ static abstract void AbstractMethod ();
+ }
+ class ImplsIRequires : IRequires
+ {
+ [RequiresUnreferencedCode ("Message for --StaticInterfaces.ImplIRequires.VirtualMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaces.ImplIRequires.VirtualMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaces.ImplIRequires.VirtualMethod--")]
+ public static void VirtualMethod () { }
+ [RequiresUnreferencedCode ("Message for --StaticInterfaces.ImplIRequires.AbstractMethod--")]
+ [RequiresAssemblyFiles ("Message for --StaticInterfaces.ImplIRequires.AbstractMethod--")]
+ [RequiresDynamicCode ("Message for --StaticInterfaces.ImplIRequires.AbstractMethod--")]
+ public static void AbstractMethod () { }
+ }
+
+ [ExpectedWarning ("IL2026", "--StaticInterfaces.IRequires.VirtualMethod--")]
+ [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.VirtualMethod--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.VirtualMethod--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2026", "--StaticInterfaces.IRequires.AbstractMethod--")]
+ [ExpectedWarning ("IL3002", "--StaticInterfaces.IRequires.AbstractMethod--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--StaticInterfaces.IRequires.AbstractMethod--", ProducedBy = ProducedBy.Analyzer)]
+ static void UseRequiresMethods<T> () where T : IRequires
+ {
+ T.AbstractMethod ();
+ T.VirtualMethod ();
+ }
+ public static void Test ()
+ {
+ UseRequiresMethods<ImplsIRequires> ();
+ }
+ }
}
}