From e75371251c9b78c619d5346ca014aa4631cadc72 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 28 Mar 2024 14:24:06 -0700 Subject: [PATCH] Allow trimming FeatureGuard and FeatureSwitchDefinition attributes (#100263) Under AggressiveAttributeTrimming setting. Fixes https://github.com/dotnet/runtime/issues/100256. AggressiveAttributeTrimming was attempting to remove RequiresDynamicCode attributes, but the type was still referenced by FeatureGuardAttribute on IsDynamicCodeCompiled. Adding FeatureGuardAttribute to the set of attributes that get removed with AggressiveAttributeTrimming fixes this. Also adding FeatureSwitchDefinitionAttribute because that one can be removed as well. --- .../ILLink/ILLink.LinkAttributes.Shared.xml | 6 ++ .../AggressiveAttributeTrimmingTest.cs | 80 +++++++++++++++++++ .../System.Runtime.TrimmingTests.proj | 4 + 3 files changed, 90 insertions(+) create mode 100644 src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/AggressiveAttributeTrimmingTest.cs diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.LinkAttributes.Shared.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.LinkAttributes.Shared.xml index adbcd6f00ee499..7706dd2ce18fec 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.LinkAttributes.Shared.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.LinkAttributes.Shared.xml @@ -250,6 +250,12 @@ + + + + + + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/AggressiveAttributeTrimmingTest.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/AggressiveAttributeTrimmingTest.cs new file mode 100644 index 00000000000000..dfdce520e1904d --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/AggressiveAttributeTrimmingTest.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Reflection; + +/// +/// Ensures setting _AggressiveAttributeTrimming = true causes various attributes to be trimmed +/// +class Program +{ + [UnconditionalSuppressMessage ("ReflectionAnalysis", "IL2111", Justification = "Expected trim warning for reflection over annotated members.")] + [UnconditionalSuppressMessage ("ReflectionAnalysis", "IL2026", Justification = "Expected trim warning for reflection over annotated members.")] + static int Main(string[] args) + { + // Reference to IsDynamicCodeSupported (which has FeatureGuard(typeof(RequiresDynamicCodeAttribute))) + // should not produce a warning because both RequiresDynamicCodeAttribute and FeatureGuardAttribute are removed. + if (RuntimeFeature.IsDynamicCodeSupported) + { + UseDynamicCode(); + } + + // Check that a few attribute instances are indeed removed + CheckRemovedAttributes(typeof(MembersWithRemovedAttributes)); + + return 100; + } + + [RequiresDynamicCode(nameof(UseDynamicCode))] + static void UseDynamicCode() { } + + class MembersWithRemovedAttributes + { + static void DynamicallyAccessedMembers([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { } + + [FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))] + static bool FeatureGuard => throw null!; + + [FeatureSwitchDefinition("Program.MembersWithRemovedAttributes.FeatureSwitchDefinition")] + static bool FeatureSwitchDefinition => throw null!; + + [RequiresDynamicCode(nameof(RequiresDynamicCode))] + static void RequiresDynamicCode() { } + + [RequiresUnreferencedCode(nameof(RequiresUnreferencedCode))] + static void RequiresUnreferencedCode() { } + } + + static void CheckRemovedAttributes([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) + { + Console.WriteLine($"Validating {type}"); + foreach (var member in type.GetMembers(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) + { + CheckRemovedAttributes(member); + + if (member is MethodInfo method) + { + foreach (var parameter in method.GetParameters()) + { + CheckRemovedAttributes(parameter); + } + } + } + } + + static void CheckRemovedAttributes(ICustomAttributeProvider provider) + { + foreach (var attribute in provider.GetCustomAttributes(false)) + { + if (attribute is NullableContextAttribute) + continue; + + throw new Exception($"Unexpected attribute {attribute.GetType()} on {provider}"); + } + } +} diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj index c786baba78e379..c9c42b2c20234e 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj @@ -2,6 +2,10 @@ + + _AggressiveAttributeTrimming + SuppressTrimAnalysisWarnings;TrimmerSingleWarn + osx-x64;linux-x64;browser-wasm