From ebb461a4f42afa9e4aaebbbdcc9119416611b7bb Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 28 Nov 2022 14:43:55 -0800 Subject: [PATCH] Add compiler-generated code tests for NativeAot (#77457) This adds the compiler-generated code tests from illink and enables them for NativeAot. Includes fixes in the test infrastructure required to make some of the tests pass. --- .../Mono.Linker.Tests.Cases.csproj | 1 + .../RequiresCapability/BasicRequires.cs | 7 +- .../RequiresInCompilerGeneratedCode.cs | 2284 +++++++++++++++++ .../RequiresInCompilerGeneratedCodeRelease.cs | 30 + .../TestCasesRunner/ResultChecker.cs | 21 +- .../TestCasesRunner/TestRunner.cs | 2 +- 6 files changed, 2327 insertions(+), 18 deletions(-) create mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs create mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCodeRelease.cs diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj index ec237817f2901f..1e6202665c685f 100644 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj +++ b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj @@ -8,6 +8,7 @@ $(DefineConstants);INCLUDE_EXPECTATIONS 0 0 + true diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs index b89dfc61e8cf3c..25275f426c56bc 100644 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs +++ b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs @@ -188,12 +188,9 @@ class GenericWithStaticMethod public static void GenericTypeWithStaticMethodWhichRequires () { } } - // NativeAOT doesnt produce Requires warnings in Generics https://github.com/dotnet/runtime/issues/68688 - // [ExpectedWarning("IL2026", "--GenericTypeWithStaticMethodWhichRequires--"] - [ExpectedWarning ("IL2026", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.Trimmer)] - // [ExpectedWarning("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer)] - // [ExpectedWarning("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] [ExpectedWarning ("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer)] public static void GenericTypeWithStaticMethodViaLdftn () { diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs new file mode 100644 index 00000000000000..f77d373825512c --- /dev/null +++ b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCode.cs @@ -0,0 +1,2284 @@ +// 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; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.RequiresCapability +{ + [SkipKeptItemsValidation] + [ExpectedNoWarnings] + public class RequiresInCompilerGeneratedCode + { + public static void Main () + { + WarnInIteratorBody.Test (); + SuppressInIteratorBody.Test (); + + WarnInAsyncBody.Test (); + SuppressInAsyncBody.Test (); + + WarnInAsyncIteratorBody.Test (); + SuppressInAsyncIteratorBody.Test (); + + WarnInLocalFunction.Test (); + SuppressInLocalFunction.Test (); + WarnInNonNestedLocalFunctionTest (); + SuppressInNonNestedLocalFunctionTest (); + + WarnInLambda.Test (); + SuppressInLambda.Test (); + + WarnInComplex.Test (); + SuppressInComplex.Test (); + + StateMachinesOnlyReferencedViaReflection.Test (); + LocalFunctionsReferencedViaReflection.Test (); + LambdasReferencedViaReflection.Test (); + + ComplexCases.AsyncBodyCallingMethodWithRequires.Test (); + ComplexCases.GenericAsyncBodyCallingMethodWithRequires.Test (); + ComplexCases.GenericAsyncEnumerableBodyCallingRequiresWithAnnotations.Test (); + } + + class WarnInIteratorBody + { + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static IEnumerable TestCallBeforeYieldReturn () + { + MethodWithRequires (); + yield return 0; + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static IEnumerable TestCallAfterYieldReturn () + { + yield return 0; + MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + static IEnumerable TestReflectionAccess () + { + yield return 0; + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + yield return 1; + } + +#if !RELEASE + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] +#else + // In release mode, the compiler optimizes away the unused Action (and reference to MethodWithRequires) +#endif + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + static IEnumerable TestLdftn () + { + yield return 0; + yield return 1; + var action = new Action (MethodWithRequires); + } + + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static IEnumerable TestLazyDelegate () + { + yield return 0; + yield return 1; + _ = _default.Value; + } + + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] + static IEnumerable TestDynamicallyAccessedMethod () + { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + yield return 0; + yield return 1; + } + + public static void Test () + { + TestCallBeforeYieldReturn (); + TestCallAfterYieldReturn (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + } + } + + class SuppressInIteratorBody + { + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestCall () + { + MethodWithRequires (); + yield return 0; + MethodWithRequires (); + yield return 1; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestReflectionAccess () + { + yield return 0; + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + yield return 1; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestLdftn () + { + yield return 0; + yield return 1; + var action = new Action (MethodWithRequires); + } + + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static IEnumerable TestLazyDelegate () + { + yield return 0; + yield return 1; + _ = _default.Value; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestDynamicallyAccessedMethod () + { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + yield return 0; + yield return 1; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestMethodParameterWithRequirements (Type unknownType = null) + { + unknownType.RequiresNonPublicMethods (); + yield return 0; + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestGenericMethodParameterRequirement () + { + MethodWithGenericWhichRequiresMethods (); + yield return 0; + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestGenericTypeParameterRequirement () + { + new TypeWithGenericWhichRequiresNonPublicFields (); + yield return 0; + } + + [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] + [UnconditionalSuppressMessage ("AOT", "IL3050")] + public static void Test () + { + TestCall (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + TestMethodParameterWithRequirements (); + TestGenericMethodParameterRequirement (); + TestGenericTypeParameterRequirement (); + } + } + + class WarnInAsyncBody + { + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static async void TestCallBeforeYieldReturn () + { + MethodWithRequires (); + await MethodAsync (); + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static async void TestCallAfterYieldReturn () + { + await MethodAsync (); + MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + static async void TestReflectionAccess () + { + await MethodAsync (); + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + await MethodAsync (); + } + +#if !RELEASE + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer)] +#endif + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + static async void TestLdftn () + { + await MethodAsync (); + var action = new Action (MethodWithRequires); + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static async void TestLazyDelegate () + { + await MethodAsync (); + _ = _default.Value; + } + + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] + static async void TestDynamicallyAccessedMethod () + { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + await MethodAsync (); + } + + public static void Test () + { + TestCallBeforeYieldReturn (); + TestCallAfterYieldReturn (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + } + } + + class SuppressInAsyncBody + { + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestCall () + { + MethodWithRequires (); + await MethodAsync (); + MethodWithRequires (); + await MethodAsync (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestReflectionAccess () + { + await MethodAsync (); + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + await MethodAsync (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestLdftn () + { + await MethodAsync (); + var action = new Action (MethodWithRequires); + } + + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static async void TestLazyDelegate () + { + await MethodAsync (); + _ = _default.Value; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestDynamicallyAccessedMethod () + { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + await MethodAsync (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestMethodParameterWithRequirements (Type unknownType = null) + { + unknownType.RequiresNonPublicMethods (); + await MethodAsync (); + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestGenericMethodParameterRequirement () + { + MethodWithGenericWhichRequiresMethods (); + await MethodAsync (); + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestGenericTypeParameterRequirement () + { + new TypeWithGenericWhichRequiresNonPublicFields (); + await MethodAsync (); + } + + [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] + [UnconditionalSuppressMessage ("AOT", "IL3050")] + public static void Test () + { + TestCall (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + TestMethodParameterWithRequirements (); + TestGenericMethodParameterRequirement (); + TestGenericTypeParameterRequirement (); + } + } + + class WarnInAsyncIteratorBody + { + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static async IAsyncEnumerable TestCallBeforeYieldReturn () + { + await MethodAsync (); + MethodWithRequires (); + yield return 0; + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static async IAsyncEnumerable TestCallAfterYieldReturn () + { + yield return 0; + MethodWithRequires (); + await MethodAsync (); + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + static async IAsyncEnumerable TestReflectionAccess () + { + yield return 0; + await MethodAsync (); + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + await MethodAsync (); + yield return 1; + } + +#if !RELEASE + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer, CompilerGeneratedCode = true)] +#endif + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + static async IAsyncEnumerable TestLdftn () + { + await MethodAsync (); + yield return 0; + var action = new Action (MethodWithRequires); + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static async IAsyncEnumerable TestLazyDelegate () + { + await MethodAsync (); + yield return 0; + _ = _default.Value; + } + + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] + static async IAsyncEnumerable TestDynamicallyAccessedMethod () + { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + yield return 0; + await MethodAsync (); + } + + public static void Test () + { + TestCallBeforeYieldReturn (); + TestCallAfterYieldReturn (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + } + } + + class SuppressInAsyncIteratorBody + { + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestCall () + { + MethodWithRequires (); + await MethodAsync (); + yield return 0; + MethodWithRequires (); + await MethodAsync (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestReflectionAccess () + { + await MethodAsync (); + yield return 0; + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + await MethodAsync (); + yield return 0; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestLdftn () + { + await MethodAsync (); + var action = new Action (MethodWithRequires); + yield return 0; + } + + // Cannot annotate fields either with RUC nor RAF therefore the warning persists + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static async IAsyncEnumerable TestLazyDelegate () + { + await MethodAsync (); + yield return 0; + _ = _default.Value; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestDynamicallyAccessedMethod () + { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + yield return 0; + await MethodAsync (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestMethodParameterWithRequirements (Type unknownType = null) + { + unknownType.RequiresNonPublicMethods (); + await MethodAsync (); + yield return 0; + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestGenericMethodParameterRequirement () + { + yield return 0; + MethodWithGenericWhichRequiresMethods (); + await MethodAsync (); + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async IAsyncEnumerable TestGenericTypeParameterRequirement () + { + new TypeWithGenericWhichRequiresNonPublicFields (); + yield return 0; + await MethodAsync (); + } + + [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] + [UnconditionalSuppressMessage ("AOT", "IL3050")] + public static void Test () + { + TestCall (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + TestMethodParameterWithRequirements (); + TestGenericMethodParameterRequirement (); + TestGenericTypeParameterRequirement (); + } + } + + class WarnInLocalFunction + { + static void TestCall () + { + LocalFunction (); + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + void LocalFunction () => MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", "--LocalFunctionWithRequires--")] + [ExpectedWarning ("IL3002", "--LocalFunctionWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--LocalFunctionWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestLocalFunctionWithRequires () + { + LocalFunction (); + + [RequiresUnreferencedCode ("--LocalFunctionWithRequires--")] + [RequiresAssemblyFiles ("--LocalFunctionWithRequires--")] + [RequiresDynamicCode ("--LocalFunctionWithRequires--")] + void LocalFunction () => MethodWithRequires (); + } + + static void TestCallUnused () + { + // Analyzer emits warnings for code in unused local functions. + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + void LocalFunction () => MethodWithRequires (); + } + + static void TestCallWithClosure (int p = 0) + { + LocalFunction (); + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + void LocalFunction () + { + p++; + MethodWithRequires (); + } + } + + static void TestCallWithClosureUnused (int p = 0) + { + // Analyzer emits warnings for code in unused local functions. + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + void LocalFunction () + { + p++; + MethodWithRequires (); + } + } + + static void TestReflectionAccess () + { + LocalFunction (); + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + void LocalFunction () => typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + } + + static void TestLdftn () + { + LocalFunction (); + +#if !RELEASE + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] +#endif + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + void LocalFunction () + { + var action = new Action (MethodWithRequires); + } + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + LocalFunction (); + + void LocalFunction () + { + _ = _default.Value; + } + } + + static void TestDynamicallyAccessedMethod () + { + LocalFunction (); + + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] + void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + } + + public static void Test () + { + TestCall (); + TestLocalFunctionWithRequires (); + TestCallUnused (); + TestCallWithClosure (); + TestCallWithClosureUnused (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + } + } + + class SuppressInLocalFunction + { + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCall () + { + LocalFunction (); + + void LocalFunction () => MethodWithRequires (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallFromNestedLocalFunction () + { + LocalFunction (); + + void LocalFunction () + { + NestedLocalFunction (); + + void NestedLocalFunction () => MethodWithRequires (); + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallWithClosure (int p = 0) + { + LocalFunction (); + + void LocalFunction () + { + p++; + MethodWithRequires (); + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestReflectionAccess () + { + LocalFunction (); + + void LocalFunction () => typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestLdftn () + { + LocalFunction (); + + void LocalFunction () + { + var action = new Action (MethodWithRequires); + } + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Message from --MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Message from --MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + LocalFunction (); + + void LocalFunction () + { + _ = _default.Value; + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestDynamicallyAccessedMethod () + { + LocalFunction (); + + void LocalFunction () => typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestMethodParameterWithRequirements (Type unknownType = null) + { + LocalFunction (); + + void LocalFunction () => unknownType.RequiresNonPublicMethods (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestGenericMethodParameterRequirement () + { + LocalFunction (); + + void LocalFunction () => MethodWithGenericWhichRequiresMethods (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestGenericTypeParameterRequirement () + { + LocalFunction (); + + void LocalFunction () => new TypeWithGenericWhichRequiresNonPublicFields (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestGenericLocalFunction () + { + LocalFunction (); + + void LocalFunction<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + typeof (T).RequiresPublicMethods (); + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestGenericLocalFunctionInner () + { + LocalFunction (); + + void LocalFunction () + { + typeof (TUnknown).RequiresPublicMethods (); + typeof (TSecond).RequiresPublicMethods (); + } + } + + static void TestGenericLocalFunctionWithAnnotations<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> () + { + LocalFunction (); + + void LocalFunction<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TInnerPublicMethods> () + { + typeof (TPublicMethods).RequiresPublicMethods (); + typeof (TInnerPublicMethods).RequiresPublicMethods (); + } + } + + static void TestGenericLocalFunctionWithAnnotationsAndClosure<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TPublicMethods> (int p = 0) + { + LocalFunction (); + + void LocalFunction<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TInnerPublicMethods> () + { + p++; + typeof (TPublicMethods).RequiresPublicMethods (); + typeof (TInnerPublicMethods).RequiresPublicMethods (); + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallMethodWithRequiresInLtftnLocalFunction () + { + var _ = new Action (LocalFunction); + + void LocalFunction () => MethodWithRequires (); + } + + class DynamicallyAccessedLocalFunction + { + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + public static void TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction () + { + typeof (DynamicallyAccessedLocalFunction).RequiresNonPublicMethods (); + + LocalFunction (); + + void LocalFunction () => MethodWithRequires (); + } + } + + class DynamicallyAccessedLocalFunctionUnusedShouldWarn + { + // https://github.com/dotnet/runtime/issues/68786 + [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 (DynamicallyAccessedLocalFunctionUnusedShouldSuppress).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, + // in a RUC scope. + void LocalFunction () => MethodWithRequires (); + } + } + + [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestSuppressionOnLocalFunction () + { + 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 (); + unknownType.RequiresNonPublicMethods (); + } + } + + [ExpectedWarning ("IL2026")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + 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 | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestSuppressionOnLocalFunctionWithNestedLocalFunction () + { + 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 () + { + NestedLocalFunction (); + + // The linker doesn't have enough information to associate the Requires on LocalFunction + // with this nested local function. + [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.NativeAot)] + void NestedLocalFunction () => MethodWithRequires (); + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestSuppressionOnOuterAndLocalFunction () + { + LocalFunction (); + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + void LocalFunction (Type unknownType = null) + { + MethodWithRequires (); + unknownType.RequiresNonPublicMethods (); + } + } + + class TestSuppressionOnOuterWithSameName + { + [ExpectedWarning ("IL2026", nameof (Outer) + "()")] + [ExpectedWarning ("IL3002", nameof (Outer) + "()", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", nameof (Outer) + "()", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + public static void Test () + { + Outer (); + Outer (0); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void Outer () + { + // Even though this method has the same name as Outer(int i), + // it should not suppress warnings originating from compiler-generated + // code for the lambda contained in Outer(int i). + } + + static void Outer (int i) + { + LocalFunction (); + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + void LocalFunction () => MethodWithRequires (); + } + } + + [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] + [UnconditionalSuppressMessage ("AOT", "IL3050")] + public static void Test () + { + TestCall (); + TestCallFromNestedLocalFunction (); + TestCallWithClosure (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestMethodParameterWithRequirements (); + TestDynamicallyAccessedMethod (); + TestGenericMethodParameterRequirement (); + TestGenericTypeParameterRequirement (); + TestGenericLocalFunction (); + TestGenericLocalFunctionInner (); + TestGenericLocalFunctionWithAnnotations (); + TestGenericLocalFunctionWithAnnotationsAndClosure (); + TestCallMethodWithRequiresInLtftnLocalFunction (); + DynamicallyAccessedLocalFunction.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction (); + DynamicallyAccessedLocalFunctionUnusedShouldWarn.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction (); + DynamicallyAccessedLocalFunctionUnusedShouldSuppress.TestCallMethodWithRequiresInDynamicallyAccessedLocalFunction (); + TestSuppressionOnLocalFunction (); + TestSuppressionOnLocalFunctionWithAssignment (); + TestSuppressionOnLocalFunctionWithNestedLocalFunction (); + TestSuppressionOnOuterAndLocalFunction (); + TestSuppressionOnOuterWithSameName.Test (); + } + } + + static void WarnInNonNestedLocalFunctionTest () + { + LocalFunction (); + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void LocalFunction () => MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", "--MethodWithNonNestedLocalFunction--")] + [ExpectedWarning ("IL3002", "--MethodWithNonNestedLocalFunction--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithNonNestedLocalFunction--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void SuppressInNonNestedLocalFunctionTest () + { + MethodWithNonNestedLocalFunction (); + } + + [RequiresUnreferencedCode ("--MethodWithNonNestedLocalFunction--")] + [RequiresAssemblyFiles ("--MethodWithNonNestedLocalFunction--")] + [RequiresDynamicCode ("--MethodWithNonNestedLocalFunction--")] + static void MethodWithNonNestedLocalFunction () + { + LocalFunction (); + + static void LocalFunction () => MethodWithRequires (); + } + + class WarnInLambda + { + static void TestCall () + { + Action lambda = + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + () => MethodWithRequires (); + + lambda (); + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--LambdaWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [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 _ = + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + () => MethodWithRequires (); + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--LambdaWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [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 = + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + () => { + p++; + MethodWithRequires (); + }; + + lambda (); + } + + static void TestCallWithClosureUnused (int p = 0) + { + Action _ = +#if !RELEASE + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.NativeAot)] +#endif + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + () => { + p++; + MethodWithRequires (); + }; + } + + static void TestReflectionAccess () + { + Action _ = + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + () => { + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + }; + } + + static void TestLdftn () + { + Action _ = +#if !RELEASE + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] +#endif + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer)] + () => { + var action = new Action (MethodWithRequires); + }; + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + Action _ = () => { + var action = _default.Value; + }; + } + + static void TestDynamicallyAccessedMethod () + { + Action _ = + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] + () => { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + }; + } + + public static void Test () + { + TestCall (); + TestCallUnused (); + TestLambdaWithRequires (); + TestLambdaWithRequiresUnused (); + TestCallWithClosure (); + TestCallWithClosureUnused (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + } + } + + class SuppressInLambda + { + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCall () + { + Action _ = + () => MethodWithRequires (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallFromNestedLambda () + { + Action lambda = () => { + Action nestedLambda = () => MethodWithRequires (); + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallWithReflectionAnalysisWarning () + { + // This should not produce warning because the Requires + Action _ = + (t) => t.RequiresPublicMethods (); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallWithClosure (int p = 0) + { + Action _ = + () => { + p++; + MethodWithRequires (); + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestReflectionAccess () + { + Action _ = + () => { + typeof (RequiresInCompilerGeneratedCode) + .GetMethod ("MethodWithRequires", System.Reflection.BindingFlags.NonPublic) + .Invoke (null, new object[] { }); + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestLdftn () + { + Action _ = + () => { + var action = new Action (MethodWithRequires); + }; + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--MethodWithRequiresAndReturns--", CompilerGeneratedCode = true, ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--MethodWithRequiresAndReturns--", ProducedBy = ProducedBy.Analyzer)] + public static Lazy _default = new Lazy (MethodWithRequiresAndReturns); + + static void TestLazyDelegate () + { + Action _ = () => { + var action = _default.Value; + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestDynamicallyAccessedMethod () + { + Action _ = + () => { + typeof (TypeWithMethodWithRequires).RequiresNonPublicMethods (); + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestMethodParameterWithRequirements (Type unknownType = null) + { + Action _ = + () => unknownType.RequiresNonPublicMethods (); + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestGenericMethodParameterRequirement () + { + Action _ = + () => { + MethodWithGenericWhichRequiresMethods (); + }; + } + + // https://github.com/dotnet/runtime/issues/68688 + // This test passes on NativeAot even without the Requires* attributes. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestGenericTypeParameterRequirement () + { + Action _ = () => { + new TypeWithGenericWhichRequiresNonPublicFields (); + }; + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)] + static void TestSuppressionOnLambda () + { + var lambda = + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + () => MethodWithRequires (); + + lambda (); // This will produce a warning since the lambda has Requires on it + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer)] + static void TestSuppressionOnLambdaWithNestedLambda () + { + var lambda = + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + () => { + // The linker doesn't try to associate the Requires on lambda with this nested + // lambda. It would be possible to do this because the declaration site will contain + // an IL reference to the generated lambda method, unlike local functions. + // However, we don't make this association, for consistency with local functions. + var nestedLambda = + [ExpectedWarning ("IL2026", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.NativeAot)] + () => MethodWithRequires (); + }; + + lambda (); // This will produce a warning since the lambda has Requires on it + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestSuppressionOnOuterAndLambda () + { + var lambda = + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + (Type unknownType) => { + MethodWithRequires (); + unknownType.RequiresNonPublicMethods (); + }; + + lambda (null); + } + + class TestSuppressionOnOuterWithSameName + { + [ExpectedWarning ("IL2026", nameof (Outer) + "()")] + [ExpectedWarning ("IL3002", nameof (Outer) + "()", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", nameof (Outer) + "()", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + public static void Test () + { + Outer (); + Outer (0); + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void Outer () + { + // Even though this method has the same name as Outer(int i), + // it should not suppress warnings originating from compiler-generated + // code for the lambda contained in Outer(int i). + } + + static void Outer (int i) + { + var lambda = + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + () => MethodWithRequires (); + + lambda (); + } + } + + + [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] + [UnconditionalSuppressMessage ("AOT", "IL3050")] + public static void Test () + { + TestCall (); + TestCallFromNestedLambda (); + TestCallWithReflectionAnalysisWarning (); + TestCallWithClosure (); + TestReflectionAccess (); + TestLdftn (); + TestLazyDelegate (); + TestDynamicallyAccessedMethod (); + TestMethodParameterWithRequirements (); + TestGenericMethodParameterRequirement (); + TestGenericTypeParameterRequirement (); + TestSuppressionOnLambda (); + TestSuppressionOnLambdaWithNestedLambda (); + TestSuppressionOnOuterAndLambda (); + TestSuppressionOnOuterWithSameName.Test (); + } + } + + class WarnInComplex + { + static async void TestIteratorLocalFunctionInAsync () + { + await MethodAsync (); + LocalFunction (); + await MethodAsync (); + + [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + IEnumerable LocalFunction () + { + yield return 0; + MethodWithRequires (); + yield return 1; + } + } + +#if !NATIVEAOT + // BUG: https://github.com/dotnet/runtime/issues/77455 + // NativeAot produces an incorrect warning pointing to the InstantiatedMethod, which isn't associated + // with the calling context. + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] + static IEnumerable TestDynamicallyAccessedMethodViaGenericMethodParameterInIterator () + { + yield return 1; + MethodWithGenericWhichRequiresMethods (); + } + + [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--", CompilerGeneratedCode = true)] + static IEnumerable TestDynamicallyAccessedMethodViaGenericTypeParameterInIterator () + { + yield return 1; + new TypeWithGenericWhichRequiresMethods (); + } +#endif + + static void TestLocalFunctionInIteratorLocalFunction () + { + IteratorLocalFunction (); + + IEnumerable IteratorLocalFunction () + { + yield return 0; + LocalFunction (); + yield return 1; + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + void LocalFunction () => MethodWithRequires (); + } + } + + static void TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod () + { + IteratorLocalFunction (); + + IEnumerable IteratorLocalFunction () + { + yield return 0; + LocalFunction (); + yield return 1; + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + void LocalFunction () => MethodWithRequires (); + } + + public static void Test () + { + TestIteratorLocalFunctionInAsync (); +#if !NATIVEAOT + TestDynamicallyAccessedMethodViaGenericMethodParameterInIterator (); + TestDynamicallyAccessedMethodViaGenericTypeParameterInIterator (); +#endif + TestLocalFunctionInIteratorLocalFunction (); + TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod (); + } + } + + class SuppressInComplex + { + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestIteratorLocalFunction () + { + LocalFunction (); + + IEnumerable LocalFunction () + { + yield return 0; + MethodWithRequires (); + yield return 1; + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestAsyncLocalFunction () + { + LocalFunction (); + + async Task LocalFunction () + { + await MethodAsync (); + MethodWithRequires (); + return 1; + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestIteratorLocalFunctionWithClosure (int p = 0) + { + LocalFunction (); + + IEnumerable LocalFunction () + { + p++; + yield return 0; + MethodWithRequires (); + yield return 1; + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestAsyncLocalFunctionWithClosure (int p = 0) + { + LocalFunction (); + + async Task LocalFunction () + { + p++; + await MethodAsync (); + MethodWithRequires (); + return 1; + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestCallToLocalFunctionInIteratorLocalFunctionWithClosure (int p = 0) + { + LocalFunction (); + + IEnumerable LocalFunction () + { + p++; + yield return 0; + LocalFunction2 (); + yield return 1; + + void LocalFunction2 () + { + MethodWithRequires (); + } + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestAsyncLambda () + { + Func> _ = async Task () => { + await MethodAsync (); + MethodWithRequires (); + return 1; + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestAsyncLambdaWithClosure (int p = 0) + { + Func> _ = async Task () => { + p++; + await MethodAsync (); + MethodWithRequires (); + return 1; + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static void TestLambdaInAsyncLambdaWithClosure (int p = 0) + { + Func> _ = async Task () => { + p++; + await MethodAsync (); + var lambda = () => MethodWithRequires (); + return 1; + }; + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestIteratorLocalFunctionInAsync () + { + await MethodAsync (); + LocalFunction (); + await MethodAsync (); + + [RequiresUnreferencedCode ("Suppress in local function")] + [RequiresAssemblyFiles ("Suppress in local function")] + [RequiresDynamicCode ("Suppress in local function")] + IEnumerable LocalFunction () + { + yield return 0; + MethodWithRequires (); + yield return 1; + } + } + + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static async void TestIteratorLocalFunctionInAsyncWithoutInner () + { + await MethodAsync (); + LocalFunction (); + await MethodAsync (); + + IEnumerable LocalFunction () + { + yield return 0; + MethodWithRequires (); + yield return 1; + } + } + +#if !NATIVEAOT + // BUG: https://github.com/dotnet/runtime/issues/77455 + // NativeAot produces an incorrect warning pointing to the InstantiatedMethod, which isn't associated + // with the calling context. + [RequiresUnreferencedCode ("Suppress in body")] + [RequiresAssemblyFiles ("Suppress in body")] + [RequiresDynamicCode ("Suppress in body")] + static IEnumerable TestDynamicallyAccessedMethodViaGenericMethodParameterInIterator () + { + MethodWithGenericWhichRequiresMethods (); + yield return 0; + } +#endif + + [ExpectedWarning ("IL2026", "--IteratorLocalFunction--")] + [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestLocalFunctionInIteratorLocalFunction () + { + IteratorLocalFunction (); + + [RequiresUnreferencedCode ("--IteratorLocalFunction--")] + [RequiresAssemblyFiles ("--IteratorLocalFunction--")] + [RequiresDynamicCode ("--IteratorLocalFunction--")] + IEnumerable IteratorLocalFunction () + { + yield return 0; + LocalFunction (); + MethodWithRequires (); + yield return 1; + + // Trimmer doesn't try to associate LocalFunction with IteratorLocalFunction + [ExpectedWarning ("IL2026", "--MethodWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.NativeAot)] + void LocalFunction () => MethodWithRequires (); + } + } + + [ExpectedWarning ("IL2026", "--IteratorLocalFunction--")] + [ExpectedWarning ("IL3002", "--IteratorLocalFunction--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--IteratorLocalFunction--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod () + { + IteratorLocalFunction (); + LocalFunction (); + + [RequiresUnreferencedCode ("--IteratorLocalFunction--")] + [RequiresAssemblyFiles ("--IteratorLocalFunction--")] + [RequiresDynamicCode ("--IteratorLocalFunction--")] + IEnumerable IteratorLocalFunction () + { + yield return 0; + LocalFunction (); + MethodWithRequires (); + yield return 1; + } + + [ExpectedWarning ("IL2026", "--MethodWithRequires--")] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + void LocalFunction () => MethodWithRequires (); + } + + [UnconditionalSuppressMessage ("Trimming", "IL2026")] + [UnconditionalSuppressMessage ("SingleFile", "IL3002")] + [UnconditionalSuppressMessage ("AOT", "IL3050")] + public static void Test () + { + TestIteratorLocalFunction (); + TestAsyncLocalFunction (); + TestIteratorLocalFunctionWithClosure (); + TestAsyncLocalFunctionWithClosure (); + TestCallToLocalFunctionInIteratorLocalFunctionWithClosure (); + TestAsyncLambda (); + TestAsyncLambdaWithClosure (); + TestLambdaInAsyncLambdaWithClosure (); + TestIteratorLocalFunctionInAsync (); + TestIteratorLocalFunctionInAsyncWithoutInner (); +#if !NATIVEAOT + TestDynamicallyAccessedMethodViaGenericMethodParameterInIterator (); +#endif + TestLocalFunctionInIteratorLocalFunction (); + TestLocalFunctionCalledFromIteratorLocalFunctionAndMethod (); + } + } + + class StateMachinesOnlyReferencedViaReflection + { + [RequiresUnreferencedCode ("--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] + [RequiresAssemblyFiles ("--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] + [RequiresDynamicCode ("--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] + static IEnumerable TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress () + { + yield return 0; + MethodWithRequires (); + } + + [RequiresUnreferencedCode ("--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] + [RequiresAssemblyFiles ("--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] + [RequiresDynamicCode ("--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] + static async void TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress () + { + await MethodAsync (); + MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static IEnumerable TestIteratorOnlyReferencedViaReflectionWhichShouldWarn () + { + yield return 0; + MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3002", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot, CompilerGeneratedCode = true)] + static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () + { + await MethodAsync (); + MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] + [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] + // Analyzer doesn't emit additional warnings about reflection access to the compiler-generated + // state machine members. + [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = ProducedBy.Trimmer)] +#if !RELEASE + [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = ProducedBy.Trimmer)] + // In debug mode, the async state machine is a class with a constructor, so a warning is emitted for the constructor. + // The MoveNext method is virtual, so doesn't warn either way. +#else + // In release mode, the async state machine is a struct which doesn't have a constructor, so no warning is emitted. +#endif + // Linker warns about reflection access to compiler-generated state machine members. + // https://github.com/dotnet/runtime/issues/68786 + [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 (); + } + + [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--")] + [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] + // NonPublicMethods doesn't warn for members emitted into compiler-generated state machine types. + static void TestNonPublicMethods () + { + typeof (StateMachinesOnlyReferencedViaReflection).RequiresNonPublicMethods (); + } + + public static void Test () + { + TestAll (); + TestNonPublicMethods (); + } + } + + class LocalFunctionsReferencedViaReflection + { + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--")] + [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestLocalFunctionWithRequires () + { + LocalFunction (); + + [RequiresUnreferencedCode ("--TestLocalFunctionWithRequires--")] + [RequiresAssemblyFiles ("--TestLocalFunctionWithRequires--")] + [RequiresDynamicCode ("--TestLocalFunctionWithRequires--")] + void LocalFunction () => MethodWithRequires (); + } + + static void TestLocalFunctionWithRequiresOnlyAccessedViaReflection () + { + [RequiresUnreferencedCode ("--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--")] + [RequiresAssemblyFiles ("--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--")] + [RequiresDynamicCode ("--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--")] + void LocalFunction () => MethodWithRequires (); + } + + [ExpectedWarning ("IL2026", "LocalFunction")] + [ExpectedWarning ("IL3002", "LocalFunction", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "LocalFunction", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + static void TestLocalFunctionWithClosureWithRequires (int p = 0) + { + LocalFunction (); + + [RequiresUnreferencedCode ("--TestLocalFunctionWithClosureWithRequires--")] + [RequiresAssemblyFiles ("--TestLocalFunctionWithClosureWithRequires--")] + [RequiresDynamicCode ("--TestLocalFunctionWithClosureWithRequires--")] + void LocalFunction () + { + p++; + MethodWithRequires (); + } + } + + [RequiresUnreferencedCode ("--TestLocalFunctionInMethodWithRequires--")] + [RequiresAssemblyFiles ("--TestLocalFunctionInMethodWithRequires--")] + [RequiresDynamicCode ("--TestLocalFunctionInMethodWithRequires--")] + static void TestLocalFunctionInMethodWithRequires () + { + LocalFunction (); + + 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--")] + static void TestLocalFunctionWithClosureInMethodWithRequires (int p = 0) + { + LocalFunction (); + + void LocalFunction () + { + p++; + MethodWithRequires (); + } + } + + // 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 | ProducedBy.NativeAot)] + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + // BUG: https://github.com/dotnet/runtime/issues/68786 + // NativeAot doesn't associate Requires on method with the local functions it contains. + [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] + // Linker warns about reflection access to compiler-generated code + // https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), + ProducedBy = ProducedBy.Trimmer)] + static void TestAll () + { + typeof (LocalFunctionsReferencedViaReflection).RequiresAll (); + } + + // 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 | ProducedBy.NativeAot)] + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + // BUG: https://github.com/dotnet/runtime/issues/68786 + // NativeAot doesn't associate Requires on method with the local functions it contains. + [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] + // Linker warns about reflection access to compiler-generated code + // https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", + ProducedBy = ProducedBy.Trimmer)] + static void TestNonPublicMethods () + { + typeof (LocalFunctionsReferencedViaReflection).RequiresNonPublicMethods (); + } + + public static void Test () + { + TestAll (); + TestNonPublicMethods (); + } + } + + class LambdasReferencedViaReflection + { + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "--TestLambdaWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", ProducedBy = ProducedBy.Analyzer)] + static void TestLambdaWithRequires () + { + var lambda = + [RequiresUnreferencedCode ("--TestLambdaWithRequires--")] + [RequiresAssemblyFiles ("--TestLambdaWithRequires--")] + [RequiresDynamicCode ("--TestLambdaWithRequires--")] + () => MethodWithRequires (); + + lambda (); + } + + // NativeAot is missing ldftn detection: https://github.com/dotnet/runtime/issues/68786 + [ExpectedWarning ("IL2026", "Lambda", ProducedBy = ProducedBy.Trimmer | ProducedBy.Analyzer)] + [ExpectedWarning ("IL3002", "Lambda", ProducedBy = ProducedBy.Analyzer)] + [ExpectedWarning ("IL3050", "Lambda", ProducedBy = ProducedBy.Analyzer)] + static void TestLambdaWithClosureWithRequires (int p = 0) + { + var lambda = + [RequiresUnreferencedCode ("--TestLambdaWithClosureWithRequires--")] + [RequiresAssemblyFiles ("--TestLambdaWithClosureWithRequires--")] + [RequiresDynamicCode ("--TestLambdaWithClosureWithRequires--")] + () => { + p++; + MethodWithRequires (); + }; + + lambda (); + } + + [RequiresUnreferencedCode ("--TestLambdaInMethodWithRequires--")] + [RequiresAssemblyFiles ("--TestLambdaInMethodWithRequires--")] + [RequiresDynamicCode ("--TestLambdaInMethodWithRequires--")] + static void TestLambdaInMethodWithRequires () + { + var lambda = () => MethodWithRequires (); + + lambda (); + } + + [RequiresUnreferencedCode ("--TestLambdaWithClosureInMethodWithRequires--")] + [RequiresAssemblyFiles ("--TestLambdaWithClosureInMethodWithRequires--")] + [RequiresDynamicCode ("--TestLambdaWithClosureInMethodWithRequires--")] + static void TestLambdaWithClosureInMethodWithRequires (int p = 0) + { + var lambda = () => { + p++; + MethodWithRequires (); + }; + + lambda (); + } + + // Warnings for Reflection access to methods with Requires + [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--")] + [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] + // The linker correctly emits warnings about reflection access to lambdas with Requires + // or which inherit Requires from the containing method. The analyzer doesn't bind to lambdas + // so does not warn here. + [ExpectedWarning ("IL2026", "--TestLambdaWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL2026", "--TestLambdaWithClosureWithRequires--", ProducedBy = ProducedBy.Trimmer | ProducedBy.NativeAot)] + // BUG: https://github.com/dotnet/runtime/issues/68786 + // NativeAot doesn't associate Requires on method with the lambdas it contains. + [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] + [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = ProducedBy.Trimmer)] + static void TestAll () + { + typeof (LambdasReferencedViaReflection).RequiresAll (); + } + + // Warnings for Reflection access to methods with Requires + [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--")] + [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] + // NonPublicMethods doesn't warn for lambdas emitted into display class types. + static void TestNonPublicMethods () + { + typeof (LambdasReferencedViaReflection).RequiresNonPublicMethods (); + } + + public static void Test () + { + TestAll (); + TestNonPublicMethods (); + } + } + + class ComplexCases + { + public class AsyncBodyCallingMethodWithRequires + { + [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] + [RequiresDynamicCode ("")] + static Task MethodWithRequiresAsync (Type type) + { + return Task.FromResult (new object ()); + } + + [RequiresUnreferencedCode ("ParentSuppression")] + [RequiresAssemblyFiles ("ParentSuppression")] + [RequiresDynamicCode ("ParentSuppression")] + static async Task AsyncMethodCallingRequires (Type type) + { + using (var diposable = await GetDisposableAsync ()) { + return await MethodWithRequiresAsync (type); + } + } + + [ExpectedWarning ("IL2026", "ParentSuppression")] + [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + public static void Test () + { + AsyncMethodCallingRequires (typeof (object)); + } + } + + public class GenericAsyncBodyCallingMethodWithRequires + { + [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] + [RequiresDynamicCode ("")] + static ValueTask MethodWithRequiresAsync () + { + return ValueTask.FromResult (default (TValue)); + } + + [RequiresUnreferencedCode ("ParentSuppression")] + [RequiresAssemblyFiles ("ParentSuppression")] + [RequiresDynamicCode ("ParentSuppression")] + static async Task AsyncMethodCallingRequires () + { + using (var disposable = await GetDisposableAsync ()) { + return await MethodWithRequiresAsync (); + } + } + + [ExpectedWarning ("IL2026", "ParentSuppression")] + [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + public static void Test () + { + AsyncMethodCallingRequires (); + } + } + + public class GenericAsyncEnumerableBodyCallingRequiresWithAnnotations + { + class RequiresOnCtor + { + [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles ("")] + [RequiresDynamicCode ("")] + public RequiresOnCtor () + { + } + } + + [RequiresUnreferencedCode ("ParentSuppression")] + [RequiresAssemblyFiles ("ParentSuppression")] + [RequiresDynamicCode ("ParentSuppression")] + static IAsyncEnumerable AsyncEnumMethodCallingRequires< + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] TValue> () + { + return CreateAsync (); + + [RequiresUnreferencedCode ("")] + [RequiresAssemblyFiles] + [RequiresDynamicCode ("")] + static async IAsyncEnumerable CreateAsync () + { + await MethodAsync (); + new RequiresOnCtor (); + yield return default (TValue); + } + } + + [ExpectedWarning ("IL2026", "ParentSuppression")] + [ExpectedWarning ("IL3002", "ParentSuppression", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + [ExpectedWarning ("IL3050", "ParentSuppression", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] + public static void Test () + { + AsyncEnumMethodCallingRequires (); + } + } + + class Disposable : IDisposable { public void Dispose () { } } + + static Task GetDisposableAsync () { return Task.FromResult (new Disposable ()); } + } + + static async Task MethodAsync () + { + return await Task.FromResult (0); + } + + [RequiresUnreferencedCode ("--MethodWithRequires--")] + [RequiresAssemblyFiles ("--MethodWithRequires--")] + [RequiresDynamicCode ("--MethodWithRequires--")] + static void MethodWithRequires () + { + } + + class TypeWithMethodWithRequires + { + [RequiresUnreferencedCode ("--TypeWithMethodWithRequires.MethodWithRequires--")] + [RequiresAssemblyFiles ("--TypeWithMethodWithRequires.MethodWithRequires--")] + [RequiresDynamicCode ("--TypeWithMethodWithRequires.MethodWithRequires--")] + static void MethodWithRequires () + { + } + } + + [RequiresUnreferencedCode ("Message from --MethodWithRequiresAndReturns--")] + [RequiresAssemblyFiles ("Message from --MethodWithRequiresAndReturns--")] + [RequiresDynamicCode ("Message from --MethodWithRequiresAndReturns--")] + public static string MethodWithRequiresAndReturns () + { + return "string"; + } + + static void MethodWithGenericWhichRequiresMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] T> () + { + } + + class TypeWithGenericWhichRequiresMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] T> + { + } + + class TypeWithGenericWhichRequiresNonPublicFields<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicFields)] T> { } + + class TestType { } + } +} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCodeRelease.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCodeRelease.cs new file mode 100644 index 00000000000000..a5f79c8c08f2d1 --- /dev/null +++ b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/RequiresInCompilerGeneratedCodeRelease.cs @@ -0,0 +1,30 @@ +// 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.Reflection; +using System.Threading.Tasks; +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; + +namespace Mono.Linker.Tests.Cases.RequiresCapability +{ + [ExpectedNoWarnings] + [SkipKeptItemsValidation] + [SetupCompileArgument ("/optimize+")] + [Define ("RELEASE")] + [SetupCompileArgument ("/main:Mono.Linker.Tests.Cases.RequiresCapability.RequiresInCompilerGeneratedCodeRelease")] + [SandboxDependency ("RequiresInCompilerGeneratedCode.cs")] + class RequiresInCompilerGeneratedCodeRelease + { + // This test just links the RequiresIncompilerGeneratedCode test in the Release configuration, to test + // with optimizations enabled for closures and state machine types. + // Sometimes the compiler optimizes away unused references to lambdas. + public static void Main () + { + RequiresInCompilerGeneratedCode.Main (); + } + } +} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs index e09966f22d45c1..89cfe820172811 100644 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs @@ -102,8 +102,6 @@ private void VerifyLoggedMessages (AssemblyDefinition original, TestLogWriter lo List loggedMessages = logger.GetLoggedMessages (); List<(IMemberDefinition, CustomAttribute)> expectedNoWarningsAttributes = new List<(IMemberDefinition, CustomAttribute)> (); foreach (var attrProvider in GetAttributeProviders (original)) { - if (attrProvider.ToString () is string mystring && mystring.Contains ("RequiresInCompilerGeneratedCode/SuppressInLambda")) - Debug.WriteLine ("Print"); foreach (var attr in attrProvider.CustomAttributes) { if (!IsProducedByNativeAOT (attr)) continue; @@ -159,10 +157,6 @@ private void VerifyLoggedMessages (AssemblyDefinition original, TestLogWriter lo bool expectedWarningFound = false; foreach (var loggedMessage in loggedMessages) { - if (loggedMessage.ToString ().Contains ("RequiresInCompilerGeneratedCode.SuppressInLambda")) { - Debug.WriteLine ("Print 2"); - } - if (loggedMessage.Category != MessageCategory.Warning || loggedMessage.Code != expectedWarningCodeNumber) continue; @@ -213,21 +207,23 @@ private void VerifyLoggedMessages (AssemblyDefinition original, TestLogWriter lo if (attrProvider is not IMemberDefinition expectedMember) continue; - string actualName = methodDesc.OwningType.ToString ().Replace ("+", ".") + "." + methodDesc.Name; - if (actualName.Contains (expectedMember.DeclaringType.FullName.Replace ("/", ".")) && - actualName.Contains ("<" + expectedMember.Name + ">")) { + string? actualName = GetActualOriginDisplayName (methodDesc); + string expectedTypeName = ConvertSignatureToIlcFormat (GetExpectedOriginDisplayName (expectedMember.DeclaringType)); + if (actualName?.Contains (expectedTypeName) == true && + actualName?.Contains ("<" + expectedMember.Name + ">") == true) { expectedWarningFound = true; loggedMessages.Remove (loggedMessage); break; } - if (actualName.StartsWith (expectedMember.DeclaringType.FullName) && - actualName.Contains (".cctor") && (expectedMember is FieldDefinition || expectedMember is PropertyDefinition)) { + if (actualName?.StartsWith (expectedTypeName) == true && + actualName?.Contains (".cctor") == true && + (expectedMember is FieldDefinition || expectedMember is PropertyDefinition)) { expectedWarningFound = true; loggedMessages.Remove (loggedMessage); break; } if (methodDesc.Name == ".ctor" && - methodDesc.OwningType.ToString () == expectedMember.FullName) { + methodDesc.OwningType.ToString () == expectedMember.FullName) { expectedWarningFound = true; loggedMessages.Remove (loggedMessage); break; @@ -359,6 +355,7 @@ static string GetExpectedOriginDisplayName (ICustomAttributeProvider provider) = provider switch { MethodDefinition method => method.GetDisplayName (), FieldDefinition field => field.GetDisplayName (), + TypeDefinition type => type.GetDisplayName (), IMemberDefinition member => member.FullName, AssemblyDefinition asm => asm.Name.Name, _ => throw new NotImplementedException () diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs index 4617c3f6c9ec1f..6911201b8581a9 100644 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs +++ b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.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;