diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs index 8150abeca61b1e..6a5e2ed77cdf08 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/CompilerGeneratedState.cs @@ -158,8 +158,10 @@ referencedMethod.OwningType is MetadataType generatedType && 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 @@ void MapGeneratedTypeTypeParameters( break; case ILOpcode.stsfld: + case ILOpcode.ldsfld: { if (body.GetObject(reader.ReadILToken()) is FieldDesc { OwningType: MetadataType owningType } && compilerGeneratedType == owningType.GetTypeDefinition()) diff --git a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs index 5f26219e22fdea..db0f9b2481f8e4 100644 --- a/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs +++ b/src/tools/illink/src/linker/Linker.Dataflow/CompilerGeneratedState.cs @@ -180,7 +180,8 @@ referencedMethod.DeclaringType is var generatedType && 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 @@ static void MapGeneratedTypeTypeParameters ( 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; diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedTypes.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedTypes.cs index c414bc252d1280..324e2cbb505f3a 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedTypes.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/CompilerGeneratedTypes.cs @@ -43,6 +43,7 @@ public static void Main () CapturingLocalFunctionInsideIterator (); LambdaInsideAsync (); LocalFunctionInsideAsync (); + NestedStaticLambda.Test (); } private static void UseIterator () @@ -352,5 +353,21 @@ void LocalFunction () await Task.Delay (0); LocalFunction (); } + + class NestedStaticLambda + { + public static class Container<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> { + public static Func, Func> NestedLambda = + (Func x) => v => x(v); + } + + [ExpectedWarning ("IL2091", "T", nameof (Container), nameof (DynamicallyAccessedMemberTypes.PublicMethods), + // https://github.com/dotnet/runtime/issues/84918 + ProducedBy = Tool.Trimmer | Tool.NativeAot)] + public static void Test () + { + Container.NestedLambda ((T t) => t) (default (T)); + } + } } }