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
path: root/test
diff options
context:
space:
mode:
authorSven Boemer <sbomer@gmail.com>2022-06-07 21:23:01 +0300
committerGitHub <noreply@github.com>2022-06-07 21:23:01 +0300
commit42eddb34cbde2364da89dc40dac722957f225b15 (patch)
treeb4d7b99aeb02c19a57fd1fb5a0062a7d5a834e4d /test
parent1481a51970586b26208a7bc6173dc77d658f3508 (diff)
Scan compiler-generated methods as a group (#2792)
This scans compiler-generated methods together as a group when marking the corresponding user code. There are two scans that we do: 1. An initial scan to determine whether we need to run the dataflow scanner. It is also what marks static dependencies of the method IL. 2. The full dataflow scan (only if the initial scan says we need to). This produces warnings and marks reflection dependencies. Both scans are now done for the group of compiler-generated methods when marking the user code. For now, we only do the dataflow scan once per method, but in a later change, we will need to allow re-scanning compiler-generated callees (as part of the full scan for the corresponding user code) to properly track captured state. When compiler-generated code is accessed via reflection, we now don't do a dataflow scan because we don't have the context that might be captured from user code. This also means that reflection-dependencies of the compiler-generated code aren't kept, and dataflow warnings aren't produced, unless the code is reached through the corresponding user method. To guard against this, there are new warnings on reflection access to compiler-generated code. The reflection access warnings are only for compiler-generated code which would normally require the reflection method body scanner. This is a heuristic meant to conservatively approximate "this compiler-generated code would produce dataflow warnings if invoked by reflection with an unknown context".
Diffstat (limited to 'test')
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs6
-rw-r--r--test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs8
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs523
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs213
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs136
-rw-r--r--test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs18
-rw-r--r--test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs23
7 files changed, 898 insertions, 29 deletions
diff --git a/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs b/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
index b92038a6a..5e7ccb3dd 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
@@ -71,6 +71,12 @@ namespace ILLink.RoslynAnalyzer.Tests
}
[Fact]
+ public Task CompilerGeneratedCodeAccessedViaReflection ()
+ {
+ return RunTest ();
+ }
+
+ [Fact]
public Task DynamicDependencyDataflow ()
{
return RunTest (nameof (DynamicDependencyDataflow));
diff --git a/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs b/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs
index 52873a9d0..ad36b4884 100644
--- a/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs
+++ b/test/ILLink.RoslynAnalyzer.Tests/RequiresCapabilityTests.cs
@@ -6,7 +6,7 @@ using Xunit;
namespace ILLink.RoslynAnalyzer.Tests
{
- public sealed class RequiresCapabilityTests : LinkerTestBase
+ public sealed partial class RequiresCapabilityTests : LinkerTestBase
{
protected override string TestSuiteName => "RequiresCapability";
@@ -17,6 +17,12 @@ namespace ILLink.RoslynAnalyzer.Tests
}
[Fact]
+ public Task ReflectionAccessFromCompilerGeneratedCode ()
+ {
+ return RunTest ();
+ }
+
+ [Fact]
public Task RequiresAccessedThrough ()
{
return RunTest (nameof (RequiresAccessedThrough));
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs
new file mode 100644
index 000000000..1b5f65c7e
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs
@@ -0,0 +1,523 @@
+// 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.Linq.Expressions;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Mono.Linker.Tests.Cases.DataFlow;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Helpers;
+
+namespace Mono.Linker.Tests.Cases.DataFlow
+{
+ [SkipKeptItemsValidation]
+ [ExpectedNoWarnings]
+ class CompilerGeneratedCodeAccessedViaReflection
+ {
+ public static void Main ()
+ {
+ IteratorStateMachines.Test ();
+ AsyncStateMachines.Test ();
+ AsyncIteratorStateMachines.Test ();
+ Lambdas.Test ();
+ LocalFunctions.Test ();
+ }
+
+ class BaseTypeWithIteratorStateMachines
+ {
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ public static IEnumerable<int> BaseIteratorWithCorrectDataflow ()
+ {
+ var t = GetAll ();
+ yield return 0;
+ t.RequiresAll ();
+ }
+ }
+
+ [ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
+ class IteratorStateMachines : BaseTypeWithIteratorStateMachines
+ {
+ public static IEnumerable<int> IteratorWithoutDataflow ()
+ {
+ yield return 0;
+ }
+
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--",
+ ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--",
+ ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", CompilerGeneratedCode = true)]
+ public static IEnumerable<int> IteratorCallsMethodWithRequires ()
+ {
+ yield return 0;
+ MethodWithRequires ();
+ }
+
+ [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext", CompilerGeneratedCode = true)]
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ public static IEnumerable<int> IteratorWithCorrectDataflow ()
+ {
+ var t = GetAll ();
+ yield return 0;
+ t.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext", CompilerGeneratedCode = true)]
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ public static IEnumerable<int> IteratorWithProblematicDataflow ()
+ {
+ var t = GetWithPublicMethods ();
+ yield return 0;
+ t.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", CompilerGeneratedCode = true)]
+ [RequiresUnreferencedCode ("--RUCTypeWithIterators--")]
+ class RUCTypeWithIterators
+ {
+ [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires), "--RUCTypeWithIterators--",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2112", "<" + nameof (StaticIteratorCallsMethodWithRequires) + ">", "--RUCTypeWithIterators--", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)] // state machine ctor
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ public static IEnumerable<int> StaticIteratorCallsMethodWithRequires ()
+ {
+ yield return 0;
+ MethodWithRequires ();
+ }
+
+ // BUG: this should also give IL2112 for the InstanceIteratorCallsMethodWithRequires state machine constructor.
+ // https://github.com/dotnet/linker/issues/2806
+ // [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + ">")]
+ // With that, the IL2119 warning should also go away.
+ [ExpectedWarning ("IL2119", "<" + nameof (InstanceIteratorCallsMethodWithRequires) + ">", "MoveNext", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ public IEnumerable<int> InstanceIteratorCallsMethodWithRequires ()
+ {
+ yield return 0;
+ MethodWithRequires ();
+ }
+ }
+
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--")]
+ // Expect to see warnings about RUC on type, for all static state machine members.
+ [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.StaticIteratorCallsMethodWithRequires) + "()", "--RUCTypeWithIterators--")]
+ [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithIterators.StaticIteratorCallsMethodWithRequires) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ // BUG: this should also give IL2026 for the InstanceIteratorCallsMethodWithRequires state machine constructor.
+ // https://github.com/dotnet/linker/issues/2806
+ // [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + ">")]
+ // With that, the IL2118 warning should also go away.
+ [ExpectedWarning ("IL2118", "<" + nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ public static void Test (IteratorStateMachines test = null)
+ {
+ typeof (IteratorStateMachines).RequiresAll ();
+
+ test.GetType ().RequiresAll ();
+ }
+ }
+
+ class AsyncStateMachines
+ {
+ public static async Task AsyncWithoutDataflow ()
+ {
+ }
+
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ public static async Task AsyncCallsMethodWithRequires ()
+ {
+ MethodWithRequires ();
+ }
+
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ public static async Task AsyncWithCorrectDataflow ()
+ {
+ var t = GetAll ();
+ t.RequiresAll ();
+ }
+
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ public static async Task AsyncWithProblematicDataflow ()
+ {
+ var t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncCallsMethodWithRequires) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ public static void Test ()
+ {
+ typeof (AsyncStateMachines).RequiresAll ();
+ }
+ }
+
+ class AsyncIteratorStateMachines
+ {
+ public static async IAsyncEnumerable<int> AsyncIteratorWithoutDataflow ()
+ {
+ yield return await MethodAsync ();
+ }
+
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ public static async IAsyncEnumerable<int> AsyncIteratorCallsMethodWithRequires ()
+ {
+ yield return await MethodAsync ();
+ MethodWithRequires ();
+ }
+
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ public static async IAsyncEnumerable<int> AsyncIteratorWithCorrectDataflow ()
+ {
+ var t = GetAll ();
+ yield return await MethodAsync ();
+ t.RequiresAll ();
+ }
+
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll),
+ nameof (AsyncIteratorWithProblematicDataflow), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ public static async IAsyncEnumerable<int> AsyncIteratorWithProblematicDataflow ()
+ {
+ var t = GetWithPublicMethods ();
+ yield return await MethodAsync ();
+ t.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorCallsMethodWithRequires) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
+ public static void Test ()
+ {
+ typeof (AsyncIteratorStateMachines).RequiresAll ();
+ }
+ }
+
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
+ class Lambdas
+ {
+ static void LambdaWithoutDataflow ()
+ {
+ var lambda = () => 0;
+ lambda ();
+ }
+
+ static void LambdaCallsMethodWithRequires ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--")]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ () => MethodWithRequires ();
+ lambda ();
+ }
+
+ static void LambdaWithCorrectDataflow ()
+ {
+ var lambda =
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCorrectDataflow) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ () => {
+ var t = GetAll ();
+ t.RequiresAll ();
+ };
+ lambda ();
+ }
+
+ [ExpectedWarning ("IL2111", "<" + nameof (LambdaWithCorrectParameter) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ static void LambdaWithCorrectParameter ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2114", "<" + nameof (LambdaWithCorrectParameter) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ ([DynamicallyAccessedMembersAttribute (DynamicallyAccessedMemberTypes.All)] Type t) => {
+ t.RequiresAll ();
+ };
+ lambda (null);
+ }
+
+ static void LambdaWithProblematicDataflow ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithProblematicDataflow) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => {
+ var t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ };
+ lambda ();
+ }
+
+ static void LambdaWithCapturedTypeToDAM ()
+ {
+ var t = GetWithPublicMethods ();
+ var lambda =
+ [ExpectedWarning ("IL2119", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => {
+ t.RequiresAll ();
+ };
+ lambda ();
+ }
+
+ static void LambdaWithCapturedInt ()
+ {
+ int i = 0;
+ var lambda =
+ () => i;
+ i++;
+ lambda ();
+ }
+
+ [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", CompilerGeneratedCode = true)]
+ [RequiresUnreferencedCode ("--RUCTypeWithLambdas--")]
+ class RUCTypeWithLambdas
+ {
+ public void MethodWithLambdas ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2119", "<" + nameof (MethodWithLambdas) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ () => MethodWithRequires ();
+
+ int i = 0;
+ var lambdaWithCapturedState =
+ [ExpectedWarning ("IL2119", "<" + nameof (MethodWithLambdas) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ () => {
+ i++;
+ MethodWithRequires ();
+ };
+
+ lambda ();
+ lambdaWithCapturedState ();
+ }
+ }
+
+ [ExpectedWarning ("IL2118", "<" + nameof (LambdaCallsMethodWithRequires) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2111", "<" + nameof (LambdaWithCorrectParameter) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ // Expect RUC warnings for static, compiler-generated code warnings for instance.
+ [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--")]
+ [ExpectedWarning ("IL2118", "<" + nameof (RUCTypeWithLambdas.MethodWithLambdas) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (RUCTypeWithLambdas.MethodWithLambdas) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ public static void Test (Lambdas test = null)
+ {
+ typeof (Lambdas).RequiresAll ();
+
+ test.GetType ().RequiresAll ();
+ }
+ }
+
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
+ class LocalFunctions
+ {
+ static void LocalFunctionWithoutDataflow ()
+ {
+ int LocalFunction () => 0;
+ LocalFunction ();
+ }
+
+ static void LocalFunctionCallsMethodWithRequires ()
+ {
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--")]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => MethodWithRequires ();
+ LocalFunction ();
+ }
+
+ static void LocalFunctionWithCorrectDataflow ()
+ {
+ [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCorrectDataflow) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction ()
+ {
+ var t = GetAll ();
+ t.RequiresAll ();
+ };
+ LocalFunction ();
+ }
+
+ static void LocalFunctionWithProblematicDataflow ()
+ {
+ [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithProblematicDataflow) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction ()
+ {
+ var t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ };
+ LocalFunction ();
+ }
+
+ static void LocalFunctionWithCapturedTypeToDAM ()
+ {
+ var t = GetAll ();
+ [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionWithCapturedTypeToDAM) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
+ [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction ()
+ {
+ t.RequiresAll ();
+ };
+ LocalFunction ();
+ }
+
+ static void LocalFunctionWithCapturedInt ()
+ {
+ int i = 0;
+ int LocalFunction () => i;
+ i++;
+ LocalFunction ();
+ }
+
+ [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", CompilerGeneratedCode = true)]
+ [RequiresUnreferencedCode ("--RUCTypeWithLocalFunctions--")]
+ class RUCTypeWithLocalFunctions
+ {
+ public void MethodWithLocalFunctions ()
+ {
+ [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ void LocalFunction () => MethodWithRequires ();
+
+ [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ static void StaticLocalFunction () => MethodWithRequires ();
+
+ int i = 0;
+ [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ void LocalFunctionWithCapturedState ()
+ {
+ i++;
+ MethodWithRequires ();
+ }
+
+ LocalFunction ();
+ StaticLocalFunction ();
+ LocalFunctionWithCapturedState ();
+ }
+ }
+
+ [ExpectedWarning ("IL2118", nameof (LocalFunctionCallsMethodWithRequires),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCorrectDataflow),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (LocalFunctionWithProblematicDataflow),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (LocalFunctionWithCapturedTypeToDAM),
+ ProducedBy = ProducedBy.Trimmer)]
+ // Expect RUC warnings for static, compiler-generated code warnings for instance.
+ [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions) + "()", "--RUCTypeWithLocalFunctions--")]
+ [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "LocalFunctionWithCapturedState",
+ ProducedBy = ProducedBy.Trimmer)] // displayclass ctor
+ [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "StaticLocalFunction",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "LocalFunction",
+ ProducedBy = ProducedBy.Trimmer)]
+ public static void Test (LocalFunctions test = null)
+ {
+ typeof (LocalFunctions).RequiresAll ();
+
+ test.GetType ().RequiresAll ();
+ }
+ }
+
+ [RequiresUnreferencedCode ("--MethodWithRequires--")]
+ [RequiresAssemblyFiles ("--MethodWithRequires--")]
+ [RequiresDynamicCode ("--MethodWithRequires--")]
+ static void MethodWithRequires ()
+ {
+ }
+
+ static async Task<int> MethodAsync ()
+ {
+ return await Task.FromResult (0);
+ }
+
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ static Type GetWithPublicMethods () => null;
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
+ static Type GetAll () => null;
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs
new file mode 100644
index 000000000..14fd917fb
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/ReflectionAccessFromCompilerGeneratedCode.cs
@@ -0,0 +1,213 @@
+// 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.Threading.Tasks;
+using Mono.Linker.Tests.Cases.Expectations.Assertions;
+using Mono.Linker.Tests.Cases.Expectations.Helpers;
+
+namespace Mono.Linker.Tests.Cases.RequiresCapability
+{
+ [SkipKeptItemsValidation]
+ [ExpectedNoWarnings]
+ public class ReflectionAccessFromCompilerGeneratedCode
+ {
+ public static void Main ()
+ {
+ ReflectionAccessFromStateMachine.Test ();
+ ReflectionAccessFromLocalFunction.Test ();
+ ReflectionAccessFromLambda.Test ();
+ }
+
+ class ReflectionAccessFromStateMachine
+ {
+ [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ static IEnumerable<int> TestIterator ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ yield return 0;
+ }
+
+ [RequiresUnreferencedCode ("--TestIteratorWithRUC--")]
+ static IEnumerable<int> TestIteratorWithRUC ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ yield return 0;
+ }
+
+ [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ static async void TestAsync ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ await MethodAsync ();
+ }
+
+ [RequiresUnreferencedCode ("--TestAsyncWithRUC--")]
+ static async void TestAsyncWithRUC ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ await MethodAsync ();
+ }
+
+ [ExpectedWarning ("IL2026", "--TestIteratorWithRUC--")]
+ [ExpectedWarning ("IL2026", "--TestAsyncWithRUC--")]
+ public static void Test ()
+ {
+ TestIterator ();
+ TestIteratorWithRUC ();
+ TestAsync ();
+ TestAsyncWithRUC ();
+ }
+ }
+
+ class ReflectionAccessFromLocalFunction
+ {
+ static void TestLocalFunction ()
+ {
+ [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ }
+ LocalFunction ();
+ }
+
+ [ExpectedWarning ("IL2026", "--LocalFunction--")]
+ static void TestLocalFunctionWithRUC ()
+ {
+ [RequiresUnreferencedCode ("--LocalFunction--")]
+ void LocalFunction ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ }
+ LocalFunction ();
+ }
+
+ [RequiresUnreferencedCode ("--TestLocalFunctionInMethodWithRUC--")]
+ static void TestLocalFunctionInMethodWithRUC ()
+ {
+ void LocalFunction ()
+ {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ }
+ LocalFunction ();
+ }
+
+ [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRUC--")]
+ public static void Test ()
+ {
+ TestLocalFunction ();
+ TestLocalFunctionWithRUC ();
+ TestLocalFunctionInMethodWithRUC ();
+ }
+ }
+
+ class ReflectionAccessFromLambda
+ {
+ static void TestLambda ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ };
+ lambda ();
+ }
+
+ [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRUC--")]
+ static void TestLambdaWithRUC ()
+ {
+ var lambda =
+ [RequiresUnreferencedCode ("--TestLambdaInMethodWithRUC--")]
+ () => {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ };
+ lambda ();
+ }
+
+ [RequiresUnreferencedCode ("--TestLambdaInMethodWithRUC--")]
+ static void TestLambdaInMethodWithRUC ()
+ {
+ var lambda =
+ () => {
+ typeof (TypeWithMethodWithRequires).RequiresAll ();
+ };
+ lambda ();
+ }
+
+ [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRUC--")]
+ public static void Test ()
+ {
+ TestLambda ();
+ TestLambdaWithRUC ();
+ TestLambdaInMethodWithRUC ();
+ }
+ }
+
+ static async Task<int> MethodAsync ()
+ {
+ return await Task.FromResult (0);
+ }
+
+ class TypeWithMethodWithRequires
+ {
+ [RequiresUnreferencedCode ("--TypeWithMethodWithRequires.MethodWithRequires--")]
+ [RequiresAssemblyFiles ("--TypeWithMethodWithRequires.MethodWithRequires--")]
+ [RequiresDynamicCode ("--TypeWithMethodWithRequires.MethodWithRequires--")]
+ public static void MethodWithRequires ()
+ {
+ }
+
+ public static void MethodWithAnnotations ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type t) { }
+
+ [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--")]
+ public static void MethodWithLocalFunctionWithRUC ()
+ {
+ [RequiresUnreferencedCode ("--MethodWithLocalFunctionWithRUC.LocalFunction--")]
+ void LocalFunction ()
+ { }
+ LocalFunction ();
+ }
+
+ public static void MethodWithLocalFunctionCallsRUC ()
+ {
+ [ExpectedWarning ("IL2026", "--MethodWithRUC--")]
+ void LocalFunction () => MethodWithRUC ();
+ LocalFunction ();
+ }
+ }
+
+ [RequiresUnreferencedCode ("--MethodWithRUC--")]
+ static void MethodWithRUC () { }
+ }
+}
diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs
index d3f277902..79b795c66 100644
--- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs
+++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs
@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// 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;
@@ -618,7 +618,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
{
LocalFunction ();
- [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--",
+ ProducedBy = ProducedBy.Trimmer)]
void LocalFunction () => typeof (RequiresInCompilerGeneratedCode)
.GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic)
.Invoke (null, new object[] { });
@@ -656,7 +657,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
{
LocalFunction ();
- [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--",
+ ProducedBy = ProducedBy.Trimmer)]
void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods ();
}
@@ -869,19 +871,38 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
}
}
- class DynamicallyAccessedLocalFunctionUnused
+ class DynamicallyAccessedLocalFunctionUnusedShouldWarn
+ {
+ [ExpectedWarning ("IL2118", nameof (TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction), "LocalFunction", ProducedBy = ProducedBy.Trimmer)]
+ public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction ()
+ {
+ typeof (DynamicallyAccessedLocalFunctionUnusedShouldWarn).RequiresNonPublicMethods ();
+
+ // The linker isn't able to figure out which user method this local function
+ // belongs to, but it doesn't warn because it is only accessed via reflection.
+ // Instead this warns on the reflection access.
+ [ExpectedWarning ("IL2026", "--MethodWithRequires--",
+ ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3002", "--MethodWithRequires--",
+ ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--MethodWithRequires--",
+ ProducedBy = ProducedBy.Analyzer)]
+ void LocalFunction () => MethodWithRequires ();
+ }
+ }
+
+ class DynamicallyAccessedLocalFunctionUnusedShouldSuppress
{
[RequiresUnreferencedCode ("Suppress in body")]
[RequiresAssemblyFiles ("Suppress in body")]
[RequiresDynamicCode ("Suppress in body")]
public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction ()
{
- typeof (DynamicallyAccessedLocalFunctionUnused).RequiresNonPublicMethods ();
+ typeof (DynamicallyAccessedLocalFunctionUnusedShouldSuppress).RequiresNonPublicMethods ();
- // This local function is unused except for the dynamic reference above,
- // so the linker isn't able to figure out which user method it belongs to,
- // and the warning is not suppressed.
- [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ // The linker isn't able to figure out which user method this local function
+ // belongs to, but it doesn't warn because it is only accessed via reflection,
+ // in a RUC scope.
void LocalFunction () => MethodWithRequires ();
}
}
@@ -906,6 +927,26 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
[ExpectedWarning ("IL2026")]
[ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
+ static void TestSuppressionOnLocalFunctionWithAssignment ()
+ {
+ LocalFunction (); // This will produce a warning since the local function has Requires on it
+
+ [RequiresUnreferencedCode ("Suppress in body")]
+ [RequiresAssemblyFiles ("Suppress in body")]
+ [RequiresDynamicCode ("Suppress in body")]
+ void LocalFunction (Type unknownType = null)
+ {
+ MethodWithRequires ();
+ typeWithNonPublicMethods = unknownType;
+ }
+ }
+
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ static Type typeWithNonPublicMethods;
+
+ [ExpectedWarning ("IL2026")]
+ [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)]
static void TestSuppressionOnLocalFunctionWithNestedLocalFunction ()
{
LocalFunction (); // This will produce a warning since the local function has Requires on it
@@ -994,8 +1035,10 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
TestGenericLocalFunctionWithAnnotationsAndClosure<TestType> ();
TestCallMethodWithRequiresInLtftnLocalFunction ();
DynamicallyAccessedLocalFunction.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction ();
- DynamicallyAccessedLocalFunctionUnused.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction ();
+ DynamicallyAccessedLocalFunctionUnusedShouldWarn.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction ();
+ DynamicallyAccessedLocalFunctionUnusedShouldSuppress.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction ();
TestSuppressionOnLocalFunction ();
+ TestSuppressionOnLocalFunctionWithAssignment ();
TestSuppressionOnLocalFunctionWithNestedLocalFunction ();
TestSuppressionOnOuterAndLocalFunction ();
TestSuppressionOnOuterWithSameName.Test ();
@@ -1043,6 +1086,20 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
lambda ();
}
+ [ExpectedWarning ("IL2026", "--LambdaWithRequires--")]
+ [ExpectedWarning ("IL3002", "--LambdaWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--LambdaWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ static void TestLambdaWithRequires ()
+ {
+ Action lambda =
+ [RequiresUnreferencedCodeAttribute ("--LambdaWithRequires--")]
+ [RequiresAssemblyFiles ("--LambdaWithRequires--")]
+ [RequiresDynamicCode ("--LambdaWithRequires--")]
+ () => MethodWithRequires ();
+
+ lambda ();
+ }
+
static void TestCallUnused ()
{
Action _ =
@@ -1052,6 +1109,18 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
() => MethodWithRequires ();
}
+ [ExpectedWarning ("IL2026", "--LambdaWithRequires--")]
+ [ExpectedWarning ("IL3002", "--LambdaWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ [ExpectedWarning ("IL3050", "--LambdaWithRequires--", ProducedBy = ProducedBy.Analyzer)]
+ static void TestLambdaWithRequiresUnused ()
+ {
+ Action _ =
+ [RequiresUnreferencedCode ("--LambdaWithRequires--")]
+ [RequiresAssemblyFiles ("--LambdaWithRequires--")]
+ [RequiresDynamicCode ("--LambdaWithRequires--")]
+ () => MethodWithRequires ();
+ }
+
static void TestCallWithClosure (int p = 0)
{
Action lambda =
@@ -1125,6 +1194,8 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
{
TestCall ();
TestCallUnused ();
+ TestLambdaWithRequires ();
+ TestLambdaWithRequiresUnused ();
TestCallWithClosure ();
TestCallWithClosureUnused ();
TestReflectionAccess ();
@@ -1390,6 +1461,13 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
MethodWithGenericWhichRequiresMethods<TypeWithMethodWithRequires> ();
}
+ [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)]
+ static IEnumerable<int> TestDynamicallyAccessedMethodViaGenericTypeParameterInIterator ()
+ {
+ yield return 1;
+ new TypeWithGenericWhichRequiresMethods<TypeWithMethodWithRequires> ();
+ }
+
static void TestLocalFunctionInIteratorLocalFunction ()
{
IteratorLocalFunction ();
@@ -1428,6 +1506,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
{
TestIteratorLocalFunctionInAsync ();
TestDynamicallyAccessedMethodViaGenericMethodParameterInIterator ();
+ TestDynamicallyAccessedMethodViaGenericTypeParameterInIterator ();
TestLocalFunctionInIteratorLocalFunction ();
TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod ();
}
@@ -1716,6 +1795,11 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
// state machine members.
[ExpectedWarning ("IL2026", "Requires to suppress", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "Requires to suppress", ProducedBy = ProducedBy.Trimmer)]
+ // Linker warns about reflection access to compiler-generated state machine members.
+ [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestAsyncOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", nameof (StateMachinesOnlyReferencedViaReflection), "<" + nameof (TestIteratorOnlyReferencedViaReflectionWhichShouldWarn) + ">", "MoveNext()",
+ ProducedBy = ProducedBy.Trimmer)]
static void TestAll ()
{
typeof (StateMachinesOnlyReferencedViaReflection).RequiresAll ();
@@ -1751,6 +1835,14 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
void LocalFunction () => MethodWithRequires ();
}
+ static void TestLocalFunctionWithRequiresOnlyAccessedViaReflection ()
+ {
+ [RequiresUnreferencedCode ("--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--")]
+ [RequiresAssemblyFiles ("--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--")]
+ [RequiresDynamicCode ("--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--")]
+ void LocalFunction () => MethodWithRequires ();
+ }
+
[ExpectedWarning ("IL2026", "LocalFunction")]
[ExpectedWarning ("IL3002", "LocalFunction", ProducedBy = ProducedBy.Analyzer)]
[ExpectedWarning ("IL3050", "LocalFunction", ProducedBy = ProducedBy.Analyzer)]
@@ -1778,6 +1870,16 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
void LocalFunction () => MethodWithRequires ();
}
+ [RequiresUnreferencedCode ("--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")]
+ [RequiresAssemblyFiles ("--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")]
+ [RequiresDynamicCode ("--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")]
+ static void TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection ()
+ {
+ // This is unused, except for the reflection access. Don't warn about MethodWithRequires
+ // because the reflection access will warn about accessing compiler-generated code.
+ void LocalFunction () => MethodWithRequires ();
+ }
+
[RequiresUnreferencedCode ("--TestLocalFunctionWithClosureInMethodWithRequires--")]
[RequiresAssemblyFiles ("--TestLocalFunctionWithClosureInMethodWithRequires--")]
[RequiresDynamicCode ("--TestLocalFunctionWithClosureInMethodWithRequires--")]
@@ -1795,13 +1897,18 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
// Warnings for Reflection access to methods with Requires
[ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--")]
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--")]
+ [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")]
// The linker correctly emits warnings about reflection access to local functions with Requires
// or which inherit Requires from the containing method. The analyzer doesn't bind to local functions
// so does not warn here.
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ // Linker warns about reflection access to compiler-generated code
+ [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection),
+ ProducedBy = ProducedBy.Trimmer)]
static void TestAll ()
{
typeof (LocalFunctionsReferencedViaReflection).RequiresAll ();
@@ -1810,11 +1917,16 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
// Warnings for Reflection access to methods with Requires
[ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--")]
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--")]
+ [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")]
// NonPublicMethods warns for local functions not emitted into display classes.
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)]
+ // Linker warns about reflection access to compiler-generated code
+ [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">",
+ ProducedBy = ProducedBy.Trimmer)]
static void TestNonPublicMethods ()
{
typeof (LocalFunctionsReferencedViaReflection).RequiresNonPublicMethods ();
@@ -2053,6 +2165,10 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
{
}
+ class TypeWithGenericWhichRequiresMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] T>
+ {
+ }
+
class TypeWithGenericWhichRequiresNonPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicFields)] T> { }
class TestType { }
diff --git a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs
index 9cb6e8a50..a0ecc2e51 100644
--- a/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs
+++ b/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs
@@ -719,12 +719,30 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
instance.GetType ().GetField ("publicField");
}
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
+ class DAMAnnotatedClassAccessedFromRUCScope
+ {
+ [ExpectedWarning ("IL2112", "DAMAnnotatedClassAccessedFromRUCScope.RUCMethod", ProducedBy = ProducedBy.Trimmer)]
+ [RequiresUnreferencedCode ("--RUCMethod--")]
+ public static void RUCMethod () { }
+ }
+
+ // RUC on the callsite to GetType should not suppress warnings about the
+ // attribute on the type.
+ [RequiresUnreferencedCode ("--TestDAMOnTypeAccessInRUCScope--")]
+ static void TestDAMOnTypeAccessInRUCScope (DAMAnnotatedClassAccessedFromRUCScope instance = null)
+ {
+ instance.GetType ().GetMethod ("RUCMethod");
+ }
+
+ [ExpectedWarning ("IL2026", "--TestDAMOnTypeAccessInRUCScope--")]
public static void Test ()
{
TestDAMAccess ();
TestDirectReflectionAccess ();
TestDynamicDependencyAccess ();
TestDAMOnTypeAccess (null);
+ TestDAMOnTypeAccessInRUCScope ();
}
}
diff --git a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs
index d1e1cc5f6..0c9bd06b1 100644
--- a/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs
+++ b/test/Mono.Linker.Tests.Cases/Warnings/WarningSuppression/SuppressWarningsInCompilerGeneratedCode.cs
@@ -279,6 +279,7 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression
class DynamicallyAccessedLocalFunction
{
+ [ExpectedWarning ("IL2118", "LocalFunction", ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
public static void TestCallRUCMethodInDynamicallyAccessedLocalFunction ()
{
@@ -290,21 +291,6 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression
}
}
- class DynamicallyAccessedLocalFunctionUnused
- {
- [UnconditionalSuppressMessage ("Test", "IL2026")]
- public static void TestCallRUCMethodInDynamicallyAccessedLocalFunction ()
- {
- typeof (DynamicallyAccessedLocalFunctionUnused).RequiresNonPublicMethods ();
-
- // This local function is unused except for the dynamic reference above,
- // so the linker isn't able to figure out which user method it belongs to,
- // and the warning is not suppressed.
- [ExpectedWarning ("IL2026", "--RequiresUnreferencedCodeMethod--", ProducedBy = ProducedBy.Trimmer)]
- void LocalFunction () => RequiresUnreferencedCodeMethod ();
- }
- }
-
static void TestSuppressionOnLocalFunction ()
{
LocalFunction ();
@@ -370,7 +356,6 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression
TestGenericLocalFunctionWithAnnotationsAndClosure<TestType> ();
TestCallRUCMethodInLtftnLocalFunction ();
DynamicallyAccessedLocalFunction.TestCallRUCMethodInDynamicallyAccessedLocalFunction ();
- DynamicallyAccessedLocalFunctionUnused.TestCallRUCMethodInDynamicallyAccessedLocalFunction ();
TestSuppressionOnLocalFunction ();
TestSuppressionOnOuterAndLocalFunction ();
TestSuppressionOnOuterWithSameName.Test ();
@@ -441,10 +426,11 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression
class DynamicallyAccessedLambda
{
+ [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
public static void TestCallRUCMethodInDynamicallyAccessedLambda ()
{
- typeof (DynamicallyAccessedLambda).RequiresNonPublicMethods ();
+ typeof (DynamicallyAccessedLambda).RequiresAll ();
Action lambda = () => RequiresUnreferencedCodeMethod ();
@@ -454,10 +440,11 @@ namespace Mono.Linker.Tests.Cases.Warnings.WarningSuppression
class DynamicallyAccessedLambdaUnused
{
+ [ExpectedWarning ("IL2118", nameof (TestCallRUCMethodInDynamicallyAccessedLambda), ProducedBy = ProducedBy.Trimmer)]
[UnconditionalSuppressMessage ("Test", "IL2026")]
public static void TestCallRUCMethodInDynamicallyAccessedLambda ()
{
- typeof (DynamicallyAccessedLambdaUnused).RequiresNonPublicMethods ();
+ typeof (DynamicallyAccessedLambdaUnused).RequiresAll ();
Action _ = () => RequiresUnreferencedCodeMethod ();
}