From 6cf354afa1d33b4d5824866e3a5f1428b088e6bb Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 17 Jan 2023 18:22:46 -0600 Subject: [PATCH 1/2] LambdaExpression.CanCompileToIL should respect IsDynamicCodeSupported With the new feature switch added in https://github.com/dotnet/runtime/issues/39806, calling LambdaExpression.Compile is throwing a PlatformNotSupportedException. Instead, LambdaExpression should respect IsDynamicCodeSupported and switch to using the interpreter when IsDynamicCodeSupported is false. --- .../src/System/Linq/Expressions/LambdaExpression.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs index d8621b03cdd22..f4c2aa2f74baf 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs @@ -26,7 +26,7 @@ public abstract class LambdaExpression : Expression, IParameterProvider private readonly Expression _body; // This can be flipped to false using feature switches at publishing time - public static bool CanCompileToIL => true; + public static bool CanCompileToIL => RuntimeFeature.IsDynamicCodeSupported; // This could be flipped to false using feature switches at publishing time public static bool CanInterpret => true; @@ -154,7 +154,7 @@ public Delegate Compile() /// A delegate containing the compiled version of the lambda. public Delegate Compile(bool preferInterpretation) { - if (CanCompileToIL && CanInterpret && preferInterpretation) + if (CanInterpret && preferInterpretation) { return new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); } @@ -234,7 +234,7 @@ internal Expression(Expression body) /// A delegate containing the compiled version of the lambda. public new TDelegate Compile(bool preferInterpretation) { - if (CanCompileToIL && CanInterpret && preferInterpretation) + if (CanInterpret && preferInterpretation) { return (TDelegate)(object)new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); } From 807d807be29b736f6cdf965dd838e2069996a491 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 18 Jan 2023 12:29:39 -0600 Subject: [PATCH 2/2] Add tests --- .../tests/CompilerTests.cs | 24 +++++++++++++++++++ .../System.Linq.Expressions.Tests.csproj | 1 + 2 files changed, 25 insertions(+) diff --git a/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs b/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs index 069d72e6abcef..3c2f4bc6b5698 100644 --- a/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using System.Text.RegularExpressions; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Linq.Expressions.Tests @@ -429,6 +430,29 @@ private static void Verify_VariableBinder_CatchBlock_Filter(CatchBlock @catch) Assert.Throws(() => e.Compile()); } + + /// + /// Verifies that compiling and executing a lambda method works when IsDynamicCodeSupported == false. + /// + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void CompileWorksWhenDynamicCodeNotSupported() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", false.ToString()); + + using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(static () => + { + ParameterExpression param = Expression.Parameter(typeof(int)); + + Func typedDel = + Expression.Lambda>(Expression.Add(param, Expression.Constant(4)), param).Compile(); + Assert.Equal(304, typedDel(300)); + + Delegate del = + Expression.Lambda(Expression.Add(param, Expression.Constant(5)), param).Compile(); + Assert.Equal(305, del.DynamicInvoke(300)); + }, options); + } } public enum ConstantsEnum diff --git a/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj b/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj index 481d04cc820ac..97ead77d06810 100644 --- a/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj +++ b/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj @@ -1,6 +1,7 @@ $(NetCoreAppCurrent);$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst + true