From c1bb71b900f9055a1daa0183cf5405a046a0bc29 Mon Sep 17 00:00:00 2001 From: dadhi Date: Wed, 18 Dec 2024 11:13:46 +0100 Subject: [PATCH] added test for #443 --- .../FastExpressionCompiler.cs | 11 +-- ...443_Nested_Calls_with_lambda_parameters.cs | 84 +++++++++++++++++-- ...pressionCompiler.TestsRunner.Net472.csproj | 2 +- .../Program.cs | 3 +- 4 files changed, 86 insertions(+), 14 deletions(-) diff --git a/src/FastExpressionCompiler/FastExpressionCompiler.cs b/src/FastExpressionCompiler/FastExpressionCompiler.cs index 93f32cd6..4893c57c 100644 --- a/src/FastExpressionCompiler/FastExpressionCompiler.cs +++ b/src/FastExpressionCompiler/FastExpressionCompiler.cs @@ -1738,14 +1738,15 @@ private static bool TryCompileNestedLambda(ref ClosureInfo nestedClosureInfo, Ne return false; il.Demit(OpCodes.Ret); - // If we don't have closure then create a static or an open delegate to pass closure later with `TryEmitNestedLambda`, - // constructing the new closure with non-passed arguments and the rest of items - nestedLambdaInfo.Lambda = nestedLambdaClosure != null + // If we don't have closure then create a static or an open delegate to pass closure later in `TryEmitNestedLambda`, + // constructing the new closure with NonPassedParams and the rest of items stored in NestedLambdaWithConstantsAndNestedLambdas + var nestedLambda = nestedLambdaClosure != null ? method.CreateDelegate(nestedLambdaExpr.Type, nestedLambdaClosure) : method.CreateDelegate(Tools.GetFuncOrActionType(closurePlusParamTypes, nestedReturnType), null); - if (nestedConstsAndLambdas != null & containsConstantsOrNestedLambdas & hasNonPassedParameters) - nestedLambdaInfo.Lambda = new NestedLambdaWithConstantsAndNestedLambdas(nestedLambdaInfo.Lambda, nestedConstsAndLambdas); + nestedLambdaInfo.Lambda = nestedConstsAndLambdas != null & hasNonPassedParameters + ? new NestedLambdaWithConstantsAndNestedLambdas(nestedLambda, nestedConstsAndLambdas) + : nestedLambda; ReturnClosureTypeToParamTypesToPool(closurePlusParamTypes); return true; diff --git a/test/FastExpressionCompiler.IssueTests/Issue443_Nested_Calls_with_lambda_parameters.cs b/test/FastExpressionCompiler.IssueTests/Issue443_Nested_Calls_with_lambda_parameters.cs index 434e5ed3..09fd1012 100644 --- a/test/FastExpressionCompiler.IssueTests/Issue443_Nested_Calls_with_lambda_parameters.cs +++ b/test/FastExpressionCompiler.IssueTests/Issue443_Nested_Calls_with_lambda_parameters.cs @@ -17,8 +17,10 @@ public class Issue443_Nested_Calls_with_lambda_parameters : ITest { public int Run() { - Original_case_1(); - return 1; + // Original_case(); + // Case_with_Invoke(); + Case_with_Invoke_NoInlining(); + return 2; } public class TestClass @@ -27,7 +29,7 @@ public class TestClass } [Test] - public void Original_case_1() + public void Original_case() { var executeDelegate = typeof(TestClass).GetMethod(nameof(TestClass.ExecuteDelegate)); var local = Variable(typeof(int), "local"); @@ -37,10 +39,6 @@ public void Original_case_1() Block( new ParameterExpression[] { local }, Assign(local, Constant(42)), - - // Invoke works - //Invoke( Lambda>( local ) ) - // Call does not work Call(executeDelegate, Lambda>(local)) ) @@ -64,4 +62,76 @@ public void Original_case_1() var fr = ff(); Assert.AreEqual(42, fr); } + + [Test] + public void Case_with_Invoke() + { + var executeDelegate = typeof(TestClass).GetMethod(nameof(TestClass.ExecuteDelegate)); + var local = Variable(typeof(int), "local"); + + var innerLambda = + Lambda>( + Block( + new ParameterExpression[] { local }, + Assign(local, Constant(42)), + + // Invoke works + Invoke(Lambda>(local)) + ) + ); + + var expr = Lambda>( + Call(executeDelegate, innerLambda) + ); + + expr.PrintCSharp(); + + var fs = expr.CompileSys(); + fs.PrintIL(); + + var sr = fs(); + Assert.AreEqual(42, sr); + + var ff = expr.CompileFast(false); + ff.PrintIL(); + + var fr = ff(); + Assert.AreEqual(42, fr); + } + + [Test] + public void Case_with_Invoke_NoInlining() + { + var executeDelegate = typeof(TestClass).GetMethod(nameof(TestClass.ExecuteDelegate)); + var local = Variable(typeof(int), "local"); + + var innerLambda = + Lambda>( + Block( + new ParameterExpression[] { local }, + Assign(local, Constant(42)), + + // Invoke works + Invoke(Lambda>(local)) + ) + ); + + var expr = Lambda>( + Call(executeDelegate, innerLambda) + ); + + expr.PrintCSharp(); + + var fs = expr.CompileSys(); + fs.PrintIL(); + + var sr = fs(); + Assert.AreEqual(42, sr); + + var ff = expr.CompileFast(false, CompilerFlags.NoInvocationLambdaInlining); + ff.PrintIL(); + + var fr = ff(); + Assert.AreEqual(42, fr); + } } \ No newline at end of file diff --git a/test/FastExpressionCompiler.TestsRunner.Net472/FastExpressionCompiler.TestsRunner.Net472.csproj b/test/FastExpressionCompiler.TestsRunner.Net472/FastExpressionCompiler.TestsRunner.Net472.csproj index 88285ff1..82668b0c 100644 --- a/test/FastExpressionCompiler.TestsRunner.Net472/FastExpressionCompiler.TestsRunner.Net472.csproj +++ b/test/FastExpressionCompiler.TestsRunner.Net472/FastExpressionCompiler.TestsRunner.Net472.csproj @@ -6,7 +6,7 @@ false false - $(NoWarn);NETSDK1005;NETSDK1138;NU1702 + $(NoWarn);NETSDK1005;NETSDK1138;NU1702;NU1900 diff --git a/test/FastExpressionCompiler.TestsRunner/Program.cs b/test/FastExpressionCompiler.TestsRunner/Program.cs index eee17eea..b9a5003e 100644 --- a/test/FastExpressionCompiler.TestsRunner/Program.cs +++ b/test/FastExpressionCompiler.TestsRunner/Program.cs @@ -9,7 +9,8 @@ public class Program { public static void Main() { - new LightExpression.IssueTests.Issue437_Shared_variables_with_nested_lambdas_returning_incorrect_values().Run(); + new LightExpression.IssueTests.Issue443_Nested_Calls_with_lambda_parameters().Run(); + // new LightExpression.IssueTests.Issue437_Shared_variables_with_nested_lambdas_returning_incorrect_values().Run(); // new LightExpression.UnitTests.ArithmeticOperationsTests().Run(); RunAllTests();