[release/8.0] Fix type parameter mapping logic in ILLink/ILCompiler (#92139)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sat, 16 Sep 2023 21:05:12 +0000 (14:05 -0700)
committerGitHub <noreply@github.com>
Sat, 16 Sep 2023 21:05:12 +0000 (14:05 -0700)
* Fix type parameter mapping bug in illink

* Same in ILCompiler

* Check dataflow of mapped type parameter

* Fix test for analyzer

---------

Co-authored-by: Sven Boemer <sbomer@gmail.com>
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs
src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs
src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedTypes.cs

index 8150abe..6a5e2ed 100644 (file)
@@ -158,8 +158,10 @@ namespace ILCompiler.Dataflow
                                     break;
 
                                 case ILOpcode.stsfld:
+                                case ILOpcode.ldsfld:
                                     {
                                         // Same as above, but stsfld instead of a call to the constructor
+                                        // Ldsfld may also trigger a cctor that creates a closure environment
                                         FieldDesc? field = methodBody.GetObject(reader.ReadILToken()) as FieldDesc;
                                         if (field == null)
                                             continue;
@@ -417,6 +419,7 @@ namespace ILCompiler.Dataflow
                                 break;
 
                             case ILOpcode.stsfld:
+                            case ILOpcode.ldsfld:
                                 {
                                     if (body.GetObject(reader.ReadILToken()) is FieldDesc { OwningType: MetadataType owningType }
                                         && compilerGeneratedType == owningType.GetTypeDefinition())
index 5f26219..db0f9b2 100644 (file)
@@ -180,7 +180,8 @@ namespace Mono.Linker.Dataflow
 
                                                case OperandType.InlineField: {
                                                                // Same as above, but stsfld instead of a call to the constructor
-                                                               if (instruction.OpCode.Code is not Code.Stsfld)
+                                                               // Ldsfld may also trigger a cctor that creates a closure environment
+                                                               if (instruction.OpCode.Code is not (Code.Stsfld or Code.Ldsfld))
                                                                        continue;
 
                                                                FieldDefinition? field = _context.TryResolve ((FieldReference) instruction.Operand);
@@ -390,7 +391,8 @@ namespace Mono.Linker.Dataflow
                                                        handled = true;
                                                }
                                                break;
-                                       case Code.Stsfld: {
+                                       case Code.Stsfld:
+                                       case Code.Ldsfld: {
                                                        if (instr.Operand is FieldReference { DeclaringType: GenericInstanceType typeRef }
                                                                && compilerGeneratedType == context.TryResolve (typeRef)) {
                                                                return typeRef;
index c414bc2..324e2cb 100644 (file)
@@ -43,6 +43,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
                        CapturingLocalFunctionInsideIterator<int> ();
                        LambdaInsideAsync<int> ();
                        LocalFunctionInsideAsync<int> ();
+                       NestedStaticLambda.Test<int> ();
                }
 
                private static void UseIterator ()
@@ -352,5 +353,21 @@ namespace Mono.Linker.Tests.Cases.DataFlow
                        await Task.Delay (0);
                        LocalFunction ();
                }
+
+               class NestedStaticLambda
+               {
+                       public static class Container<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> {
+                               public static Func<Func<T, T>, Func<T, T>> NestedLambda =
+                                       (Func<T, T> x) => v => x(v);
+                       }
+
+                       [ExpectedWarning ("IL2091", "T", nameof (Container<T>), nameof (DynamicallyAccessedMemberTypes.PublicMethods),
+                               // https://github.com/dotnet/runtime/issues/84918
+                               ProducedBy = Tool.Trimmer | Tool.NativeAot)]
+                       public static void Test<T> ()
+                       {
+                               Container<T>.NestedLambda ((T t) => t) (default (T));
+                       }
+               }
        }
 }