Skip to content

Commit e753712

Browse files
authored
Allow trimming FeatureGuard and FeatureSwitchDefinition attributes (#100263)
Under AggressiveAttributeTrimming setting. Fixes #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.
1 parent 7c14f71 commit e753712

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

src/libraries/System.Private.CoreLib/src/ILLink/ILLink.LinkAttributes.Shared.xml

+6
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@
250250
<type fullname="System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute">
251251
<attribute internal="RemoveAttributeInstances" />
252252
</type>
253+
<type fullname="System.Diagnostics.CodeAnalysis.FeatureGuardAttribute">
254+
<attribute internal="RemoveAttributeInstances" />
255+
</type>
256+
<type fullname="System.Diagnostics.CodeAnalysis.FeatureSwitchDefinitionAttribute">
257+
<attribute internal="RemoveAttributeInstances" />
258+
</type>
253259
<type fullname="System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute">
254260
<attribute internal="RemoveAttributeInstances" />
255261
</type>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#nullable enable
5+
6+
using System;
7+
using System.Diagnostics.CodeAnalysis;
8+
using System.Runtime.CompilerServices;
9+
using System.Reflection;
10+
11+
/// <summary>
12+
/// Ensures setting _AggressiveAttributeTrimming = true causes various attributes to be trimmed
13+
/// </summary>
14+
class Program
15+
{
16+
[UnconditionalSuppressMessage ("ReflectionAnalysis", "IL2111", Justification = "Expected trim warning for reflection over annotated members.")]
17+
[UnconditionalSuppressMessage ("ReflectionAnalysis", "IL2026", Justification = "Expected trim warning for reflection over annotated members.")]
18+
static int Main(string[] args)
19+
{
20+
// Reference to IsDynamicCodeSupported (which has FeatureGuard(typeof(RequiresDynamicCodeAttribute)))
21+
// should not produce a warning because both RequiresDynamicCodeAttribute and FeatureGuardAttribute are removed.
22+
if (RuntimeFeature.IsDynamicCodeSupported)
23+
{
24+
UseDynamicCode();
25+
}
26+
27+
// Check that a few attribute instances are indeed removed
28+
CheckRemovedAttributes(typeof(MembersWithRemovedAttributes));
29+
30+
return 100;
31+
}
32+
33+
[RequiresDynamicCode(nameof(UseDynamicCode))]
34+
static void UseDynamicCode() { }
35+
36+
class MembersWithRemovedAttributes
37+
{
38+
static void DynamicallyAccessedMembers([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type t) { }
39+
40+
[FeatureGuard(typeof(RequiresUnreferencedCodeAttribute))]
41+
static bool FeatureGuard => throw null!;
42+
43+
[FeatureSwitchDefinition("Program.MembersWithRemovedAttributes.FeatureSwitchDefinition")]
44+
static bool FeatureSwitchDefinition => throw null!;
45+
46+
[RequiresDynamicCode(nameof(RequiresDynamicCode))]
47+
static void RequiresDynamicCode() { }
48+
49+
[RequiresUnreferencedCode(nameof(RequiresUnreferencedCode))]
50+
static void RequiresUnreferencedCode() { }
51+
}
52+
53+
static void CheckRemovedAttributes([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type)
54+
{
55+
Console.WriteLine($"Validating {type}");
56+
foreach (var member in type.GetMembers(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
57+
{
58+
CheckRemovedAttributes(member);
59+
60+
if (member is MethodInfo method)
61+
{
62+
foreach (var parameter in method.GetParameters())
63+
{
64+
CheckRemovedAttributes(parameter);
65+
}
66+
}
67+
}
68+
}
69+
70+
static void CheckRemovedAttributes(ICustomAttributeProvider provider)
71+
{
72+
foreach (var attribute in provider.GetCustomAttributes(false))
73+
{
74+
if (attribute is NullableContextAttribute)
75+
continue;
76+
77+
throw new Exception($"Unexpected attribute {attribute.GetType()} on {provider}");
78+
}
79+
}
80+
}

src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/System.Runtime.TrimmingTests.proj

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
33

44
<ItemGroup>
5+
<TestConsoleAppSourceFiles Include="AggressiveAttributeTrimmingTest.cs">
6+
<EnabledProperties>_AggressiveAttributeTrimming</EnabledProperties>
7+
<DisabledProperties>SuppressTrimAnalysisWarnings;TrimmerSingleWarn</DisabledProperties>
8+
</TestConsoleAppSourceFiles>
59
<TestConsoleAppSourceFiles Include="AppDomainGetThreadGenericPrincipalTest.cs" />
610
<TestConsoleAppSourceFiles Include="AppDomainGetThreadWindowsPrincipalTest.cs">
711
<SkipOnTestRuntimes>osx-x64;linux-x64;browser-wasm</SkipOnTestRuntimes>

0 commit comments

Comments
 (0)