diff options
author | Jackson Schuster <36744439+jtschuster@users.noreply.github.com> | 2022-08-11 23:37:57 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-11 23:37:57 +0300 |
commit | e45a9356e779e457edf335ea9c34e6c9c49330f6 (patch) | |
tree | f22dc02f9bd5c9a720cad3ddd7c78ee8222a5cf8 | |
parent | 6e8e139a484f74c524c821c7a4a08287d77257a4 (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.
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> (); + } + } } } |