diff options
Diffstat (limited to 'test/Mono.Linker.Tests.Cases/DataFlow')
-rw-r--r-- | test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeAccessedViaReflection.cs | 83 | ||||
-rw-r--r-- | test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedCodeDataflow.cs | 562 |
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 |