Add file-scoped class trimming test (#89640)
authorSven Boemer <sbomer@gmail.com>
Mon, 31 Jul 2023 16:17:11 +0000 (09:17 -0700)
committerGitHub <noreply@github.com>
Mon, 31 Jul 2023 16:17:11 +0000 (09:17 -0700)
Adds a testcase for file-scoped classes, including a case that
reproduced the crash from
https://github.com/dotnet/runtime/issues/89191 (before the fix
https://github.com/dotnet/runtime/pull/89327).

src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/DataFlowTests.cs
src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FileScopedClasses.cs [new file with mode: 0644]

index 3bf7964..3c5bb3c 100644 (file)
@@ -138,6 +138,12 @@ namespace ILLink.RoslynAnalyzer.Tests
                }
 
                [Fact]
+               public Task FileScopedClasses ()
+               {
+                       return RunTest ();
+               }
+
+               [Fact]
                public Task GenericParameterDataFlow ()
                {
                        return RunTest (nameof (GenericParameterDataFlow));
diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FileScopedClasses.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/FileScopedClasses.cs
new file mode 100644 (file)
index 0000000..6230321
--- /dev/null
@@ -0,0 +1,77 @@
+// 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.Diagnostics.CodeAnalysis;
+using System.Reflection;
+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
+{
+       [ExpectedNoWarnings]
+       class FileScopedClasses
+       {
+               static void Main() {
+                       BasicKeptValidation.Test ();
+                       BasicDataFlow.Test ();
+                       CompilerGeneratedCodeConsistency.Test ();
+               }
+       }
+
+       [ExpectedNoWarnings]
+       file class BasicKeptValidation
+       {
+               [Kept]
+               public static void Test () {
+                       KeptMethod ();
+               }
+
+               [Kept]
+               static void KeptMethod () { }
+
+               static void UnusedMethod () { }
+       }
+
+       [ExpectedNoWarnings]
+       file class BasicDataFlow
+       {
+               [Kept]
+               [ExpectedWarning ("IL2072")]
+               public static void Test () {
+                       RequirePublicFields (GetNone ());
+               }
+
+               [Kept]
+               static Type GetNone () => null;
+
+               [Kept]
+               static void RequirePublicFields ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type t) {}
+       }
+
+       [ExpectedNoWarnings]
+       file class CompilerGeneratedCodeConsistency
+       {
+               [Kept]
+               public static void Test () {
+                       TriggerDataflowAnalysis ();
+
+                       // Reference a lambda to hit the bug in https://github.com/dotnet/runtime/issues/89191.
+                       // The bug occurred when dataflow analysis was performed on a method in a file-scoped class,
+                       // where the method had references to lambdas.
+                       // This would produce an inconsistency between the set of methods tracked in the compiler-generated
+                       // state and the dataflow analysis. Dataflow analysis always sees the lambdas, but the
+                       // compiler-generated state handling treated file-scoped classes like compiler-generated
+                       // classes, and would not build a type cache of this class.
+                       var l =
+                               [Kept]
+                               static () => "hello";
+                       l();
+               }
+
+               [Kept]
+               [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
+               static Type TriggerDataflowAnalysis () => null;
+       }
+}