diff --git a/src/Compiler/Optimize/LowerStateMachines.fs b/src/Compiler/Optimize/LowerStateMachines.fs index 5a6fadcfd6d..7986cec3e04 100644 --- a/src/Compiler/Optimize/LowerStateMachines.fs +++ b/src/Compiler/Optimize/LowerStateMachines.fs @@ -187,8 +187,17 @@ type LowerStateMachine(g: TcGlobals) = | Expr.Let (defn, bodyExpr, _, _) when isStateMachineBindingVar g defn.Var -> if sm_verbose then printfn "binding %A --> %A..." defn.Var defn.Expr let envR = { env with ResumableCodeDefns = env.ResumableCodeDefns.Add defn.Var defn.Expr } + let envR, _ = BindResumableCodeDefinitions envR defn.Expr BindResumableCodeDefinitions envR bodyExpr + | Expr.Lambda (valParams = valParams; bodyExpr = bodyExpr; overallType = ty) when isReturnsResumableCodeTy g ty -> + if sm_verbose then printfn "binding fun %A --> %A..." valParams bodyExpr + BindResumableCodeDefinitions env bodyExpr + + | Expr.DebugPoint (_, innerExpr) -> + let envR, _ = BindResumableCodeDefinitions env innerExpr + envR, expr + // Eliminate 'if __useResumableCode ...' | IfUseResumableStateMachinesExpr g (thenExpr, _) -> if sm_verbose then printfn "eliminating 'if __useResumableCode...'" @@ -313,11 +322,14 @@ type LowerStateMachine(g: TcGlobals) = | Some innerExpr2 -> Some (Expr.DebugPoint (dp, innerExpr2)) | None -> None + | Expr.App _ -> + TryReduceExpr env expr args id + | _ -> None // Apply a single expansion of resumable code at the outermost position in an arbitrary expression - let rec TryReduceExpr (env: env) expr args remake = + and TryReduceExpr (env: env) expr args remake = if sm_verbose then printfn "expanding defns and reducing %A..." expr //if sm_verbose then printfn "checking %A for possible resumable code application..." expr match expr with diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs index c2dca0d1fb4..3cf3c4f3020 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs @@ -102,6 +102,97 @@ let compute () = // multiple invocations to trigger tiered compilation for i in 1 .. 100 do compute().Wait () +""" + |> withOptimize + |> compileExeAndRun + |> shouldSucceed + + [] // https://github.com/dotnet/fsharp/issues/12839#issuecomment-1292310944 + let ``Tasks with a for loop over tuples are statically compilable``() = + FSharp """ +module TestProject1 + +let ret i = task { return i } + +let one (f: seq) = task { + let mutable sum = 0 + + let! x = ret 1 + sum <- sum + x + + for name, _whatever, i in f do + let! x = ret i + sum <- sum + x + + System.Console.Write name + + let! x = ret i + sum <- sum + x + + let! x = ret 1 + sum <- sum + x + + return sum +} + +let two (f: seq) = task { + let mutable sum = 0 + + let! x = ret 1 + sum <- sum + x + + for name, _whatever, i in f do + let! x = ret i + sum <- sum + x + + System.Console.Write name + + let! x = ret 1 + sum <- sum + x + + return sum +} + +let three (f: seq) = task { + let mutable sum = 0 + + let! x = ret 1 + sum <- sum + x + + for name, _whatever, i in f do + let! x = ret i + sum <- sum + x + + System.Console.Write name + + return sum +} + +let four (f: seq) = task { + let mutable sum = 0 + + let! x = ret 5 + sum <- sum + x + + for name, _i in f do + System.Console.Write name + + let! x = ret 1 + sum <- sum + x + + return sum +} + +if (one [ ("", "", 1); ("", "", 2) ]).Result <> 8 then + failwith "unexpected result one" +if (one []).Result <> 2 then + failwith "unexpected result one" +if (two [ ("", "", 2) ]).Result <> 4 then + failwith "unexpected result two" +if (three [ ("", "", 5) ]).Result <> 6 then + failwith "unexpected result three" +if (four [ ("", 10) ]).Result <> 6 then + failwith "unexpected result four" """ |> withOptimize |> compileExeAndRun