Open
Description
Description
When a method (e. g. ToString
or GetHashCode
) is called on a lambda expression compiled in the interpretation mode, the lambda gets invoked for some reason.
Reproduction Steps
using System.Linq.Expressions;
// build () => { Console.WriteLine("Test"); return Task.CompletedTask; }
var consoleWriteLine = typeof(Console).GetMethod(nameof(Console.WriteLine), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, new[] { typeof(string) });
var returnTarget = Expression.Label(typeof(Task));
var innerBody = Expression.Block(typeof(Task),
Expression.Call(consoleWriteLine, Expression.Constant("Test")),
Expression.Return(returnTarget, Expression.Constant(Task.CompletedTask)),
Expression.Label(returnTarget, Expression.Constant(null, typeof(Task)))
);
var innerLambda = Expression.Lambda<Func<Task>>(innerBody);
// call .ToString() on this lambda
var toStringMethod = typeof(Func<Task>).GetMethod("ToString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, new Type[] { });
var outerBody = Expression.Call(innerLambda, toStringMethod);
var outerLambda = Expression.Lambda<Action>(outerBody);
var compiled1 = outerLambda.Compile(preferInterpretation: false);
Console.WriteLine("Compiled");
compiled1(); // CORRECT: does not write anything on the console
Console.WriteLine();
Console.WriteLine();
var compiled2 = outerLambda.Compile(preferInterpretation: true);
Console.WriteLine("Interpreted");
compiled2(); // INCORRECT: invokes the lambda
Expected behavior
In both modes, calling a method on innerLambda
should not invoke it.
Actual behavior
When preferInterpretation
is true
, the lambda gets invoked.
Furthermore, if the lambda is of type Action
, I am getting IndexOutOfRangeException
.
Regression?
I was able to reproduce the issue on all versions of .NET Core since .NET Core 3.1.
On .NET Framework 4.7.2, the issue does not occur.
Known Workarounds
No response
Configuration
x64
reproduced on Windows and Linux
Other information
No response