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
diff options
context:
space:
mode:
Diffstat (limited to 'test/Mono.Linker.Tests.Cases/DataFlow')
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs83
-rw-r--r--test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs562
2 files changed, 613 insertions, 32 deletions
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs
index 1b5f65c7e..804f2a370 100644
--- a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs
@@ -30,8 +30,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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 ();
@@ -42,6 +40,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext",
ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2120", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "<t>",
+ ProducedBy = ProducedBy.Trimmer)]
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
class IteratorStateMachines : BaseTypeWithIteratorStateMachines
{
@@ -63,25 +63,33 @@ namespace Mono.Linker.Tests.Cases.DataFlow
}
[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)]
+ [ExpectedWarning ("IL2119", "<t_IteratorWithCorrectDataflow>", CompilerGeneratedCode = true)]
public static IEnumerable<int> IteratorWithCorrectDataflow ()
{
- var t = GetAll ();
+ var t_IteratorWithCorrectDataflow = GetAll ();
yield return 0;
- t.RequiresAll ();
+ t_IteratorWithCorrectDataflow.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2119", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext", CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL2119", "<types>", CompilerGeneratedCode = true)]
+ public static IEnumerable<int> IteratorWithIntegerDataflow ()
+ {
+ int integerLocal = 0;
+ yield return 0;
+ var types = new Type[] { GetWithPublicMethods (), GetWithPublicFields () };
+ types[integerLocal].RequiresPublicMethods ();
}
[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,
+ [ExpectedWarning ("IL2119", "<t_IteratorWithProblematicDataflow>", CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
ProducedBy = ProducedBy.Trimmer)]
public static IEnumerable<int> IteratorWithProblematicDataflow ()
{
- var t = GetWithPublicMethods ();
+ var t_IteratorWithProblematicDataflow = GetWithPublicMethods ();
yield return 0;
- t.RequiresAll ();
+ t_IteratorWithProblematicDataflow.RequiresAll ();
}
[ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", CompilerGeneratedCode = true)]
@@ -121,6 +129,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "MoveNext",
ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "MoveNext",
+ ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "MoveNext",
ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--")]
@@ -134,6 +144,18 @@ namespace Mono.Linker.Tests.Cases.DataFlow
// With that, the IL2118 warning should also go away.
[ExpectedWarning ("IL2118", "<" + nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + ">", "MoveNext",
ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "<t_IteratorWithCorrectDataflow>",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "<t_IteratorWithProblematicDataflow>",
+ ProducedBy = ProducedBy.Trimmer)]
+ // Technically the access to IteratorWithIntegerDataflow should warn about access to the integer
+ // field integerLocal, but our heuristics only warn if the field type satisfies the
+ // "IsTypeInterestingForDatafllow" check. This is likely good enough because in most cases the
+ // compiler-generated code will have other hoisted fields with types that _are_ interesting for dataflow.
+ [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithIntegerDataflow) + ">", "<types>",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (BaseIteratorWithCorrectDataflow) + ">", "<t>",
+ ProducedBy = ProducedBy.Trimmer)]
public static void Test (IteratorStateMachines test = null)
{
typeof (IteratorStateMachines).RequiresAll ();
@@ -156,22 +178,18 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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 ();
+ var t_AsyncWithCorrectDataflow = GetAll ();
+ t_AsyncWithCorrectDataflow.RequiresAll ();
}
- // Annotations aren't propagated to hoisted locals: https://github.com/dotnet/linker/issues/2001
- [ExpectedWarning ("IL2077", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
ProducedBy = ProducedBy.Trimmer)]
public static async Task AsyncWithProblematicDataflow ()
{
- var t = GetWithPublicMethods ();
- t.RequiresAll ();
+ var t_AsyncWithProblematicDataflow = GetWithPublicMethods ();
+ t_AsyncWithProblematicDataflow.RequiresAll ();
}
[ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "MoveNext",
@@ -180,6 +198,10 @@ namespace Mono.Linker.Tests.Cases.DataFlow
ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "MoveNext",
ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithCorrectDataflow) + ">", "<t_AsyncWithCorrectDataflow>",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncWithProblematicDataflow) + ">", "<t_AsyncWithProblematicDataflow>",
+ ProducedBy = ProducedBy.Trimmer)]
public static void Test ()
{
typeof (AsyncStateMachines).RequiresAll ();
@@ -202,9 +224,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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 ();
@@ -212,9 +231,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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,
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
ProducedBy = ProducedBy.Trimmer)]
public static async IAsyncEnumerable<int> AsyncIteratorWithProblematicDataflow ()
{
@@ -229,6 +246,10 @@ namespace Mono.Linker.Tests.Cases.DataFlow
ProducedBy = ProducedBy.Trimmer)]
[ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "MoveNext",
ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithCorrectDataflow) + ">", "<t>",
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2118", "<" + nameof (AsyncIteratorWithProblematicDataflow) + ">", "<t>",
+ ProducedBy = ProducedBy.Trimmer)]
public static void Test ()
{
typeof (AsyncIteratorStateMachines).RequiresAll ();
@@ -259,7 +280,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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)]
() => {
@@ -302,8 +322,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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),
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
ProducedBy = ProducedBy.Trimmer)]
() => {
t.RequiresAll ();
@@ -424,9 +443,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow
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 ();
@@ -517,6 +533,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
static Type GetWithPublicMethods () => null;
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
+ static Type GetWithPublicFields () => null;
+
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
static Type GetAll () => null;
}
diff --git a/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs
new file mode 100644
index 000000000..f42464e54
--- /dev/null
+++ b/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs
@@ -0,0 +1,562 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+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;
+using Mono.Linker.Tests.Cases.Expectations.Metadata;
+
+namespace Mono.Linker.Tests.Cases.DataFlow
+{
+ [SkipKeptItemsValidation]
+ [SetupCompileArgument ("/unsafe")]
+ [ExpectedNoWarnings]
+ public class CompilerGeneratedCodeDataflow
+ {
+ public static void Main ()
+ {
+ Iterator.Test ();
+ Async.Test ();
+ AsyncIterator.Test ();
+ LocalFunction.Test ();
+ Lambda.Test ();
+ Complex.Test ();
+ }
+
+ class Iterator
+ {
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ CompilerGeneratedCode = true)]
+ static IEnumerable<int> FlowAcrossYieldReturn ()
+ {
+ Type t = GetWithPublicMethods ();
+ yield return 0;
+ t.RequiresAll ();
+ }
+
+ // Linker tracks all assignments of hoisted locals, so this produces warnings.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), CompilerGeneratedCode = true)]
+ static IEnumerable<int> NoFlowAcrossYieldReturn ()
+ {
+ Type t = GetWithPublicMethods ();
+ t.RequiresPublicMethods ();
+ yield return 0;
+ t = GetWithPublicFields ();
+ t.RequiresPublicFields ();
+ }
+
+ [ExpectedWarning ("IL2067", "publicMethodsType", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ static IEnumerable<int> UseParameterBeforeYieldReturn ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type publicMethodsType = null)
+ {
+ publicMethodsType.RequiresAll ();
+ yield return 0;
+ }
+
+ [ExpectedWarning ("IL2067", "unknownType", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ static IEnumerable<int> UseUnannotatedParameterBeforeYieldReturn (Type unknownType = null)
+ {
+ unknownType.RequiresAll ();
+ yield return 0;
+ }
+
+ [ExpectedWarning ("IL2067", "publicMethodsType", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ static IEnumerable<int> FlowParameterAcrossYieldReturn ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type publicMethodsType = null)
+ {
+ yield return 0;
+ publicMethodsType.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2067", "unknownType", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ static IEnumerable<int> FlowUnannotatedParameterAcrossYieldReturn (Type unknownType = null)
+ {
+ yield return 0;
+ unknownType.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ // Linker includes backwards branches for hoisted locals, by virtue of tracking all assignments.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ static IEnumerable<int> FlowAcrossYieldReturnWithBackwardsBranch (int n = 0)
+ {
+ Type t = GetWithPublicMethods ();
+ for (int i = 0; i < n; i++) {
+ yield return 0;
+ t.RequiresAll ();
+ yield return 1;
+ t = GetWithPublicFields ();
+ }
+ }
+
+ public static void Test ()
+ {
+ FlowAcrossYieldReturn ();
+ NoFlowAcrossYieldReturn ();
+ NoFlowAcrossYieldReturn ();
+ UseParameterBeforeYieldReturn ();
+ UseUnannotatedParameterBeforeYieldReturn ();
+ FlowParameterAcrossYieldReturn ();
+ FlowUnannotatedParameterAcrossYieldReturn ();
+ FlowAcrossYieldReturnWithBackwardsBranch ();
+ }
+ }
+
+ class Async
+ {
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ CompilerGeneratedCode = true)]
+ static async void FlowAcrossAwait ()
+ {
+ Type t = GetWithPublicMethods ();
+ await MethodAsync ();
+ t.RequiresAll ();
+ }
+
+ // Linker tracks all assignments of hoisted locals, so this produces warnings.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields), CompilerGeneratedCode = true)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods), CompilerGeneratedCode = true)]
+ static async void NoFlowAcrossAwait ()
+ {
+ Type t = GetWithPublicMethods ();
+ t.RequiresPublicMethods ();
+ await MethodAsync ();
+ t = GetWithPublicFields ();
+ t.RequiresPublicFields ();
+ }
+
+ [ExpectedWarning ("IL2067", "publicMethodsType", nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true)]
+ static async void FlowParameterAcrossAwait ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type publicMethodsType = null)
+ {
+ await MethodAsync ();
+ publicMethodsType.RequiresAll ();
+ }
+
+ public static void Test ()
+ {
+ FlowAcrossAwait ();
+ NoFlowAcrossAwait ();
+ FlowParameterAcrossAwait ();
+ }
+ }
+
+ class AsyncIterator
+ {
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ static async IAsyncEnumerable<int> FlowAcrossAwaitAndYieldReturn ()
+ {
+ Type t = GetWithPublicMethods ();
+ await MethodAsync ();
+ yield return 0;
+ t.RequiresAll ();
+ }
+
+ public static void Test ()
+ {
+ FlowAcrossAwaitAndYieldReturn ();
+ }
+ }
+
+ class LocalFunction
+ {
+ static void WarningsInBody ()
+ {
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ static void LocalFunction ()
+ {
+ Type t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ }
+
+ LocalFunction ();
+ }
+
+ static void WarningsInBodyUnused ()
+ {
+ // Trimmer doesn't warn because this is unused code.
+ static void LocalFunction ()
+ {
+ Type t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ }
+ }
+
+ static void ReadCapturedVariable ()
+ {
+ Type t = GetWithPublicMethods ();
+ LocalFunction ();
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction ()
+ {
+ t.RequiresAll ();
+ }
+ }
+
+ static void ReadMergedCapturedVariable (bool b = false)
+ {
+ Type t;
+ if (b) {
+ t = GetWithPublicMethods ();
+ } else {
+ t = GetWithPublicFields ();
+ }
+
+ LocalFunction ();
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ static void ReadCapturedVariableInMultipleBranches (bool b = false)
+ {
+ Type t;
+ if (b) {
+ t = GetWithPublicMethods ();
+ LocalFunction ();
+ } else {
+ t = GetWithPublicFields ();
+ LocalFunction ();
+ }
+
+ LocalFunction ();
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ static void ReadCapturedVariableInMultipleBranchesDistinct (bool b = false)
+ {
+ Type t;
+ if (b) {
+ t = GetWithPublicMethods ();
+ LocalFunctionRequiresMethods ();
+ } else {
+ t = GetWithPublicFields ();
+ LocalFunctionRequiresFields ();
+ }
+
+ // We include all writes, including ones that can't reach the local function invocation.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresPublicFields),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunctionRequiresFields () => t.RequiresPublicFields ();
+ // We include all writes, including ones that can't reach the local function invocation.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresPublicMethods),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunctionRequiresMethods () => t.RequiresPublicMethods ();
+ }
+
+ static void ReadCapturedVariableWithBackwardsBranch (int i = 0)
+ {
+ Type t = GetWithPublicMethods ();
+ while (true) {
+ LocalFunction ();
+ if (i++ == 5)
+ break;
+ t = GetWithPublicFields ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ // Linker includes backwards branches for hoisted locals, by virtue of tracking all assignments.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ static void ReadCapturedVariableInMultipleFunctions ()
+ {
+ Type t = GetWithPublicMethods ();
+ LocalFunction ();
+
+ CallerOfLocalFunction ();
+
+ void CallerOfLocalFunction ()
+ {
+ t = GetWithPublicFields ();
+ LocalFunction ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ static void ReadCapturedVariableInCallGraphCycle ()
+ {
+ Type t = GetUnknownType ();
+ A ();
+
+ void A ()
+ {
+ t = GetWithPublicMethods ();
+ LocalFunction ();
+ B ();
+ }
+
+ void B ()
+ {
+ t = GetWithPublicFields ();
+ LocalFunction ();
+ A ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetUnknownType), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ public static void ReadCapturedParameter (Type tParameter)
+ {
+ LocalFunction ();
+
+ [ExpectedWarning ("IL2067", nameof (ReadCapturedParameter), "tParameter", nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => tParameter.RequiresAll ();
+ }
+
+ public static void ReadCapturedParameterAfterWrite (Type tParameter)
+ {
+ tParameter = GetWithPublicMethods ();
+ LocalFunction ();
+
+ [ExpectedWarning ("IL2067", "tParameter", nameof (DataFlowTypeExtensions.RequiresPublicMethods),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => tParameter.RequiresPublicMethods ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ // analyzer clears all local state, but trimmer doesn't
+ ProducedBy = ProducedBy.Trimmer)]
+ static void ReadCapturedVariableWithUnhoistedLocals ()
+ {
+ Type t = GetWithPublicMethods ();
+ Type notCaptured = GetWithPublicFields ();
+ LocalFunction ();
+ notCaptured.RequiresAll ();
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ // We include all writes, including ones that can't reach the local function invocation.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ static void WriteCapturedVariable ()
+ {
+ Type t = GetWithPublicFields ();
+ LocalFunction ();
+ t.RequiresAll ();
+
+ void LocalFunction () => t = GetWithPublicMethods ();
+ }
+
+ public static void Test ()
+ {
+ WarningsInBody ();
+ WarningsInBodyUnused ();
+ ReadCapturedVariable ();
+ ReadMergedCapturedVariable ();
+ ReadCapturedVariableInMultipleBranches ();
+ ReadCapturedVariableInMultipleBranchesDistinct ();
+ ReadCapturedVariableInMultipleFunctions ();
+ ReadCapturedVariableInCallGraphCycle ();
+ ReadCapturedVariableWithBackwardsBranch ();
+ ReadCapturedParameter (null);
+ ReadCapturedParameterAfterWrite (null);
+ ReadCapturedVariableWithUnhoistedLocals ();
+ WriteCapturedVariable ();
+ }
+ }
+
+ class Lambda
+ {
+ static void WarningsInBody ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => {
+ Type t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ };
+
+ lambda ();
+ }
+
+ static void WarningsInBodyUnused ()
+ {
+ var lambda =
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => {
+ Type t = GetWithPublicMethods ();
+ t.RequiresAll ();
+ };
+ }
+
+ static void ReadCapturedVariable ()
+ {
+ Type t = GetWithPublicMethods ();
+ Action lambda =
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => t.RequiresAll ();
+ lambda ();
+ }
+
+ static void ReadCapturedVariableAfterWriteAfterDefinition ()
+ {
+ Type t = GetWithPublicFields ();
+
+ Action lambda =
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => t.RequiresAll ();
+
+ t = GetWithPublicMethods ();
+ lambda ();
+ }
+
+ public static void ReadCapturedParameter (Type tParameter)
+ {
+ var lambda =
+ [ExpectedWarning ("IL2067", nameof (ReadCapturedParameter), "tParameter", nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => tParameter.RequiresAll ();
+
+ lambda ();
+ }
+
+ public static void ReadCapturedParameterAfterWrite (Type tParameter)
+ {
+ tParameter = GetWithPublicMethods ();
+ var lambda =
+ // We produce dataflow warnings for the unknown parameter even though it has been overwritten
+ // with a value that satisfies the requirement.
+ [ExpectedWarning ("IL2067", "tParameter", nameof (DataFlowTypeExtensions.RequiresPublicMethods),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => tParameter.RequiresPublicMethods ();
+ lambda ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ static void ReadCapturedVariableWithUnhoistedLocals ()
+ {
+ Type t = GetWithPublicMethods ();
+ Type notCaptured = GetWithPublicFields ();
+ Action lambda =
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ () => t.RequiresAll ();
+ lambda ();
+ notCaptured.RequiresAll ();
+ }
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ // We include all writes, including ones that can't reach the local function invocation.
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ static void WriteCapturedVariable ()
+ {
+ Type t = GetWithPublicFields ();
+ Action lambda = () => t = GetWithPublicMethods ();
+ lambda ();
+ t.RequiresAll ();
+ }
+
+ public static void Test ()
+ {
+ WarningsInBody ();
+ WarningsInBodyUnused ();
+ ReadCapturedVariable ();
+ ReadCapturedVariableAfterWriteAfterDefinition ();
+ ReadCapturedParameter (null);
+ ReadCapturedParameterAfterWrite (null);
+ ReadCapturedVariableWithUnhoistedLocals ();
+ WriteCapturedVariable ();
+ }
+ }
+
+ class Complex
+ {
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ // Linker merges branches going forward
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll), CompilerGeneratedCode = true,
+ ProducedBy = ProducedBy.Trimmer)]
+ static IEnumerable<int> IteratorWithLocalFunctions ()
+ {
+ Type t = GetWithPublicMethods ();
+ LocalFunction ();
+
+ yield return 0;
+
+ LocalFunction ();
+ t = GetWithPublicFields ();
+ LocalFunction ();
+ t.RequiresAll ();
+
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicMethods), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ [ExpectedWarning ("IL2072", nameof (GetWithPublicFields), nameof (DataFlowTypeExtensions.RequiresAll),
+ ProducedBy = ProducedBy.Trimmer)]
+ void LocalFunction () => t.RequiresAll ();
+ }
+
+ public static void Test ()
+ {
+ IteratorWithLocalFunctions ();
+ }
+ }
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)]
+ static Type GetAll () => null;
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
+ static Type GetWithPublicMethods () => null;
+
+ [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
+ static Type GetWithPublicFields () => null;
+
+ static Type GetUnknownType () => null;
+
+ static async Task<int> MethodAsync ()
+ {
+ return await Task.FromResult (0);
+ }
+
+ [RequiresUnreferencedCode ("RUC")]
+ static void RUCMethod () { }
+
+ struct TestStruct
+ {
+ [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
+ public Type TypeWithPublicFields => null;
+ }
+ }
+} \ No newline at end of file