Skip to content

Commit

Permalink
LambdaExpression.CanCompileToIL should respect IsDynamicCodeSupported (
Browse files Browse the repository at this point in the history
…dotnet#80759)

* LambdaExpression.CanCompileToIL should respect IsDynamicCodeSupported

With the new feature switch added in dotnet#39806, calling LambdaExpression.Compile is throwing a PlatformNotSupportedException. Instead, LambdaExpression should respect IsDynamicCodeSupported and switch to using the interpreter when IsDynamicCodeSupported is false.

* Add tests
  • Loading branch information
eerhardt authored and mdh1418 committed Jan 24, 2023
1 parent 6d1b552 commit 18fc239
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -154,7 +154,7 @@ public Delegate Compile()
/// <returns>A delegate containing the compiled version of the lambda.</returns>
public Delegate Compile(bool preferInterpretation)
{
if (CanCompileToIL && CanInterpret && preferInterpretation)
if (CanInterpret && preferInterpretation)
{
return new Interpreter.LightCompiler().CompileTop(this).CreateDelegate();
}
Expand Down Expand Up @@ -234,7 +234,7 @@ internal Expression(Expression body)
/// <returns>A delegate containing the compiled version of the lambda.</returns>
public new TDelegate Compile(bool preferInterpretation)
{
if (CanCompileToIL && CanInterpret && preferInterpretation)
if (CanInterpret && preferInterpretation)
{
return (TDelegate)(object)new Interpreter.LightCompiler().CompileTop(this).CreateDelegate();
}
Expand Down
24 changes: 24 additions & 0 deletions src/libraries/System.Linq.Expressions/tests/CompilerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Linq.Expressions.Tests
Expand Down Expand Up @@ -429,6 +430,29 @@ private static void Verify_VariableBinder_CatchBlock_Filter(CatchBlock @catch)

Assert.Throws<InvalidOperationException>(() => e.Compile());
}

/// <summary>
/// Verifies that compiling and executing a lambda method works when IsDynamicCodeSupported == false.
/// </summary>
[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<int, int> typedDel =
Expression.Lambda<Func<int, int>>(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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst</TargetFrameworks>
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 18fc239

Please sign in to comment.