From b6609f25fad5abb834550256eb46f23348d90e29 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Jul 2026 18:53:07 +0000 Subject: [PATCH 1/2] Initial plan From 860048e3fa9c978bfa8662a8b585fb55e378d181 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Jul 2026 19:44:54 +0000 Subject: [PATCH 2/2] Add ILLink unused annotation regression coverage Co-authored-by: jtschuster <36744439+jtschuster@users.noreply.github.com> --- .../UnusedVirtualMethodAnnotations.cs | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnusedVirtualMethodAnnotations.cs diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnusedVirtualMethodAnnotations.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnusedVirtualMethodAnnotations.cs new file mode 100644 index 00000000000000..9137a74c34d030 --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/UnusedVirtualMethodAnnotations.cs @@ -0,0 +1,84 @@ +// 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.Diagnostics.CodeAnalysis; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Helpers; + +namespace Mono.Linker.Tests.Cases.DataFlow +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + class UnusedVirtualMethodAnnotations + { + [UnconditionalSuppressMessage("Test", "IL2026")] + public static void Main() + { + _ = typeof(TypeOnlyImplementation); + + IUsed used = new UsedImplementation(); + used.Method(typeof(object)); + + IPartiallyUsed partiallyUsed = new PartiallyUsedImplementation(); + partiallyUsed.Method(typeof(object)); + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + interface IUnused + { + [RequiresUnreferencedCode(nameof(Method))] + void Method([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type); + } + + class UnusedImplementation : IUnused + { + public void Method(Type type) { } + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + interface ITypeOnly + { + [RequiresUnreferencedCode(nameof(Method))] + void Method([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type); + } + + class TypeOnlyImplementation : ITypeOnly + { + public void Method(Type type) { } + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + interface IUsed + { + [RequiresUnreferencedCode(nameof(Method))] + void Method([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type); + } + + class UsedImplementation : IUsed + { + [ExpectedWarning("IL2046")] + [ExpectedWarning("IL2092")] + public void Method(Type type) { } + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] + interface IPartiallyUsed + { + [RequiresUnreferencedCode(nameof(Method))] + void Method([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type); + } + + class PartiallyUsedImplementation : IPartiallyUsed + { + [ExpectedWarning("IL2046")] + [ExpectedWarning("IL2092")] + public void Method(Type type) { } + } + + class UnusedImplementationOfPartiallyUsedInterface : IPartiallyUsed + { + public void Method(Type type) { } + } + } +}