Skip to content

Expression.Compile(preferInterpretation: true) invokes inner lambda when a method is called on it #96385

Open
@tomasherceg

Description

@tomasherceg

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

Metadata

Metadata

Assignees

Labels

area-System.Linq.Expressionsin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions