diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs index a85e669a17a532..b81cddee9188c6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs @@ -46,11 +46,14 @@ public override IEnumerable GetStaticDependencies(NodeFacto var mdManager = (UsageBasedMetadataManager)factory.MetadataManager; if (_type.IsDelegate) { - // A delegate type metadata is rather useless without the Invoke method. - // If someone reflects on a delegate, chances are they're going to look at the signature. + // We've decided as a policy that delegate Invoke methods will be generated in full. + // The libraries (e.g. System.Linq.Expressions) have trimming warning suppressions + // in places where they assume IL-level trimming (where the method cannot be removed). + // We ask for a full reflectable method with its method body instead of just the + // metadata. var invokeMethod = _type.GetMethod("Invoke", null); if (!mdManager.IsReflectionBlocked(invokeMethod)) - dependencies.Add(factory.MethodMetadata(invokeMethod), "Delegate invoke method metadata"); + dependencies.Add(factory.ReflectableMethod(invokeMethod), "Delegate invoke method"); } if (_type.IsEnum) diff --git a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs index 78d1a6c0560c62..67894c9e5fb52e 100644 --- a/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs +++ b/src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs @@ -9,6 +9,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Linq.Expressions; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Reflection; @@ -31,6 +32,7 @@ private static int Main() TestVirtualDelegateTargets.Run(); TestRunClassConstructor.Run(); TestFieldMetadata.Run(); + TestLinqInvocation.Run(); #if !OPTIMIZED_MODE_WITHOUT_SCANNER TestContainment.Run(); TestInterfaceMethod.Run(); @@ -1859,6 +1861,19 @@ public static void Run() } } + class TestLinqInvocation + { + delegate void RunMeDelegate(); + + static void RunMe() { } + + public static void Run() + { + Expression> ex = (RunMeDelegate m) => m(); + ex.Compile()(RunMe); + } + } + class TestRunClassConstructor { static class TypeWithNoStaticFieldsButACCtor