From 97a742cd8481cee3d52fa67bf2b7c6a9aad5d313 Mon Sep 17 00:00:00 2001 From: majocha <1760221+majocha@users.noreply.github.com> Date: Sun, 6 Sep 2026 22:53:33 +0200 Subject: [PATCH 1/5] Preserve resumable state-machine lowering in Debug --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/Optimize/Optimizer.fs | 91 ++++++++++++++-- .../EmittedIL/DebugInlineAsCall.fs | 34 +++++- .../Resumable 04 - Builder Run is inlined.bsl | 100 ++++++++++++++++++ 4 files changed, 216 insertions(+), 10 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 04 - Builder Run is inlined.bsl diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 9441f8587e0..63983c9de7e 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -5,6 +5,7 @@ * Fix Release-only (`--optimize+`) `System.InvalidProgramException` from `Seq.collect` / `yield!` over a value-type (struct) collection implementing `seq<'T>` (e.g. `ImmutableArray<_>`) when materialised with `List.ofSeq` / `Seq.toList` / `Seq.toArray` or a list/array comprehension. The collector lowering now boxes a struct sub-collection to `seq<'T>` before calling `AddMany`/`AddManyAndClose` (matching the coercion the type checker already inserts for `yield!`), and uses `unit` as the try/finally result type instead of the body type (removing a spurious `ldnull` store). ([Issue #20203](https://github.com/dotnet/fsharp/issues/20203)) * Fix recursive inline SRTP resolution being truncated by one currying level (e.g. FSharpPlus `memoizeN`), a regression from the function-domain unification order change in [PR #15181](https://github.com/dotnet/fsharp/pull/15181); the contravariant domain now keeps the inference variable that still carries the pending member constraint. ([PR #20247](https://github.com/dotnet/fsharp/pull/20247)) * Fix exponential (2^N) compile time in pattern matching with shared guards and partial active patterns. ([Issue #18425](https://github.com/dotnet/fsharp/issues/18425), [PR #20244](https://github.com/dotnet/fsharp/pull/20244)) +* Fix incorrect Debug lowering of inline builders that compose low-level resumable state machines. ([Issue #20466](https://github.com/dotnet/fsharp/issues/20466)) * Fix incorrect `StructLayout(Size = 1)` emission for data-less struct unions where the compiler-generated tag field makes the actual runtime size larger. ([PR #19759](https://github.com/dotnet/fsharp/pull/19759)) * Fix FS0750 "This construct may only be used within computation expressions" incorrectly raised for `let!`/`use!`/`do!` appearing in the right-hand side of a plain `let` binding inside a computation expression. The right-hand side is now desugared as a nested computation of the same builder whose result is bound with `let!`, keeping its bindings correctly scoped. ([Issue #19457](https://github.com/dotnet/fsharp/issues/19457), [PR #19868](https://github.com/dotnet/fsharp/pull/19868)) * Stop leaking a `System.Diagnostics.Metrics.MeterListener` per `Cache` in DEBUG builds. Each cache created a `CacheMetrics.CacheMetricsListener` (which starts a `MeterListener` registered in the process-global metrics registry) and never disposed it, so listeners accumulated for the lifetime of the process. Because every cache hit/miss/add published to all registered listeners, the per-operation cost grew linearly with the number of leaked listeners, so repeated checks (and Debug FCS test runs) slowed down over time. The per-cache `CacheMetricsListener` and the per-instance `cacheId` tag are removed; `DebugDisplay` and tests now read the existing name-aggregated stats populated by the single `ListenToAll` listener, so no per-cache listener is created and no per-operation cost is added. ([PR #19995](https://github.com/dotnet/fsharp/pull/19995)) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index bdb1cda813e..673844e9814 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -499,6 +499,9 @@ type IncrementalOptimizationEnv = /// definition-site replay finds no match; this call site does, letting the correct extension be honored /// instead of degrading to the throwing dynamic stub. None outside the debug-specialization path. debugInlineCallSite: range option + + /// Inline resumable-code combinators while specializing an enclosing state-machine builder. + resumableCodeContext: bool } static member Empty = @@ -513,7 +516,8 @@ type IncrementalOptimizationEnv = methEnv = { pipelineCount = 0 } referencedCcus = [] earlierImplFileSignatures = [] - debugInlineCallSite = None } + debugInlineCallSite = None + resumableCodeContext = false } override x.ToString() = "" @@ -2504,6 +2508,49 @@ and ExprIsFrameLocal cenv env expr = FoldExpr folder false expr +// A Debug helper method would hide this definition tree from LowerStateMachines. +let HasResumableStateMachineBody cenv env (vref: ValRef) = + let rec hasResumableCodeArgument ty = + let ty = stripTyEqns cenv.g ty + + if isFunTy cenv.g ty then + isResumableCodeTy cenv.g (domainOfFunTy cenv.g ty) + || hasResumableCodeArgument (rangeOfFunTy cenv.g ty) + else + false + + let rec containsStateMachineBody visiting expr = + let folder = + { ExprFolder0 with + exprIntercept = + fun _recurseF noInterceptF acc expr -> + if acc then + acc + else + match expr with + | StructStateMachineExpr cenv.g _ -> true + | Expr.Val (nestedVref, _, _) when nestedVref.ShouldInline -> + hasStateMachineBody visiting nestedVref + | _ -> noInterceptF acc expr } + + FoldExpr folder false expr + + and hasStateMachineBody visiting (vref: ValRef) = + if List.exists ((=) vref.Stamp) visiting then + false + else + let _, ty = tryDestForallTy cenv.g vref.Type + + if not (hasResumableCodeArgument ty) then + false + else + match TryGetInfoForVal cenv env vref |> Option.map (fun info -> stripValue info.ValExprInfo) with + | Some(CurriedLambdaValue (_, _, _, body, _)) -> + containsStateMachineBody (vref.Stamp :: visiting) body + | _ -> false + + hasStateMachineBody [] vref + let shouldForceInlineInDebug cenv env (vref: ValRef) : bool = let g = cenv.g @@ -2512,6 +2559,10 @@ let shouldForceInlineInDebug cenv env (vref: ValRef) : bool = (vref.HasDeclaringEntity && shouldForceInlineMembersInDebug g vref.DeclaringEntity) || + (cenv.optimizing && + (HasResumableStateMachineBody cenv env vref || + (env.resumableCodeContext && isReturnsResumableCodeTy g vref.TauType))) || + HasFrameLocalBody cenv env vref /// Optimize/analyze an expression @@ -3657,9 +3708,10 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) = /// Attempt to inline an application of a known value at callsites and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, args: Expr list, m) = let g = cenv.g - match cenv.settings.alwaysInline, stripExpr valExpr with - | false, Expr.Val(vref, _, _) when vref.ShouldInline && not (shouldForceInlineInDebug cenv env vref) -> + | false, Expr.Val(vref, _, _) when vref.ShouldInline -> + let forceInline = shouldForceInlineInDebug cenv env vref + let hasResumableStateMachineBody = HasResumableStateMachineBody cenv env vref let hasNoTraits = let tps, _ = tryDestForallTy g vref.Type GetTraitConstraintInfosOfTypars g tps |> List.isEmpty @@ -3678,17 +3730,25 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // so route those through the specialization path which inlines the body. let isHiddenBySignature = cenv.signatureHidingInfo.HiddenVals.Contains vref.Deref let canCallDirectly = + not forceInline && (cenv.optimizing || (vref.Accessibility.IsPublic && not isHiddenBySignature)) && (hasNoTraits || (allTyargsAreBareTypars && vref.ValReprInfo.IsSome)) - let argsR = args |> List.map (OptimizeExpr cenv env >> fst) + // Keep nested resumable combinators in the same expression tree as the builder. + let inlineEnv = + if forceInline && hasResumableStateMachineBody then + { env with resumableCodeContext = true } + else + env + + let argsR = args |> List.map (OptimizeExpr cenv inlineEnv >> fst) let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } if canCallDirectly then Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) else - let origFinfo = GetInfoForVal cenv env m vref + let origFinfo = GetInfoForVal cenv inlineEnv m vref match stripValue origFinfo.ValExprInfo with | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) -> let f2R = CopyExprForInlining cenv true origLambda m @@ -3709,7 +3769,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // function (e.g. sumint> can call sum in its body). For // non-concrete type args, never specialize recursively. let canSpecialize = - match Map.tryFind origLambdaId env.dontInline with + match Map.tryFind origLambdaId inlineEnv.dontInline with | Some tys -> allTyargsAreConcrete && not tys.IsEmpty && @@ -3725,15 +3785,28 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg | Some (_, body) -> copyExpr g CloneAll body | None -> - let existingTypes = defaultArg (Map.tryFind origLambdaId env.dontInline) [] - let env = { env with dontInline = Map.add origLambdaId (specLambdaTy :: existingTypes) env.dontInline; debugInlineCallSite = Some m } + let existingTypes = defaultArg (Map.tryFind origLambdaId inlineEnv.dontInline) [] + let currentDontInline = inlineEnv.dontInline + let env = { inlineEnv with dontInline = Map.add origLambdaId (specLambdaTy :: existingTypes) currentDontInline; debugInlineCallSite = Some m } let specLambdaR, _ = OptimizeExpr cenv env specLambda cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) specLambdaR else - let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Map.add origLambdaId [] env.dontInline; debugInlineCallSite = Some m } specLambda + let currentDontInline = inlineEnv.dontInline + let specLambdaR, _ = OptimizeExpr cenv { inlineEnv with dontInline = Map.add origLambdaId [] currentDontInline; debugInlineCallSite = Some m } specLambda specLambdaR + let fullyInlineResumable = + forceInline && + (hasResumableStateMachineBody || + (inlineEnv.resumableCodeContext && isReturnsResumableCodeTy g vref.TauType)) + + // A helper method boundary would hide the resumable definitions from lowering. + if fullyInlineResumable then + let reducedExpr = MakeApplicationAndBetaReduce g (specLambdaR, specLambdaTy, [], argsR, m) + Some(OptimizeExpr cenv inlineEnv reducedExpr) + else + // Abstract the specialized lambda over its free typars so IlxGen emits a static // method with flattened arguments. The alternative closure form (valReprInfo = None) // wraps args in a reference Tuple<>, which cannot hold byrefs and fails to load at diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 976b1c5f68f..c3e0567023d 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -1759,6 +1759,39 @@ let main _ = |> compileAndRun |> verifySequencePoints + [] + let ``Resumable 04 - Builder Run is inlined`` () = + FSharp """ +open Microsoft.FSharp.Core.CompilerServices +open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers + +#nowarn "3501" +#nowarn "3513" + +type Builder() = + member inline _.Run(code: ResumableCode) = + if __useResumableCode then + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> code.Invoke(&sm) |> ignore)) + (SetStateMachineMethodImpl<_>(fun _ _ -> ())) + (AfterCode<_, _>(fun _ -> 42)) + else + 0 + +let builder = Builder() + +[] +let main _ = + let code = ResumableCode(fun _ -> true) + let result = builder.Run code + if result = 42 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifySequencePoints + [] let ``InlineIfLambda 01 - Debug`` () = FSharp """ @@ -1896,4 +1929,3 @@ let main _ = |> asExe |> compileAndRun |> verifySequencePoints - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 04 - Builder Run is inlined.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 04 - Builder Run is inlined.bsl new file mode 100644 index 00000000000..fcb69cc382b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 04 - Builder Run is inlined.bsl @@ -0,0 +1,100 @@ +open Microsoft.FSharp.Core.CompilerServices +open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers + +#nowarn "3501" +#nowarn "3513" + +type Builder() = + member inline _.Run(code: ResumableCode) = + if __useResumableCode then + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> code.Invoke(&sm) |> ignore)) + (SetStateMachineMethodImpl<_>(fun _ _ -> ())) + (AfterCode<_, _>(fun _ -> 42)) + else + 0 + +let builder = Builder() + +[] +let main _ = + let code = ResumableCode(fun _ -> true) + let result = builder.Run code + if result = 42 then 0 else 1 +-------------------------------------------------------------------------------- + +Test::main + (22,5-22,55) let code = ResumableCode(fun _ -> true) + IL_0000: ldc.i4.0 + IL_0001: stsfld $Test::init@ + IL_0006: ldsfld $Test::init@ + IL_000b: pop + IL_000c: ldnull + IL_000d: ldftn code@22::Invoke + IL_0013: newobj .ctor + IL_0018: stloc.0 + + (23,5-23,34) let result = builder.Run code + IL_0019: ldloca.s 2 + IL_001b: initobj result@23 + IL_0021: ldloca.s 2 + IL_0023: stloc.3 + IL_0024: ldc.i4.s 42 + IL_0026: stloc.1 + + (24,5-24,24) if result = 42 then + IL_0027: ldloc.1 + IL_0028: ldc.i4.s 42 + IL_002a: bne.un.s IL_002e + + (24,25-24,26) 0 + IL_002c: ldc.i4.0 + IL_002d: ret + + (24,32-24,33) 1 + IL_002e: ldc.i4.1 + IL_002f: ret + +Test::.cctor + + IL_0000: ldc.i4.0 + IL_0001: stsfld $Test::init@ + IL_0006: ldsfld $Test::init@ + IL_000b: pop + IL_000c: ret + +Test::staticInitialization@ + (18,1-18,24) let builder = Builder() + IL_0000: newobj Builder::.ctor + IL_0005: stsfld Test::builder@18 + IL_000a: ret + +Builder::.ctor + (8,6-8,13) Builder + IL_0000: ldarg.0 + IL_0001: callvirt Object::.ctor + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + +Builder::Run + (16,13-16,14) 0 + IL_0000: ldc.i4.0 + IL_0001: ret + +code@22::Invoke + (22,50-22,54) true + IL_0000: ldc.i4.1 + IL_0001: ret + +result@23::MoveNext + + IL_0000: ldarg.0 + IL_0001: stloc.1 + + (22,50-22,54) true + IL_0002: ldc.i4.1 + IL_0003: stloc.0 + IL_0004: ldloc.0 + IL_0005: stloc.2 + IL_0006: ret From 3aba0a37f1ff9d4582edb3c55d82d3088566662c Mon Sep 17 00:00:00 2001 From: majocha <1760221+majocha@users.noreply.github.com> Date: Sun, 6 Sep 2026 23:38:59 +0200 Subject: [PATCH 2/5] Keep ordinary debug inlining on the existing path --- src/Compiler/Optimize/Optimizer.fs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 673844e9814..d8bbfb392e6 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -2551,6 +2551,11 @@ let HasResumableStateMachineBody cenv env (vref: ValRef) = hasStateMachineBody [] vref +let isResumableInlineInDebug cenv env (vref: ValRef) = + cenv.optimizing && + (HasResumableStateMachineBody cenv env vref || + (env.resumableCodeContext && isReturnsResumableCodeTy cenv.g vref.TauType)) + let shouldForceInlineInDebug cenv env (vref: ValRef) : bool = let g = cenv.g @@ -2559,9 +2564,7 @@ let shouldForceInlineInDebug cenv env (vref: ValRef) : bool = (vref.HasDeclaringEntity && shouldForceInlineMembersInDebug g vref.DeclaringEntity) || - (cenv.optimizing && - (HasResumableStateMachineBody cenv env vref || - (env.resumableCodeContext && isReturnsResumableCodeTy g vref.TauType))) || + isResumableInlineInDebug cenv env vref || HasFrameLocalBody cenv env vref @@ -3709,7 +3712,9 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) = and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, args: Expr list, m) = let g = cenv.g match cenv.settings.alwaysInline, stripExpr valExpr with - | false, Expr.Val(vref, _, _) when vref.ShouldInline -> + | false, Expr.Val(vref, _, _) + when vref.ShouldInline && + (not (shouldForceInlineInDebug cenv env vref) || isResumableInlineInDebug cenv env vref) -> let forceInline = shouldForceInlineInDebug cenv env vref let hasResumableStateMachineBody = HasResumableStateMachineBody cenv env vref let hasNoTraits = @@ -3797,9 +3802,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg specLambdaR let fullyInlineResumable = - forceInline && - (hasResumableStateMachineBody || - (inlineEnv.resumableCodeContext && isReturnsResumableCodeTy g vref.TauType)) + forceInline && isResumableInlineInDebug cenv inlineEnv vref // A helper method boundary would hide the resumable definitions from lowering. if fullyInlineResumable then From 0576f3339186a35dc5026909968d33910fc3b1ca Mon Sep 17 00:00:00 2001 From: perf-bundle Date: Wed, 9 Sep 2026 10:55:41 +0200 Subject: [PATCH 3/5] Preserve resumable template context in Debug Keep resumable producers and template-hosting bodies on the compulsory inlining path. Avoid extracting Debug specializations involving state-machine templates: the generated struct can carry captured type parameters that the helper cannot preserve. Retain ordinary Debug calls, add runtime and cross-assembly regressions, and update affected IL expectations. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../.FSharp.Compiler.Service/11.0.100.md | 2 +- src/Compiler/Optimize/Optimizer.fs | 130 +- src/Compiler/TypedTree/TcGlobals.fsi | 2 + .../TypedTree/TypedTreeOps.FreeVars.fs | 13 +- .../TypedTree/TypedTreeOps.FreeVars.fsi | 5 +- .../EmittedIL/DebugInlineAsCall.fs | 2 + .../DebugInlineAsCall/Resumable 01.bsl | 101 +- .../DebugInlineAsCall/Resumable 02.bsl | 365 ++++- .../DebugInlineAsCall/Resumable 03.bsl | 31 +- ...eCode and partially resolved type args.bsl | 112 +- ...ed trait from composed inline function.bsl | 71 +- .../Language/StateMachineTests.fs | 121 ++ .../CodeGen/EmittedIL/TaskGeneratedCode.fs | 1378 +++++++++-------- 13 files changed, 1363 insertions(+), 970 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 1b79e705b95..a30df2b0166 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -5,7 +5,7 @@ * Fix Release-only (`--optimize+`) `System.InvalidProgramException` from `Seq.collect` / `yield!` over a value-type (struct) collection implementing `seq<'T>` (e.g. `ImmutableArray<_>`) when materialised with `List.ofSeq` / `Seq.toList` / `Seq.toArray` or a list/array comprehension. The collector lowering now boxes a struct sub-collection to `seq<'T>` before calling `AddMany`/`AddManyAndClose` (matching the coercion the type checker already inserts for `yield!`), and uses `unit` as the try/finally result type instead of the body type (removing a spurious `ldnull` store). ([Issue #20203](https://github.com/dotnet/fsharp/issues/20203)) * Fix recursive inline SRTP resolution being truncated by one currying level (e.g. FSharpPlus `memoizeN`), a regression from the function-domain unification order change in [PR #15181](https://github.com/dotnet/fsharp/pull/15181); the contravariant domain now keeps the inference variable that still carries the pending member constraint. ([PR #20247](https://github.com/dotnet/fsharp/pull/20247)) * Fix exponential (2^N) compile time in pattern matching with shared guards and partial active patterns. ([Issue #18425](https://github.com/dotnet/fsharp/issues/18425), [PR #20244](https://github.com/dotnet/fsharp/pull/20244)) -* Fix incorrect Debug lowering of inline builders that compose low-level resumable state machines. ([Issue #20466](https://github.com/dotnet/fsharp/issues/20466)) +* Fix incorrect Debug lowering of inline builders that compose low-level resumable state machines. ([Issue #20466](https://github.com/dotnet/fsharp/issues/20466), [PR #20469](https://github.com/dotnet/fsharp/pull/20469)) * Fix incorrect `StructLayout(Size = 1)` emission for data-less struct unions where the compiler-generated tag field makes the actual runtime size larger. ([PR #19759](https://github.com/dotnet/fsharp/pull/19759)) * Fix FS0750 "This construct may only be used within computation expressions" incorrectly raised for `let!`/`use!`/`do!` appearing in the right-hand side of a plain `let` binding inside a computation expression. The right-hand side is now desugared as a nested computation of the same builder whose result is bound with `let!`, keeping its bindings correctly scoped. ([Issue #19457](https://github.com/dotnet/fsharp/issues/19457), [PR #19868](https://github.com/dotnet/fsharp/pull/19868)) * Stop leaking a `System.Diagnostics.Metrics.MeterListener` per `Cache` in DEBUG builds. Each cache created a `CacheMetrics.CacheMetricsListener` (which starts a `MeterListener` registered in the process-global metrics registry) and never disposed it, so listeners accumulated for the lifetime of the process. Because every cache hit/miss/add published to all registered listeners, the per-operation cost grew linearly with the number of leaked listeners, so repeated checks (and Debug FCS test runs) slowed down over time. The per-cache `CacheMetricsListener` and the per-instance `cacheId` tag are removed; `DebugDisplay` and tests now read the existing name-aggregated stats populated by the single `ListenToAll` listener, so no per-cache listener is created and no per-operation cost is added. ([PR #19995](https://github.com/dotnet/fsharp/pull/19995)) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index fd842800211..8e6f236e757 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -441,8 +441,8 @@ type cenv = specializedInlineVals: HashMultiMap - /// Cache for 'HasFrameLocalBody' - frameLocalVals: Dictionary + /// Cache for 'HasForcedInlineBody' + forcedInlineVals: Dictionary signatureHidingInfo: SignatureHidingInfo } @@ -499,9 +499,6 @@ type IncrementalOptimizationEnv = /// definition-site replay finds no match; this call site does, letting the correct extension be honored /// instead of degrading to the throwing dynamic stub. None outside the debug-specialization path. debugInlineCallSite: range option - - /// Inline resumable-code combinators while specializing an enclosing state-machine builder. - resumableCodeContext: bool } static member Empty = @@ -516,8 +513,7 @@ type IncrementalOptimizationEnv = methEnv = { pipelineCount = 0 } referencedCcus = [] earlierImplFileSignatures = [] - debugInlineCallSite = None - resumableCodeContext = false } + debugInlineCallSite = None } override x.ToString() = "" @@ -2478,23 +2474,23 @@ let instrIsFrameLocal instr = /// attribute - the callee is already inlined into the recorded body, leaving only its IL - so /// recover it from the body and propagate it through further wrappers. /// See https://github.com/dotnet/fsharp/issues/20063. -let rec HasFrameLocalBody cenv env (vref: ValRef) = +let rec HasForcedInlineBody cenv env (vref: ValRef) = let stamp = vref.Stamp - match cenv.frameLocalVals.TryGetValue stamp with + match cenv.forcedInlineVals.TryGetValue stamp with | true, res -> res | _ -> // Values bound within the body being walked have no info yet, but the walk covers them anyway. match TryGetInfoForVal cenv env vref |> Option.map (fun info -> stripValue info.ValExprInfo) with | Some(CurriedLambdaValue (_, _, _, body, _)) -> - cenv.frameLocalVals[stamp] <- false // Break cycles while the body is inspected - let res = ExprIsFrameLocal cenv env body - cenv.frameLocalVals[stamp] <- res + cenv.forcedInlineVals[stamp] <- false // Break cycles while the body is inspected + let res = ExprNeedsForcedInlining cenv env body + cenv.forcedInlineVals[stamp] <- res res | _ -> false -and ExprIsFrameLocal cenv env expr = +and ExprNeedsForcedInlining cenv env expr = let folder = { ExprFolder0 with exprIntercept = @@ -2503,59 +2499,13 @@ and ExprIsFrameLocal cenv env expr = match expr with | Expr.Op (TOp.ILAsm (instrs, _), _, _, _) when List.exists instrIsFrameLocal instrs -> true - | Expr.Val (vref, _, _) when vref.ShouldInline -> HasFrameLocalBody cenv env vref + // Lowering must see the template and its resumable-code arguments in the same method. + | StructStateMachineExpr cenv.g _ -> true + | Expr.Val (vref, _, _) when vref.ShouldInline -> HasForcedInlineBody cenv env vref | _ -> noInterceptF acc expr } FoldExpr folder false expr -// A Debug helper method would hide this definition tree from LowerStateMachines. -let HasResumableStateMachineBody cenv env (vref: ValRef) = - let rec hasResumableCodeArgument ty = - let ty = stripTyEqns cenv.g ty - - if isFunTy cenv.g ty then - isResumableCodeTy cenv.g (domainOfFunTy cenv.g ty) - || hasResumableCodeArgument (rangeOfFunTy cenv.g ty) - else - false - - let rec containsStateMachineBody visiting expr = - let folder = - { ExprFolder0 with - exprIntercept = - fun _recurseF noInterceptF acc expr -> - if acc then - acc - else - match expr with - | StructStateMachineExpr cenv.g _ -> true - | Expr.Val (nestedVref, _, _) when nestedVref.ShouldInline -> - hasStateMachineBody visiting nestedVref - | _ -> noInterceptF acc expr } - - FoldExpr folder false expr - - and hasStateMachineBody visiting (vref: ValRef) = - if List.exists ((=) vref.Stamp) visiting then - false - else - let _, ty = tryDestForallTy cenv.g vref.Type - - if not (hasResumableCodeArgument ty) then - false - else - match TryGetInfoForVal cenv env vref |> Option.map (fun info -> stripValue info.ValExprInfo) with - | Some(CurriedLambdaValue (_, _, _, body, _)) -> - containsStateMachineBody (vref.Stamp :: visiting) body - | _ -> false - - hasStateMachineBody [] vref - -let isResumableInlineInDebug cenv env (vref: ValRef) = - cenv.optimizing && - (HasResumableStateMachineBody cenv env vref || - (env.resumableCodeContext && isReturnsResumableCodeTy cenv.g vref.TauType)) - let shouldForceInlineInDebug cenv env (vref: ValRef) : bool = let g = cenv.g @@ -2564,9 +2514,9 @@ let shouldForceInlineInDebug cenv env (vref: ValRef) : bool = (vref.HasDeclaringEntity && shouldForceInlineMembersInDebug g vref.DeclaringEntity) || - isResumableInlineInDebug cenv env vref || + isReturnsResumableCodeTy g vref.TauType || - HasFrameLocalBody cenv env vref + HasForcedInlineBody cenv env vref /// Optimize/analyze an expression let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr = @@ -3711,12 +3661,9 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) = /// Attempt to inline an application of a known value at callsites and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, args: Expr list, m) = let g = cenv.g + match cenv.settings.alwaysInline, stripExpr valExpr with - | false, Expr.Val(vref, _, _) - when vref.ShouldInline && - (not (shouldForceInlineInDebug cenv env vref) || isResumableInlineInDebug cenv env vref) -> - let forceInline = shouldForceInlineInDebug cenv env vref - let hasResumableStateMachineBody = HasResumableStateMachineBody cenv env vref + | false, Expr.Val(vref, _, _) when vref.ShouldInline && not (shouldForceInlineInDebug cenv env vref) -> let hasNoTraits = let tps, _ = tryDestForallTy g vref.Type GetTraitConstraintInfosOfTypars g tps |> List.isEmpty @@ -3735,31 +3682,35 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // so route those through the specialization path which inlines the body. let isHiddenBySignature = cenv.signatureHidingInfo.HiddenVals.Contains vref.Deref let canCallDirectly = - not forceInline && (cenv.optimizing || (vref.Accessibility.IsPublic && not isHiddenBySignature)) && (hasNoTraits || (allTyargsAreBareTypars && vref.ValReprInfo.IsSome)) - // Keep nested resumable combinators in the same expression tree as the builder. - let inlineEnv = - if forceInline && hasResumableStateMachineBody then - { env with resumableCodeContext = true } - else - env - - let argsR = args |> List.map (OptimizeExpr cenv inlineEnv >> fst) + let argsR = args |> List.map (OptimizeExpr cenv env >> fst) let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } if canCallDirectly then Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) else - let origFinfo = GetInfoForVal cenv inlineEnv m vref + let origFinfo = GetInfoForVal cenv env m vref match stripValue origFinfo.ValExprInfo with | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) -> let f2R = CopyExprForInlining cenv true origLambda m let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) let specLambdaTy = tyOfExpr g specLambda + let hasStateMachineTemplate = + (false, specLambdaTy) + ||> SimplifyTypes.foldTypeButNotConstraints (stripTyEqns g) (fun found ty -> + found || + (tryTcrefOfAppTy g ty |> ValueOption.exists (tyconRefEq g g.ResumableStateMachine_tcr))) + + // A separate helper loses type parameters of the struct that replaces this template during lowering. + if hasStateMachineTemplate then + let cenv = { cenv with settings = { cenv.settings with alwaysInline = true } } + Some(OptimizeApplication cenv { env with debugInlineCallSite = Some m } (valExpr, vref.Type, tyargs, argsR, m)) + else + // Typars that flow in from the enclosing scope when tyargs are non-concrete. A tyarg can reach // only the body, and typars left unabstracted below are erased to 'object'. let freeTypars = @@ -3774,7 +3725,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // function (e.g. sumint> can call sum in its body). For // non-concrete type args, never specialize recursively. let canSpecialize = - match Map.tryFind origLambdaId inlineEnv.dontInline with + match Map.tryFind origLambdaId env.dontInline with | Some tys -> allTyargsAreConcrete && not tys.IsEmpty && @@ -3790,26 +3741,15 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg | Some (_, body) -> copyExpr g CloneAll body | None -> - let existingTypes = defaultArg (Map.tryFind origLambdaId inlineEnv.dontInline) [] - let currentDontInline = inlineEnv.dontInline - let env = { inlineEnv with dontInline = Map.add origLambdaId (specLambdaTy :: existingTypes) currentDontInline; debugInlineCallSite = Some m } + let existingTypes = defaultArg (Map.tryFind origLambdaId env.dontInline) [] + let env = { env with dontInline = Map.add origLambdaId (specLambdaTy :: existingTypes) env.dontInline; debugInlineCallSite = Some m } let specLambdaR, _ = OptimizeExpr cenv env specLambda cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) specLambdaR else - let currentDontInline = inlineEnv.dontInline - let specLambdaR, _ = OptimizeExpr cenv { inlineEnv with dontInline = Map.add origLambdaId [] currentDontInline; debugInlineCallSite = Some m } specLambda + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Map.add origLambdaId [] env.dontInline; debugInlineCallSite = Some m } specLambda specLambdaR - let fullyInlineResumable = - forceInline && isResumableInlineInDebug cenv inlineEnv vref - - // A helper method boundary would hide the resumable definitions from lowering. - if fullyInlineResumable then - let reducedExpr = MakeApplicationAndBetaReduce g (specLambdaR, specLambdaTy, [], argsR, m) - Some(OptimizeExpr cenv inlineEnv reducedExpr) - else - // Abstract the specialized lambda over its free typars so IlxGen emits a static // method with flattened arguments. The alternative closure form (valReprInfo = None) // wraps args in a reference Tuple<>, which cannot hold byrefs and fails to load at @@ -4919,7 +4859,7 @@ let OptimizeImplFile (settings, ccu, tcGlobals: TcGlobals, tcVal, importMap, opt stackGuard = StackGuard("OptimizerStackGuardDepth") realsig = tcGlobals.realsig specializedInlineVals = HashMultiMap(HashIdentity.Structural, true) - frameLocalVals = Dictionary() + forcedInlineVals = Dictionary() signatureHidingInfo = SignatureHidingInfo.Empty } diff --git a/src/Compiler/TypedTree/TcGlobals.fsi b/src/Compiler/TypedTree/TcGlobals.fsi index 8356b16ccfc..e0989c05a0a 100644 --- a/src/Compiler/TypedTree/TcGlobals.fsi +++ b/src/Compiler/TypedTree/TcGlobals.fsi @@ -288,6 +288,8 @@ type internal TcGlobals = member ResumableCode_tcr: TypedTree.EntityRef + member ResumableStateMachine_tcr: TypedTree.EntityRef + member System_Runtime_CompilerServices_RuntimeFeature_ty: TypedTree.TType option member addrof2_vref: TypedTree.ValRef diff --git a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs index 975ff6cfb3a..a57f42fcc6d 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs @@ -1082,19 +1082,20 @@ module internal MemberRepresentation = module SimplifyTypes = // CAREFUL! This function does NOT walk constraints - let rec foldTypeButNotConstraints f z ty = - let ty = stripTyparEqns ty + let rec foldTypeButNotConstraints normalizeType f z ty = + let ty = normalizeType ty let z = f z ty match ty with - | TType_forall(_, bodyTy) -> foldTypeButNotConstraints f z bodyTy + | TType_forall(_, bodyTy) -> foldTypeButNotConstraints normalizeType f z bodyTy | TType_app(_, tys, _) | TType_ucase(_, tys) | TType_anon(_, tys) - | TType_tuple(_, tys) -> List.fold (foldTypeButNotConstraints f) z tys + | TType_tuple(_, tys) -> List.fold (foldTypeButNotConstraints normalizeType f) z tys - | TType_fun(domainTy, rangeTy, _) -> foldTypeButNotConstraints f (foldTypeButNotConstraints f z domainTy) rangeTy + | TType_fun(domainTy, rangeTy, _) -> + foldTypeButNotConstraints normalizeType f (foldTypeButNotConstraints normalizeType f z domainTy) rangeTy | TType_var _ -> z @@ -1109,7 +1110,7 @@ module internal MemberRepresentation = let accTyparCounts z ty = // Walk type to determine typars and their counts (for pprinting decisions) (z, ty) - ||> foldTypeButNotConstraints (fun z ty -> + ||> foldTypeButNotConstraints stripTyparEqns (fun z ty -> match ty with | TType_var(tp, _) when tp.Rigidity = TyparRigidity.Rigid -> incM tp z | _ -> z) diff --git a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fsi b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fsi index 0e9761fe5ea..476e318de36 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fsi @@ -378,9 +378,12 @@ module internal MemberRepresentation = val prefixOfInferenceTypar: Typar -> string - /// Utilities used in simplifying types for visual presentation + /// Utilities for traversing and simplifying types module SimplifyTypes = + /// Fold normalized type structure without following type-parameter constraints. + val foldTypeButNotConstraints: (TType -> TType) -> ('State -> TType -> 'State) -> 'State -> TType -> 'State + type TypeSimplificationInfo = { singletons: Typar Zset inplaceConstraints: Zmap diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index c3e0567023d..854d0726bcb 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -1790,6 +1790,8 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> shouldSucceed + |> withExitCode 0 |> verifySequencePoints [] diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 01.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 01.bsl index 538420ab647..b087cd275f7 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 01.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 01.bsl @@ -8,35 +8,88 @@ let main _ = Test::main (6,13-6,17) task - IL_0000: call TaskBuilderModule::get_task - IL_0005: stloc.1 - IL_0006: ldloc.1 - IL_0007: ldloc.1 - IL_0008: ldloc.1 - IL_0009: newobj t@6::.ctor - IL_000e: callvirt TaskBuilderBase::Delay - IL_0013: callvirt TaskBuilder::Run - IL_0018: stloc.0 + IL_0000: ldloca.s 1 + IL_0002: initobj t@6 + IL_0008: ldloca.s 1 + IL_000a: stloc.2 + IL_000b: ldloc.2 + IL_000c: ldflda t@6::Data + IL_0011: call Create + IL_0016: stfld MethodBuilder + IL_001b: ldloc.2 + IL_001c: ldflda t@6::Data + IL_0021: ldflda MethodBuilder + IL_0026: ldloc.2 + IL_0027: call Start + IL_002c: ldloc.2 + IL_002d: ldflda t@6::Data + IL_0032: ldflda MethodBuilder + IL_0037: call get_Task + IL_003c: stloc.0 (7,5-7,25) if t.Result = 1 then - IL_0019: ldloc.0 - IL_001a: callvirt get_Result - IL_001f: ldc.i4.1 - IL_0020: bne.un.s IL_0024 + IL_003d: ldloc.0 + IL_003e: callvirt get_Result + IL_0043: ldc.i4.1 + IL_0044: bne.un.s IL_0048 (7,26-7,27) 0 - IL_0022: ldc.i4.0 - IL_0023: ret + IL_0046: ldc.i4.0 + IL_0047: ret (7,33-7,34) 1 - IL_0024: ldc.i4.1 - IL_0025: ret + IL_0048: ldc.i4.1 + IL_0049: ret -t@6::Invoke - (6,20-6,28) return 1 +t@6::MoveNext + IL_0000: ldarg.0 - IL_0001: ldfld t@6::builder@ - IL_0006: ldc.i4.1 - IL_0007: tail. - IL_0009: callvirt TaskBuilderBase::Return - IL_000e: ret + IL_0001: ldfld t@6::ResumptionPoint + IL_0006: stloc.0 + + (6,20-6,28) return 1 + IL_0007: ldc.i4.1 + IL_0008: stloc.3 + IL_0009: ldarg.0 + IL_000a: ldflda t@6::Data + IL_000f: ldloc.3 + IL_0010: stfld Result + IL_0015: ldc.i4.1 + IL_0016: stloc.2 + IL_0017: ldloc.2 + IL_0018: brfalse.s IL_0037 + + + IL_001a: ldarg.0 + IL_001b: ldflda t@6::Data + IL_0020: ldflda MethodBuilder + IL_0025: ldarg.0 + IL_0026: ldflda t@6::Data + IL_002b: ldfld Result + IL_0030: call SetResult + IL_0035: leave.s IL_0045 + + + IL_0037: leave.s IL_0045 + IL_0039: castclass Exception + IL_003e: stloc.s 4 + IL_0040: ldloc.s 4 + IL_0042: stloc.1 + IL_0043: leave.s IL_0045 + + + IL_0045: ldloc.1 + IL_0046: stloc.s 5 + IL_0048: ldloc.s 5 + IL_004a: brtrue.s IL_004d + + + IL_004c: ret + + + IL_004d: ldarg.0 + IL_004e: ldflda t@6::Data + IL_0053: ldflda MethodBuilder + IL_0058: ldloc.s 5 + IL_005a: call SetException + IL_005f: ret diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 02.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 02.bsl index 420647d81d1..34a8deffeda 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 02.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 02.bsl @@ -12,73 +12,322 @@ let main _ = Test::main (6,13-6,17) task - IL_0000: call TaskBuilderModule::get_task - IL_0005: stloc.1 - IL_0006: ldloc.1 - IL_0007: ldloc.1 - IL_0008: ldloc.1 - IL_0009: newobj t@9::.ctor - IL_000e: callvirt TaskBuilderBase::Delay - IL_0013: callvirt TaskBuilder::Run - IL_0018: stloc.0 + IL_0000: ldloca.s 1 + IL_0002: initobj t@6 + IL_0008: ldloca.s 1 + IL_000a: stloc.2 + IL_000b: ldloc.2 + IL_000c: ldflda t@6::Data + IL_0011: call Create + IL_0016: stfld MethodBuilder + IL_001b: ldloc.2 + IL_001c: ldflda t@6::Data + IL_0021: ldflda MethodBuilder + IL_0026: ldloc.2 + IL_0027: call Start + IL_002c: ldloc.2 + IL_002d: ldflda t@6::Data + IL_0032: ldflda MethodBuilder + IL_0037: call get_Task + IL_003c: stloc.0 (11,5-11,25) if t.Result = 3 then - IL_0019: ldloc.0 - IL_001a: callvirt get_Result - IL_001f: ldc.i4.3 - IL_0020: bne.un.s IL_0024 + IL_003d: ldloc.0 + IL_003e: callvirt get_Result + IL_0043: ldc.i4.3 + IL_0044: bne.un.s IL_0048 (11,26-11,27) 0 - IL_0022: ldc.i4.0 - IL_0023: ret + IL_0046: ldc.i4.0 + IL_0047: ret (11,33-11,34) 1 - IL_0024: ldc.i4.1 - IL_0025: ret + IL_0048: ldc.i4.1 + IL_0049: ret -t@8-1::Invoke +t@6::MoveNext - IL_0000: ldarg.1 - IL_0001: stloc.0 + IL_0000: ldarg.0 + IL_0001: ldfld t@6::ResumptionPoint + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: sub + IL_000a: switch (2 targets) + IL_0017: br.s IL_001f + + + IL_0019: nop + IL_001a: br.s IL_0020 + + + IL_001c: nop + IL_001d: br.s IL_0020 + + + IL_001f: nop + IL_0020: ldloc.0 + IL_0021: ldc.i4.1 + IL_0022: sub + IL_0023: switch (2 targets) + IL_0030: br.s IL_003b + + + IL_0032: nop + IL_0033: br.s IL_0064 + + + IL_0035: nop + IL_0036: br IL_00c5 + + + IL_003b: nop + + (7,9-7,36) let! x = Task.FromResult(1) + IL_003c: ldc.i4.1 + IL_003d: call Task::FromResult + IL_0042: stloc.3 + IL_0043: ldarg.0 + IL_0044: ldloc.3 + IL_0045: callvirt GetAwaiter + IL_004a: stfld t@6::awaiter0 + IL_004f: ldc.i4.1 + IL_0050: stloc.s 4 + IL_0052: ldarg.0 + IL_0053: ldflda t@6::awaiter0 + IL_0058: call get_IsCompleted + IL_005d: brfalse.s IL_0061 + IL_005f: br.s IL_007a + + + IL_0061: ldc.i4.0 + IL_0062: brfalse.s IL_0068 + + + IL_0064: ldc.i4.1 + + + IL_0065: nop + IL_0066: br.s IL_0071 + + + IL_0068: ldarg.0 + IL_0069: ldc.i4.1 + IL_006a: stfld t@6::ResumptionPoint + IL_006f: ldc.i4.0 + + + IL_0070: nop + IL_0071: stloc.s 5 + IL_0073: ldloc.s 5 + IL_0075: stloc.s 4 + + + IL_0077: nop + IL_0078: br.s IL_007b + + + IL_007a: nop + IL_007b: ldloc.s 4 + IL_007d: brfalse IL_014b + + + IL_0082: ldarg.0 + IL_0083: ldflda t@6::awaiter0 + IL_0088: call GetResult + IL_008d: stloc.s 6 + IL_008f: ldloc.s 6 + IL_0091: stloc.s 7 + IL_0093: ldarg.0 + IL_0094: ldloc.s 7 + IL_0096: stfld t@6::x (8,9-8,36) let! y = Task.FromResult(2) - IL_0002: ldarg.0 - IL_0003: ldfld t@8-1::builder@ - IL_0008: ldc.i4.2 - IL_0009: call Task::FromResult - IL_000e: ldarg.0 - IL_000f: ldfld t@8-1::builder@ - IL_0014: ldloc.0 - IL_0015: newobj t@9-2::.ctor - IL_001a: tail. - IL_001c: call HighPriority::TaskBuilderBase.Bind - IL_0021: ret - -t@9-2::Invoke - - IL_0000: ldarg.1 - IL_0001: stloc.0 + IL_009b: ldc.i4.2 + IL_009c: call Task::FromResult + IL_00a1: stloc.s 8 + IL_00a3: ldarg.0 + IL_00a4: ldloc.s 8 + IL_00a6: callvirt GetAwaiter + IL_00ab: stfld t@6::awaiter + IL_00b0: ldc.i4.1 + IL_00b1: stloc.s 9 + IL_00b3: ldarg.0 + IL_00b4: ldflda t@6::awaiter + IL_00b9: call get_IsCompleted + IL_00be: brfalse.s IL_00c2 + IL_00c0: br.s IL_00db + + + IL_00c2: ldc.i4.0 + IL_00c3: brfalse.s IL_00c9 + + + IL_00c5: ldc.i4.1 + + + IL_00c6: nop + IL_00c7: br.s IL_00d2 + + + IL_00c9: ldarg.0 + IL_00ca: ldc.i4.2 + IL_00cb: stfld t@6::ResumptionPoint + IL_00d0: ldc.i4.0 + + + IL_00d1: nop + IL_00d2: stloc.s 10 + IL_00d4: ldloc.s 10 + IL_00d6: stloc.s 9 + + + IL_00d8: nop + IL_00d9: br.s IL_00dc + + + IL_00db: nop + IL_00dc: ldloc.s 9 + IL_00de: brfalse.s IL_0111 + + + IL_00e0: ldarg.0 + IL_00e1: ldflda t@6::awaiter + IL_00e6: call GetResult + IL_00eb: stloc.s 11 + IL_00ed: ldloc.s 11 + IL_00ef: stloc.s 12 + IL_00f1: ldloc.s 12 + IL_00f3: stloc.s 13 (9,9-9,21) return x + y - IL_0002: ldarg.0 - IL_0003: ldfld t@9-2::builder@ - IL_0008: ldarg.0 - IL_0009: ldfld t@9-2::x - IL_000e: ldloc.0 - IL_000f: add - IL_0010: tail. - IL_0012: callvirt TaskBuilderBase::Return - IL_0017: ret - -t@9::Invoke - (7,9-7,36) let! x = Task.FromResult(1) - IL_0000: ldarg.0 - IL_0001: ldfld t@9::builder@ - IL_0006: ldc.i4.1 - IL_0007: call Task::FromResult - IL_000c: ldarg.0 - IL_000d: ldfld t@9::builder@ - IL_0012: newobj t@8-1::.ctor - IL_0017: tail. - IL_0019: call HighPriority::TaskBuilderBase.Bind - IL_001e: ret + IL_00f5: ldarg.0 + IL_00f6: ldfld t@6::x + IL_00fb: ldloc.s 13 + IL_00fd: add + IL_00fe: stloc.s 14 + IL_0100: ldarg.0 + IL_0101: ldflda t@6::Data + IL_0106: ldloc.s 14 + IL_0108: stfld Result + IL_010d: ldc.i4.1 + + + IL_010e: nop + IL_010f: br.s IL_012a + + + IL_0111: ldarg.0 + IL_0112: ldflda t@6::Data + IL_0117: ldflda MethodBuilder + IL_011c: ldarg.0 + IL_011d: ldflda t@6::awaiter + IL_0122: ldarg.0 + IL_0123: call AwaitUnsafeOnCompleted + IL_0128: ldc.i4.0 + + + IL_0129: nop + IL_012a: brfalse.s IL_0138 + + + IL_012c: ldarg.0 + IL_012d: ldloc.s 15 + IL_012f: stfld t@6::awaiter + IL_0134: ldc.i4.1 + + + IL_0135: nop + IL_0136: br.s IL_013a + + + IL_0138: ldc.i4.0 + + + IL_0139: nop + IL_013a: brfalse.s IL_0147 + + + IL_013c: ldarg.0 + IL_013d: ldc.i4.0 + IL_013e: stfld t@6::x + IL_0143: ldc.i4.1 + + + IL_0144: nop + IL_0145: br.s IL_0164 + + + IL_0147: ldc.i4.0 + + + IL_0148: nop + IL_0149: br.s IL_0164 + + + IL_014b: ldarg.0 + IL_014c: ldflda t@6::Data + IL_0151: ldflda MethodBuilder + IL_0156: ldarg.0 + IL_0157: ldflda t@6::awaiter0 + IL_015c: ldarg.0 + IL_015d: call AwaitUnsafeOnCompleted + IL_0162: ldc.i4.0 + + + IL_0163: nop + IL_0164: brfalse.s IL_0172 + + + IL_0166: ldarg.0 + IL_0167: ldloc.s 16 + IL_0169: stfld t@6::awaiter0 + IL_016e: ldc.i4.1 + + + IL_016f: nop + IL_0170: br.s IL_0174 + + + IL_0172: ldc.i4.0 + + + IL_0173: nop + IL_0174: stloc.2 + IL_0175: ldloc.2 + IL_0176: brfalse.s IL_0195 + + + IL_0178: ldarg.0 + IL_0179: ldflda t@6::Data + IL_017e: ldflda MethodBuilder + IL_0183: ldarg.0 + IL_0184: ldflda t@6::Data + IL_0189: ldfld Result + IL_018e: call SetResult + IL_0193: leave.s IL_01a3 + + + IL_0195: leave.s IL_01a3 + IL_0197: castclass Exception + IL_019c: stloc.s 17 + IL_019e: ldloc.s 17 + IL_01a0: stloc.1 + IL_01a1: leave.s IL_01a3 + + + IL_01a3: ldloc.1 + IL_01a4: stloc.s 18 + IL_01a6: ldloc.s 18 + IL_01a8: brtrue.s IL_01ab + + + IL_01aa: ret + + + IL_01ab: ldarg.0 + IL_01ac: ldflda t@6::Data + IL_01b1: ldflda MethodBuilder + IL_01b6: ldloc.s 18 + IL_01b8: call SetException + IL_01bd: ret diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 03.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 03.bsl index d2ae10311bc..b00a66ad8a1 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 03.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/Resumable 03.bsl @@ -26,36 +26,39 @@ Test::g Test::main (19,5-19,25) let r = g (S()) - IL_0000: ldloc.1 - IL_0001: call Test::g - IL_0006: stloc.0 + IL_0000: ldloca.s 2 + IL_0002: initobj r@19 + IL_0008: ldloca.s 2 + IL_000a: stloc.3 + IL_000b: ldc.i4.s 42 + IL_000d: stloc.0 (20,5-20,19) if r = 42 then - IL_0007: ldloc.0 - IL_0008: ldc.i4.s 42 - IL_000a: bne.un.s IL_000e + IL_000e: ldloc.0 + IL_000f: ldc.i4.s 42 + IL_0011: bne.un.s IL_0015 (20,20-20,21) 0 - IL_000c: ldc.i4.0 - IL_000d: ret + IL_0013: ldc.i4.0 + IL_0014: ret (20,27-20,28) 1 - IL_000e: ldc.i4.1 - IL_000f: ret + IL_0015: ldc.i4.1 + IL_0016: ret S`1::Equals IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: isinst 0x1b000003 + IL_0003: isinst 0x1b000004 IL_0008: ldnull IL_0009: cgt.un IL_000b: brfalse.s IL_001d IL_000d: ldarg.1 - IL_000e: unbox.any 0x1b000003 + IL_000e: unbox.any 0x1b000004 IL_0013: stloc.1 IL_0014: ldarg.0 IL_0015: ldloc.1 @@ -76,14 +79,14 @@ S`1::Equals IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: isinst 0x1b000003 + IL_0003: isinst 0x1b000004 IL_0008: ldnull IL_0009: cgt.un IL_000b: brfalse.s IL_001c IL_000d: ldarg.1 - IL_000e: unbox.any 0x1b000003 + IL_000e: unbox.any 0x1b000004 IL_0013: stloc.1 IL_0014: ldarg.0 IL_0015: ldloc.1 diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 13 - Witness - Struct with ResumableCode and partially resolved type args.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 13 - Witness - Struct with ResumableCode and partially resolved type args.bsl index 25137313f09..549a83f3c2a 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 13 - Witness - Struct with ResumableCode and partially resolved type args.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 13 - Witness - Struct with ResumableCode and partially resolved type args.bsl @@ -39,43 +39,32 @@ Test::f$W Test::g (15,19-15,26) f (S()) - IL_0000: ldsfld @_instance - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.1 - IL_0008: tail. - IL_000a: callvirt Invoke - IL_000f: ret + IL_0000: ldloc.0 + IL_0001: newobj .ctor + IL_0006: ldftn Invoke + IL_000c: newobj .ctor + IL_0011: ret Test::g$W (15,19-15,26) f (S()) IL_0000: ldarg.0 - IL_0001: newobj .ctor - IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: ldloc.1 - IL_0009: tail. - IL_000b: callvirt Invoke - IL_0010: ret + IL_0001: ldloc.0 + IL_0002: newobj .ctor + IL_0007: ldftn Invoke + IL_000d: newobj .ctor + IL_0012: ret Test::main (19,35-19,39) g () - IL_0000: call Test::__debug@19 - IL_0005: pop + IL_0000: ldloc.0 + IL_0001: newobj main@19::.ctor + IL_0006: ldftn main@19::Invoke + IL_000c: newobj .ctor + IL_0011: pop (20,5-20,6) 0 - IL_0006: ldc.i4.0 - IL_0007: ret - -Test::__debug@19 - (15,19-15,26) f (S()) - IL_0000: ldsfld main@9::@_instance - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.1 - IL_0008: tail. - IL_000a: callvirt Invoke - IL_000f: ret + IL_0012: ldc.i4.0 + IL_0013: ret S::Equals @@ -133,32 +122,6 @@ D::Bar IL_0000: ldc.i4.1 IL_0001: ret -g@9::Invoke - (10,26-13,6) (fun sm -> (^A: (member Foo: unit -> unit) x) (^B: (member Bar: unit -> bool) sm.Data) ) - IL_0000: ldarg.1 - IL_0001: newobj .ctor - IL_0006: ldftn Invoke - IL_000c: newobj .ctor - IL_0011: ret - -g@9-2::Invoke - (10,26-13,6) (fun sm -> (^A: (member Foo: unit -> unit) x) (^B: (member Bar: unit -> bool) sm.Data) ) - IL_0000: ldarg.0 - IL_0001: ldfld bar - IL_0006: ldarg.1 - IL_0007: newobj .ctor - IL_000c: ldftn Invoke - IL_0012: newobj .ctor - IL_0017: ret - -main@9::Invoke - (10,26-13,6) (fun sm -> (^A: (member Foo: unit -> unit) x) (^B: (member Bar: unit -> bool) sm.Data) ) - IL_0000: ldarg.1 - IL_0001: newobj main@10-1::.ctor - IL_0006: ldftn main@10-1::Invoke - IL_000c: newobj .ctor - IL_0011: ret - f@10::Invoke (11,9-11,43) (^A: (member Foo: unit -> unit) x) IL_0000: ldc.i4.0 @@ -193,44 +156,3 @@ f@10-1::Invoke IL_001e: tail. IL_0020: callvirt Invoke IL_0025: ret - -g@10-1::Invoke - (11,9-11,43) (^A: (member Foo: unit -> unit) x) - IL_0000: ldarg.0 - IL_0001: ldflda x - IL_0006: call S::Foo - IL_000b: nop - - (12,9-12,49) (^B: (member Bar: unit -> bool) sm.Data) - IL_000c: ldstr "Dynamic invocation of Bar is not supported" - IL_0011: newobj NotSupportedException::.ctor - IL_0016: throw - -g@10-3::Invoke - (11,9-11,43) (^A: (member Foo: unit -> unit) x) - IL_0000: ldarg.0 - IL_0001: ldflda x - IL_0006: call S::Foo - IL_000b: nop - - (12,9-12,49) (^B: (member Bar: unit -> bool) sm.Data) - IL_000c: ldarg.0 - IL_000d: ldfld bar - IL_0012: ldarg.1 - IL_0013: ldfld Data - IL_0018: tail. - IL_001a: callvirt Invoke - IL_001f: ret - -main@10-1::Invoke - (11,9-11,43) (^A: (member Foo: unit -> unit) x) - IL_0000: ldarg.0 - IL_0001: ldflda main@10-1::x - IL_0006: call S::Foo - IL_000b: nop - - (12,9-12,49) (^B: (member Bar: unit -> bool) sm.Data) - IL_000c: ldarg.1 - IL_000d: ldfld Data - IL_0012: callvirt D::Bar - IL_0017: ret diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 14 - StateMachine with unresolved trait from composed inline function.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 14 - StateMachine with unresolved trait from composed inline function.bsl index aceb51ead83..8c3aca87f16 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 14 - StateMachine with unresolved trait from composed inline function.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall/SRTP 14 - StateMachine with unresolved trait from composed inline function.bsl @@ -41,60 +41,64 @@ Test::g Test::h (19,18-19,25) g (f a) IL_0000: ldsfld @_instance - IL_0005: stloc.0 - IL_0006: ldloc.0 + IL_0005: stloc.1 + IL_0006: ldloc.1 IL_0007: ldarg.0 IL_0008: callvirt Invoke - IL_000d: tail. - IL_000f: call Test::g - IL_0014: ret + IL_000d: stloc.0 + IL_000e: ldloca.s 2 + IL_0010: initobj h@19-1 + IL_0016: ldloca.s 2 + IL_0018: stloc.3 + IL_0019: ldc.i4.0 + IL_001a: ret Test::h$W (19,18-19,25) g (f a) IL_0000: ldarg.0 IL_0001: newobj .ctor - IL_0006: stloc.0 - IL_0007: ldloc.0 + IL_0006: stloc.1 + IL_0007: ldloc.1 IL_0008: ldarg.1 IL_0009: callvirt Invoke - IL_000e: tail. - IL_0010: call Test::g - IL_0015: ret + IL_000e: stloc.0 + IL_000f: ldloca.s 2 + IL_0011: initobj h@19-3 + IL_0017: ldloca.s 2 + IL_0019: stloc.3 + IL_001a: ldc.i4.0 + IL_001b: ret Test::main (23,13-23,25) h (S()) - IL_0000: ldloc.0 - IL_0001: call Test::__debug@23 - IL_0006: pop + IL_0000: ldsfld main@23::@_instance + IL_0005: stloc.2 + IL_0006: ldloc.2 + IL_0007: ldloc.0 + IL_0008: callvirt Invoke + IL_000d: stloc.1 + IL_000e: ldloca.s 3 + IL_0010: initobj main@23-1 + IL_0016: ldloca.s 3 + IL_0018: stloc.s 4 (24,5-24,6) 0 - IL_0007: ldc.i4.0 - IL_0008: ret - -Test::__debug@23 - (19,18-19,25) g (f a) - IL_0000: ldsfld main@9::@_instance - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldarg.0 - IL_0008: callvirt Invoke - IL_000d: tail. - IL_000f: call Test::g - IL_0014: ret + IL_001a: ldc.i4.0 + IL_001b: ret S`1::Equals IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: isinst 0x1b000008 + IL_0003: isinst 0x1b00000a IL_0008: ldnull IL_0009: cgt.un IL_000b: brfalse.s IL_001d IL_000d: ldarg.1 - IL_000e: unbox.any 0x1b000008 + IL_000e: unbox.any 0x1b00000a IL_0013: stloc.1 IL_0014: ldarg.0 IL_0015: ldloc.1 @@ -115,14 +119,14 @@ S`1::Equals IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: isinst 0x1b000008 + IL_0003: isinst 0x1b00000a IL_0008: ldnull IL_0009: cgt.un IL_000b: brfalse.s IL_001c IL_000d: ldarg.1 - IL_000e: unbox.any 0x1b000008 + IL_000e: unbox.any 0x1b00000a IL_0013: stloc.1 IL_0014: ldarg.0 IL_0015: ldloc.1 @@ -138,12 +142,7 @@ h@9::Invoke IL_0000: ldloc.0 IL_0001: ret -h@9-1::Invoke - (9,104-9,123) Unchecked.defaultof - IL_0000: ldloc.0 - IL_0001: ret - -main@9::Invoke +h@9-2::Invoke (9,104-9,123) Unchecked.defaultof IL_0000: ldloc.0 IL_0001: ret diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs index c4002767e55..b8d8de1aadd 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs @@ -8,6 +8,127 @@ open FSharp.Test.Compiler module StateMachineTests = + [] + let ``SRTP await helpers preserve generic state machine captures in Debug`` () = + FSharp """ +open System.Runtime.CompilerServices +open System.Threading.Tasks +open Microsoft.FSharp.Control +open Microsoft.FSharp.Core.CompilerServices + +#nowarn "3513" +#nowarn "1204" + +type Helper = + static member inline Await(builder: byref< ^Builder>, awaiter: byref< ^Awaiter>, sm: byref< ^StateMachine>) = + (^Builder: (member AwaitUnsafeOnCompleted: byref< ^Awaiter> * byref< ^StateMachine> -> unit) + (builder, &awaiter, &sm)) + +[] +type CustomAwaitable = CustomAwaitable of YieldAwaitable + +type TaskBuilderBase with + member inline _.Bind(CustomAwaitable value, continuation: unit -> TaskCode<'T, 'U>) = + TaskCode<'T, 'U>(fun sm -> + if __useResumableCode then + let mutable awaiter = value.GetAwaiter() + let mutable __stack_fin = true + if not awaiter.IsCompleted then + let __stack_yield_fin = ResumableCode.Yield().Invoke(&sm) + __stack_fin <- __stack_yield_fin + if __stack_fin then + awaiter.GetResult() + (continuation ()).Invoke(&sm) + else + Helper.Await(&sm.Data.MethodBuilder, &awaiter, &sm) + false + else + failwith "unexpected dynamic fallback") + +let fakeWork value (items: ResizeArray<_>) = + task { + items.Add value + do! CustomAwaitable(Task.Yield()) + items.Add value + } + +[] +let main _ = + let items = ResizeArray() + fakeWork 1 items |> fun work -> work.GetAwaiter().GetResult() + if Seq.toList items <> [1; 1] then failwithf "Unexpected captures: %A" items + 0 +""" + |> withDebug + |> withNoOptimize + |> withFSharpCoreShippedNet + |> compileExeAndRun + |> shouldSucceed + + [] + [] + [] + [] + [] + let ``Resumable builders and combinators inline across assemblies`` (optimizeLibrary, optimizeConsumer) = + let library = + FSharp """ +module ResumableLibrary + +open System.Runtime.CompilerServices +open Microsoft.FSharp.Core.CompilerServices +open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers + +#nowarn "3513" + +let inline finish (sm: byref<'SM> when 'SM :> IAsyncStateMachine and 'SM :> IResumableStateMachine) = + sm.MoveNext() + sm.Data + +let inline step () = + ResumableCode(fun sm -> + if __useResumableCode then + sm.Data <- sm.Data + 21 + true + else + failwith "unexpected combinator fallback") + +type Builder() = + member inline _.Run(code: ResumableCode) = + if __useResumableCode then + __stateMachine + (MoveNextMethodImpl<_>(fun sm -> + code.Invoke(&sm) |> ignore)) + (SetStateMachineMethodImpl<_>(fun _ _ -> ())) + (AfterCode<_, _>(fun sm -> finish &sm)) + else + failwith "unexpected dynamic fallback" + +let builder = Builder() + +let inline run () = + if __useResumableCode then + builder.Run(ResumableCode.Combine(step(), step())) + else + failwith "unexpected wrapper fallback" +""" + |> withName "ResumableLibrary" + |> withDebug + |> withOptions [if optimizeLibrary then "--optimize+" else "--optimize-"] + |> asLibrary + + FSharp """ +[] +let main _ = + if ResumableLibrary.run() = 42 then 0 else 1 +""" + |> withReferences [library] + |> withDebug + |> withOptions [if optimizeConsumer then "--optimize+" else "--optimize-"] + |> compileExeAndRun + |> shouldSucceed + |> withExitCode 0 + let verifyOptimizedAndRun code = Fsx code |> withOptimize diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs index c821a9e3996..dbdac18c609 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs @@ -36,61 +36,68 @@ let testTask() = task { return 1 } """, (fun verifier -> verifier.VerifyIL [ """ -.class public abstract auto ansi sealed Test - extends [runtime]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit testTask@4 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed + .method public strict virtual instance void MoveNext() cil managed { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_000d: ret - } + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,int32> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + int32 V_3, + class [runtime]System.Exception V_4, + class [runtime]System.Exception V_5) IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0006: ldc.i4.1 - IL_0007: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Return(!!0) - IL_000c: ret - } - - } - - .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed - { - - .maxstack 5 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder V_0) - IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderModule::get_task() - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.0 - IL_0008: ldloc.0 - IL_0009: newobj instance void Test/testTask@4::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_000e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0013: callvirt instance class [runtime]System.Threading.Tasks.Task`1 [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder::Run(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0>) - IL_0018: ret - } - -} + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.1 + IL_0008: stloc.3 + IL_0009: ldarg.0 + IL_000a: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_000f: ldloc.3 + IL_0010: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0015: ldc.i4.1 + IL_0016: stloc.2 + IL_0017: ldloc.2 + IL_0018: brfalse.s IL_0037 + + IL_001a: ldarg.0 + IL_001b: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0020: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0025: ldarg.0 + IL_0026: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_002b: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0030: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0035: leave.s IL_0045 + + IL_0037: leave.s IL_0045 + + } + catch [runtime]System.Object + { + IL_0039: castclass [runtime]System.Exception + IL_003e: stloc.s V_4 + IL_0040: ldloc.s V_4 + IL_0042: stloc.1 + IL_0043: leave.s IL_0045 + + } + IL_0045: ldloc.1 + IL_0046: stloc.s V_5 + IL_0048: ldloc.s V_5 + IL_004a: brtrue.s IL_004d + + IL_004c: ret + + IL_004d: ldarg.0 + IL_004e: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0053: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0058: ldloc.s V_5 + IL_005a: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_005f: ret + } """ ])) @@ -190,112 +197,169 @@ let testTask(t: Task) = task { let! res = t in return res+1 } """, (fun verifier -> verifier.VerifyIL [ """ -.class public abstract auto ansi sealed Test - extends [runtime]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@4-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed + .method public strict virtual instance void MoveNext() cil managed { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-1'::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,int32> Invoke(int32 _arg1) cil managed - { - - .maxstack 7 - .locals init (int32 V_0) - IL_0000: ldarg.1 - IL_0001: stloc.0 - IL_0002: ldarg.0 - IL_0003: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-1'::builder@ - IL_0008: ldloc.0 - IL_0009: ldc.i4.1 - IL_000a: add - IL_000b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Return(!!0) - IL_0010: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit testTask@4 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>> - { - .field public class [runtime]System.Threading.Tasks.Task`1 t - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [runtime]System.Threading.Tasks.Task`1 t, class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [runtime]System.Threading.Tasks.Task`1 Test/testTask@4::t - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0014: ret - } + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,int32> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 + .maxstack 5 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + class [runtime]System.Threading.Tasks.Task`1 V_3, + bool V_4, + bool V_5, + int32 V_6, + int32 V_7, + int32 V_8, + int32 V_9, + valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 V_10, + class [runtime]System.Exception V_11, + class [runtime]System.Exception V_12) IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0006: ldarg.0 - IL_0007: ldfld class [runtime]System.Threading.Tasks.Task`1 Test/testTask@4::t - IL_000c: ldarg.0 - IL_000d: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0012: newobj instance void Test/'testTask@4-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_0017: call class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!2> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority::TaskBuilderBase.Bind(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase, - class [runtime]System.Threading.Tasks.Task`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!2>>) - IL_001c: ret - } - - } + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: sub + IL_000a: switch ( + IL_0015) + IL_0013: br.s IL_0018 - .method public static class [runtime]System.Threading.Tasks.Task`1 testTask(class [runtime]System.Threading.Tasks.Task`1 t) cil managed - { - - .maxstack 6 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder V_0) - IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderModule::get_task() - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.0 - IL_0008: ldarg.0 - IL_0009: ldloc.0 - IL_000a: newobj instance void Test/testTask@4::.ctor(class [runtime]System.Threading.Tasks.Task`1, - class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_000f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0014: callvirt instance class [runtime]System.Threading.Tasks.Task`1 [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder::Run(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0>) - IL_0019: ret - } + IL_0015: nop + IL_0016: br.s IL_0019 -} + IL_0018: nop + .try + { + IL_0019: ldloc.0 + IL_001a: ldc.i4.1 + IL_001b: sub + IL_001c: switch ( + IL_0027) + IL_0025: br.s IL_002a + + IL_0027: nop + IL_0028: br.s IL_0053 + + IL_002a: nop + IL_002b: ldarg.0 + IL_002c: ldfld class [runtime]System.Threading.Tasks.Task`1 Test/testTask@4::t + IL_0031: stloc.3 + IL_0032: ldarg.0 + IL_0033: ldloc.3 + IL_0034: callvirt instance valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 class [netstandard]System.Threading.Tasks.Task`1::GetAwaiter() + IL_0039: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_003e: ldc.i4.1 + IL_003f: stloc.s V_4 + IL_0041: ldarg.0 + IL_0042: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_0047: call instance bool valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::get_IsCompleted() + IL_004c: brfalse.s IL_0050 + + IL_004e: br.s IL_0069 + + IL_0050: ldc.i4.0 + IL_0051: brfalse.s IL_0057 + + IL_0053: ldc.i4.1 + IL_0054: nop + IL_0055: br.s IL_0060 + + IL_0057: ldarg.0 + IL_0058: ldc.i4.1 + IL_0059: stfld int32 Test/testTask@4::ResumptionPoint + IL_005e: ldc.i4.0 + IL_005f: nop + IL_0060: stloc.s V_5 + IL_0062: ldloc.s V_5 + IL_0064: stloc.s V_4 + IL_0066: nop + IL_0067: br.s IL_006a + + IL_0069: nop + IL_006a: ldloc.s V_4 + IL_006c: brfalse.s IL_009a + + IL_006e: ldarg.0 + IL_006f: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_0074: call instance !0 valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::GetResult() + IL_0079: stloc.s V_6 + IL_007b: ldloc.s V_6 + IL_007d: stloc.s V_7 + IL_007f: ldloc.s V_7 + IL_0081: stloc.s V_8 + IL_0083: ldloc.s V_8 + IL_0085: ldc.i4.1 + IL_0086: add + IL_0087: stloc.s V_9 + IL_0089: ldarg.0 + IL_008a: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_008f: ldloc.s V_9 + IL_0091: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0096: ldc.i4.1 + IL_0097: nop + IL_0098: br.s IL_00b3 + + IL_009a: ldarg.0 + IL_009b: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_00a0: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_00a5: ldarg.0 + IL_00a6: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_00ab: ldarg.0 + IL_00ac: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompleted,valuetype Test/testTask@4>(!!0&, + !!1&) + IL_00b1: ldc.i4.0 + IL_00b2: nop + IL_00b3: brfalse.s IL_00c1 + + IL_00b5: ldarg.0 + IL_00b6: ldloc.s V_10 + IL_00b8: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 Test/testTask@4::awaiter + IL_00bd: ldc.i4.1 + IL_00be: nop + IL_00bf: br.s IL_00c3 + + IL_00c1: ldc.i4.0 + IL_00c2: nop + IL_00c3: stloc.2 + IL_00c4: ldloc.2 + IL_00c5: brfalse.s IL_00e4 + + IL_00c7: ldarg.0 + IL_00c8: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_00cd: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_00d2: ldarg.0 + IL_00d3: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_00d8: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_00dd: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_00e2: leave.s IL_00f2 + + IL_00e4: leave.s IL_00f2 + + } + catch [runtime]System.Object + { + IL_00e6: castclass [runtime]System.Exception + IL_00eb: stloc.s V_11 + IL_00ed: ldloc.s V_11 + IL_00ef: stloc.1 + IL_00f0: leave.s IL_00f2 + + } + IL_00f2: ldloc.1 + IL_00f3: stloc.s V_12 + IL_00f5: ldloc.s V_12 + IL_00f7: brtrue.s IL_00fa + + IL_00f9: ret + + IL_00fa: ldarg.0 + IL_00fb: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0100: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0105: ldloc.s V_12 + IL_0107: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_010c: ret + } """ ])) @@ -421,139 +485,111 @@ let testTask() = task { try 1+1 finally System.Console.WriteLine("finally") } """, (fun verifier -> verifier.VerifyIL [ """ -.class public abstract auto ansi sealed Test - extends [runtime]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit testTask@4 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed + .method public strict virtual instance void MoveNext() cil managed { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0006: ldarg.0 - IL_0007: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_000c: ldarg.0 - IL_000d: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0012: newobj instance void Test/'testTask@4-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_0017: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_001c: ldsfld class Test/'testTask@4-2' Test/'testTask@4-2'::@_instance - IL_0021: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::TryFinally(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1>, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0026: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@4-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-1'::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-1'::builder@ - IL_0007: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Zero() - IL_000c: ret - } - - } + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@4-2' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 - { - .field static assembly initonly class Test/'testTask@4-2' @_instance - .method assembly specialname rtspecialname instance void .ctor() cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_3, + bool V_4, + bool V_5, + class [runtime]System.Exception V_6, + bool V_7, + bool V_8, + class [runtime]System.Exception V_9, + class [runtime]System.Exception V_10) IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() - IL_0006: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 - IL_0000: nop - IL_0001: ldstr "finally" - IL_0006: call void [runtime]System.Console::WriteLine(string) - IL_000b: ldnull - IL_000c: ret - } - - .method private specialname rtspecialname static void .cctor() cil managed - { - - .maxstack 10 - IL_0000: newobj instance void Test/'testTask@4-2'::.ctor() - IL_0005: stsfld class Test/'testTask@4-2' Test/'testTask@4-2'::@_instance - IL_000a: ret - } - - } + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldsfld class Test/'testTask@4-1' Test/'testTask@4-1'::@_instance + IL_000c: stloc.3 + IL_000d: ldc.i4.0 + IL_000e: stloc.s V_4 + .try + { + IL_0010: nop + IL_0011: ldc.i4.1 + IL_0012: stloc.s V_5 + IL_0014: ldloc.s V_5 + IL_0016: stloc.s V_4 + IL_0018: leave.s IL_0037 - .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed - { - - .maxstack 5 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder V_0) - IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderModule::get_task() - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.0 - IL_0008: ldloc.0 - IL_0009: newobj instance void Test/testTask@4::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_000e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0013: callvirt instance class [runtime]System.Threading.Tasks.Task`1 [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder::Run(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0>) - IL_0018: ret - } + } + catch [runtime]System.Object + { + IL_001a: castclass [runtime]System.Exception + IL_001f: stloc.s V_6 + IL_0021: ldloc.3 + IL_0022: ldnull + IL_0023: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0028: pop + IL_0029: ldc.i4.1 + IL_002a: stloc.s V_7 + IL_002c: rethrow + IL_002e: ldnull + IL_002f: unbox.any [FSharp.Core]Microsoft.FSharp.Core.Unit + IL_0034: pop + IL_0035: leave.s IL_0037 -} + } + IL_0037: ldloc.s V_4 + IL_0039: brfalse.s IL_0049 + + IL_003b: ldloc.3 + IL_003c: ldnull + IL_003d: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0042: pop + IL_0043: ldc.i4.1 + IL_0044: stloc.s V_8 + IL_0046: nop + IL_0047: br.s IL_004a + + IL_0049: nop + IL_004a: ldloc.s V_4 + IL_004c: stloc.2 + IL_004d: ldloc.2 + IL_004e: brfalse.s IL_006d + + IL_0050: ldarg.0 + IL_0051: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0056: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_005b: ldarg.0 + IL_005c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0061: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0066: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_006b: leave.s IL_007b + + IL_006d: leave.s IL_007b + + } + catch [runtime]System.Object + { + IL_006f: castclass [runtime]System.Exception + IL_0074: stloc.s V_9 + IL_0076: ldloc.s V_9 + IL_0078: stloc.1 + IL_0079: leave.s IL_007b + + } + IL_007b: ldloc.1 + IL_007c: stloc.s V_10 + IL_007e: ldloc.s V_10 + IL_0080: brtrue.s IL_0083 + + IL_0082: ret + + IL_0083: ldarg.0 + IL_0084: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0089: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_008e: ldloc.s V_10 + IL_0090: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0095: ret + } """ ])) @@ -683,142 +719,109 @@ let testTask() = task { try 1 with e -> System.Console.WriteLine("with"); 2 } """, (fun verifier -> verifier.VerifyIL [ """ -.class public abstract auto ansi sealed Test - extends [runtime]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@4-2' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-2'::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [runtime]System.Exception _arg1) cil managed - { - - .maxstack 5 - .locals init (class [runtime]System.Exception V_0) - IL_0000: ldarg.1 - IL_0001: stloc.0 - IL_0002: ldstr "with" - IL_0007: call void [runtime]System.Console::WriteLine(string) - IL_000c: ldarg.0 - IL_000d: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-2'::builder@ - IL_0012: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Zero() - IL_0017: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit testTask@4 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + .method public strict virtual instance void MoveNext() cil managed { - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0006: ldarg.0 - IL_0007: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_000c: ldarg.0 - IL_000d: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0012: newobj instance void Test/'testTask@4-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_0017: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_001c: ldarg.0 - IL_001d: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@4::builder@ - IL_0022: newobj instance void Test/'testTask@4-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_0027: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::TryWith(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1>, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_002c: ret - } - - } + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@4-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + bool V_3, + bool V_4, + class [runtime]System.Exception V_5, + bool V_6, + class [runtime]System.Exception V_7, + class [runtime]System.Exception V_8, + class [runtime]System.Exception V_9, + class [runtime]System.Exception V_10, + class [runtime]System.Exception V_11) IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-1'::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 - IL_0000: nop - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@4-1'::builder@ - IL_0007: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Zero() - IL_000c: ret - } + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldc.i4.0 + IL_0008: stloc.3 + IL_0009: ldc.i4.0 + IL_000a: stloc.s V_4 + IL_000c: ldnull + IL_000d: stloc.s V_5 + .try + { + IL_000f: nop + IL_0010: ldc.i4.1 + IL_0011: stloc.s V_6 + IL_0013: ldloc.s V_6 + IL_0015: stloc.3 + IL_0016: leave.s IL_0028 - } + } + catch [runtime]System.Object + { + IL_0018: castclass [runtime]System.Exception + IL_001d: stloc.s V_7 + IL_001f: ldc.i4.1 + IL_0020: stloc.s V_4 + IL_0022: ldloc.s V_7 + IL_0024: stloc.s V_5 + IL_0026: leave.s IL_0028 - .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed - { - - .maxstack 5 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder V_0) - IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderModule::get_task() - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.0 - IL_0008: ldloc.0 - IL_0009: newobj instance void Test/testTask@4::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_000e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0013: callvirt instance class [runtime]System.Threading.Tasks.Task`1 [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder::Run(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0>) - IL_0018: ret - } + } + IL_0028: ldloc.s V_4 + IL_002a: brfalse.s IL_0042 + + IL_002c: ldloc.s V_5 + IL_002e: stloc.s V_8 + IL_0030: ldloc.s V_8 + IL_0032: stloc.s V_9 + IL_0034: ldstr "with" + IL_0039: call void [runtime]System.Console::WriteLine(string) + IL_003e: ldc.i4.1 + IL_003f: nop + IL_0040: br.s IL_0044 -} + IL_0042: ldloc.3 + IL_0043: nop + IL_0044: stloc.2 + IL_0045: ldloc.2 + IL_0046: brfalse.s IL_0065 + + IL_0048: ldarg.0 + IL_0049: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_004e: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0053: ldarg.0 + IL_0054: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0059: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_005e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0063: leave.s IL_0073 + + IL_0065: leave.s IL_0073 + + } + catch [runtime]System.Object + { + IL_0067: castclass [runtime]System.Exception + IL_006c: stloc.s V_10 + IL_006e: ldloc.s V_10 + IL_0070: stloc.1 + IL_0071: leave.s IL_0073 + + } + IL_0073: ldloc.1 + IL_0074: stloc.s V_11 + IL_0076: ldloc.s V_11 + IL_0078: brtrue.s IL_007b + + IL_007a: ret + + IL_007b: ldarg.0 + IL_007c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0081: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0086: ldloc.s V_11 + IL_0088: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_008d: ret + } """ ])) @@ -934,184 +937,91 @@ let testTask() = task { while x > 4 do System.Console.WriteLine("loop") } """, (fun verifier -> verifier.VerifyIL [ """ -.class public abstract auto ansi sealed Test - extends [runtime]System.Object -{ - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit testTask@5 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@5::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + .method public strict virtual instance void MoveNext() cil managed { - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@5::builder@ - IL_0006: ldsfld class Test/'testTask@5-1' Test/'testTask@5-1'::@_instance - IL_000b: ldarg.0 - IL_000c: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@5::builder@ - IL_0011: ldarg.0 - IL_0012: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/testTask@5::builder@ - IL_0017: newobj instance void Test/'testTask@5-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_001c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0021: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::While(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, - class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>) - IL_0026: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@5-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 - { - .field static assembly initonly class Test/'testTask@5-1' @_instance - .method assembly specialname rtspecialname instance void .ctor() cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() - IL_0006: ret - } - - .method public strict virtual instance bool Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 - IL_0000: call int32 Test::get_x() - IL_0005: ldc.i4.4 - IL_0006: cgt - IL_0008: ret - } - - .method private specialname rtspecialname static void .cctor() cil managed - { - - .maxstack 10 - IL_0000: newobj instance void Test/'testTask@5-1'::.ctor() - IL_0005: stsfld class Test/'testTask@5-1' Test/'testTask@5-1'::@_instance - IL_000a: ret - } - - } + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext - .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@5-2' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed - { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 + .maxstack 4 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_3, + bool V_4, + bool V_5, + class [runtime]System.Exception V_6, + class [runtime]System.Exception V_7) IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@5-2'::builder@ - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed - { - - .maxstack 8 - IL_0000: ldstr "loop" - IL_0005: call void [runtime]System.Console::WriteLine(string) - IL_000a: ldarg.0 - IL_000b: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder Test/'testTask@5-2'::builder@ - IL_0010: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,class [FSharp.Core]Microsoft.FSharp.Core.Unit> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Zero() - IL_0015: ret - } - - } - - .field static assembly int32 x@4 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .method public specialname static int32 get_x() cil managed - { - - .maxstack 8 - IL_0000: ldsfld int32 Test::x@4 - IL_0005: ret - } - - .method public specialname static void set_x(int32 'value') cil managed - { - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: stsfld int32 Test::x@4 - IL_0006: ret - } - - .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed - { - - .maxstack 5 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder V_0) - IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderModule::get_task() - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.0 - IL_0008: ldloc.0 - IL_0009: newobj instance void Test/testTask@5::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_000e: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0013: callvirt instance class [runtime]System.Threading.Tasks.Task`1 [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder::Run(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0>) - IL_0018: ret - } - - .method private specialname rtspecialname static void .cctor() cil managed - { - - .maxstack 8 - IL_0000: ldc.i4.0 - IL_0001: stsfld int32 ''.$Test::init@ - IL_0006: ldsfld int32 ''.$Test::init@ - IL_000b: pop - IL_000c: ret - } - - .method assembly static void staticInitialization@() cil managed - { - - .maxstack 8 - IL_0000: ldc.i4.1 - IL_0001: stsfld int32 Test::x@4 - IL_0006: ret - } - - .property int32 x() - { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) - .set void Test::set_x(int32) - .get int32 Test::get_x() - } -} + IL_0001: ldfld int32 Test/testTask@5::ResumptionPoint + IL_0006: stloc.0 + .try + { + IL_0007: ldsfld class Test/'testTask@5-1' Test/'testTask@5-1'::@_instance + IL_000c: stloc.3 + IL_000d: ldc.i4.1 + IL_000e: stloc.s V_4 + IL_0010: br.s IL_0025 + + IL_0012: ldstr "loop" + IL_0017: call void [runtime]System.Console::WriteLine(string) + IL_001c: ldc.i4.1 + IL_001d: stloc.s V_5 + IL_001f: ldloc.s V_5 + IL_0021: stloc.s V_4 + IL_0023: ldc.i4.0 + IL_0024: stloc.0 + IL_0025: ldloc.s V_4 + IL_0027: brfalse.s IL_0033 + + IL_0029: ldloc.3 + IL_002a: ldnull + IL_002b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0030: nop + IL_0031: br.s IL_0035 + + IL_0033: ldc.i4.0 + IL_0034: nop + IL_0035: brtrue.s IL_0012 + + IL_0037: ldloc.s V_4 + IL_0039: stloc.2 + IL_003a: ldloc.2 + IL_003b: brfalse.s IL_005a + + IL_003d: ldarg.0 + IL_003e: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0043: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0048: ldarg.0 + IL_0049: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_004e: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_0053: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_0058: leave.s IL_0068 + + IL_005a: leave.s IL_0068 + + } + catch [runtime]System.Object + { + IL_005c: castclass [runtime]System.Exception + IL_0061: stloc.s V_6 + IL_0063: ldloc.s V_6 + IL_0065: stloc.1 + IL_0066: leave.s IL_0068 + + } + IL_0068: ldloc.1 + IL_0069: stloc.s V_7 + IL_006b: ldloc.s V_7 + IL_006d: brtrue.s IL_0070 + + IL_006f: ret + + IL_0070: ldarg.0 + IL_0071: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0076: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_007b: ldloc.s V_7 + IL_007d: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_0082: ret + } """ ])) #endif @@ -1192,95 +1102,283 @@ type Generic1InGeneric1<'T>() = .class public abstract auto ansi sealed Test extends [runtime]System.Object { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) .class auto ansi serializable nested public beforefieldinit Generic1InGeneric1`1 extends [runtime]System.Object { - .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit clo@7 - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!A>> + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .class auto autochar sealed nested assembly beforefieldinit specialname clo@7 + extends [runtime]System.ValueType + implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, + class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Data + .field public int32 ResumptionPoint .field public class [runtime]System.Threading.Tasks.Task`1 computation - .field public class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@ - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [runtime]System.Threading.Tasks.Task`1 computation, class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder builder@) cil managed + .field public valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 awaiter + .method public strict virtual instance void MoveNext() cil managed { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 8 + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext + + .maxstack 5 + .locals init (int32 V_0, + class [runtime]System.Exception V_1, + bool V_2, + class [runtime]System.Threading.Tasks.Task`1 V_3, + bool V_4, + bool V_5, + !A V_6, + !A V_7, + valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 V_8, + class [runtime]System.Exception V_9, + class [runtime]System.Exception V_10) IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!A>>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [runtime]System.Threading.Tasks.Task`1 class Test/Generic1InGeneric1`1/clo@7::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder class Test/Generic1InGeneric1`1/clo@7::builder@ - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!A> Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + IL_0001: ldfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint + IL_0006: stloc.0 + IL_0007: ldloc.0 + IL_0008: ldc.i4.1 + IL_0009: sub + IL_000a: switch ( + IL_0015) + IL_0013: br.s IL_0018 + + IL_0015: nop + IL_0016: br.s IL_001b + + IL_0018: nop + IL_0019: ldnull + IL_001a: stloc.1 + .try + { + IL_001b: ldloc.0 + IL_001c: ldc.i4.1 + IL_001d: sub + IL_001e: switch ( + IL_0029) + IL_0027: br.s IL_002c + + IL_0029: nop + IL_002a: br.s IL_0055 + + IL_002c: nop + IL_002d: ldarg.0 + IL_002e: ldfld class [runtime]System.Threading.Tasks.Task`1 valuetype Test/Generic1InGeneric1`1/clo@7::computation + IL_0033: stloc.3 + IL_0034: ldarg.0 + IL_0035: ldloc.3 + IL_0036: callvirt instance valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 class [netstandard]System.Threading.Tasks.Task`1::GetAwaiter() + IL_003b: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_0040: ldc.i4.1 + IL_0041: stloc.s V_4 + IL_0043: ldarg.0 + IL_0044: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_0049: call instance bool valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::get_IsCompleted() + IL_004e: brfalse.s IL_0052 + + IL_0050: br.s IL_006b + + IL_0052: ldc.i4.0 + IL_0053: brfalse.s IL_0059 + + IL_0055: ldc.i4.1 + IL_0056: nop + IL_0057: br.s IL_0062 + + IL_0059: ldarg.0 + IL_005a: ldc.i4.1 + IL_005b: stfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint + IL_0060: ldc.i4.0 + IL_0061: nop + IL_0062: stloc.s V_5 + IL_0064: ldloc.s V_5 + IL_0066: stloc.s V_4 + IL_0068: nop + IL_0069: br.s IL_006c + + IL_006b: nop + IL_006c: ldloc.s V_4 + IL_006e: brfalse.s IL_0092 + + IL_0070: ldarg.0 + IL_0071: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_0076: call instance !0 valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::GetResult() + IL_007b: stloc.s V_6 + IL_007d: ldloc.s V_6 + IL_007f: stloc.s V_7 + IL_0081: ldarg.0 + IL_0082: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0087: ldloc.s V_7 + IL_0089: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_008e: ldc.i4.1 + IL_008f: nop + IL_0090: br.s IL_00ab + + IL_0092: ldarg.0 + IL_0093: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0098: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_009d: ldarg.0 + IL_009e: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_00a3: ldarg.0 + IL_00a4: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompleted,valuetype Test/Generic1InGeneric1`1/clo@7>(!!0&, + !!1&) + IL_00a9: ldc.i4.0 + IL_00aa: nop + IL_00ab: brfalse.s IL_00c1 + + IL_00ad: ldarg.0 + IL_00ae: ldloca.s V_8 + IL_00b0: initobj valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 + IL_00b6: ldloc.s V_8 + IL_00b8: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_00bd: ldc.i4.1 + IL_00be: nop + IL_00bf: br.s IL_00c3 + + IL_00c1: ldc.i4.0 + IL_00c2: nop + IL_00c3: stloc.2 + IL_00c4: ldloc.2 + IL_00c5: brfalse.s IL_00e4 + + IL_00c7: ldarg.0 + IL_00c8: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_00cd: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_00d2: ldarg.0 + IL_00d3: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_00d8: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result + IL_00dd: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) + IL_00e2: leave.s IL_00f2 + + IL_00e4: leave.s IL_00f2 + + } + catch [runtime]System.Object + { + IL_00e6: castclass [runtime]System.Exception + IL_00eb: stloc.s V_9 + IL_00ed: ldloc.s V_9 + IL_00ef: stloc.1 + IL_00f0: leave.s IL_00f2 + + } + IL_00f2: ldloc.1 + IL_00f3: stloc.s V_10 + IL_00f5: ldloc.s V_10 + IL_00f7: brtrue.s IL_00fa + + IL_00f9: ret + + IL_00fa: ldarg.0 + IL_00fb: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0100: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0105: ldloc.s V_10 + IL_0107: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) + IL_010c: ret + } + + .method public strict virtual instance void SetStateMachine(class [runtime]System.Runtime.CompilerServices.IAsyncStateMachine state) cil managed { - + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine + .maxstack 8 IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder class Test/Generic1InGeneric1`1/clo@7::builder@ - IL_0006: ldarg.0 - IL_0007: ldfld class [runtime]System.Threading.Tasks.Task`1 class Test/Generic1InGeneric1`1/clo@7::computation - IL_000c: call class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderExtensions.HighPriority::TaskBuilderBase.ReturnFrom(class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase, - class [runtime]System.Threading.Tasks.Task`1) + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_000b: ldarg.1 + IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) IL_0011: ret - } + } - } + .method public strict virtual instance int32 get_ResumptionPoint() cil managed + { + .override method instance int32 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_ResumptionPoint() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint + IL_0006: ret + } + + .method public strict virtual instance valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 get_Data() cil managed + { + .override method instance !0 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_Data() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0006: ret + } + + .method public strict virtual instance void set_Data(valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 'value') cil managed + { + .override method instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::set_Data(!0) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0007: ret + } + + } .method public specialname rtspecialname instance void .ctor() cil managed { - + .maxstack 8 IL_0000: ldarg.0 IL_0001: callvirt instance void [runtime]System.Object::.ctor() IL_0006: ldarg.0 IL_0007: pop IL_0008: ret - } + } .method public hidebysig instance class [runtime]System.Threading.Tasks.Task`1 Run() cil managed { - + .maxstack 8 IL_0000: ldarg.0 IL_0001: ldc.i4.3 IL_0002: call class [runtime]System.Threading.Tasks.Task`1 [runtime]System.Threading.Tasks.Task::FromResult(!!0) IL_0007: callvirt instance class [runtime]System.Threading.Tasks.Task`1 class Test/Generic1InGeneric1`1::run(class [runtime]System.Threading.Tasks.Task`1) IL_000c: ret - } + } .method assembly hidebysig instance class [runtime]System.Threading.Tasks.Task`1 run(class [runtime]System.Threading.Tasks.Task`1 computation) cil managed { - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - - .maxstack 6 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder V_0) - IL_0000: call class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderModule::get_task() - IL_0005: stloc.0 - IL_0006: ldloc.0 - IL_0007: ldloc.0 - IL_0008: ldarg.1 - IL_0009: ldloc.0 - IL_000a: newobj instance void class Test/Generic1InGeneric1`1/clo@7::.ctor(class [runtime]System.Threading.Tasks.Task`1, - class [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder) - IL_000f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!1> [FSharp.Core]Microsoft.FSharp.Control.TaskBuilderBase::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,!!1>>) - IL_0014: callvirt instance class [runtime]System.Threading.Tasks.Task`1 [FSharp.Core]Microsoft.FSharp.Control.TaskBuilder::Run(class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ResumableCode`2,!!0>) - IL_0019: ret - } + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - } + .maxstack 4 + .locals init (valuetype Test/Generic1InGeneric1`1/clo@7 V_0, + valuetype Test/Generic1InGeneric1`1/clo@7& V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj valuetype Test/Generic1InGeneric1`1/clo@7 + IL_0008: ldloca.s V_0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldarg.1 + IL_000d: stfld class [runtime]System.Threading.Tasks.Task`1 valuetype Test/Generic1InGeneric1`1/clo@7::computation + IL_0012: ldloc.1 + IL_0013: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0018: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_001d: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0022: ldloc.1 + IL_0023: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0028: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_002d: ldloc.1 + IL_002e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start>(!!0&) + IL_0033: ldloc.1 + IL_0034: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0039: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_003e: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_0043: ret + } -} + } + +} """ ])) #endif From ec5e2458c4a2a03a6c09606ecc4c3cc2e211e13c Mon Sep 17 00:00:00 2001 From: perf-bundle Date: Wed, 9 Sep 2026 11:27:10 +0200 Subject: [PATCH 4/5] Reuse optimization helpers in resumable regression tests Use withOptimization instead of rebuilding compiler flags. Parameterize the captured-state-machine regression over Debug and optimized compilation without duplicating its source or adding lines. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Language/StateMachineTests.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs index b8d8de1aadd..07924ab9bf1 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs @@ -8,8 +8,8 @@ open FSharp.Test.Compiler module StateMachineTests = - [] - let ``SRTP await helpers preserve generic state machine captures in Debug`` () = + [] + let ``SRTP await helpers preserve generic state machine captures`` optimize = FSharp """ open System.Runtime.CompilerServices open System.Threading.Tasks @@ -60,7 +60,7 @@ let main _ = 0 """ |> withDebug - |> withNoOptimize + |> withOptimization optimize |> withFSharpCoreShippedNet |> compileExeAndRun |> shouldSucceed @@ -114,7 +114,7 @@ let inline run () = """ |> withName "ResumableLibrary" |> withDebug - |> withOptions [if optimizeLibrary then "--optimize+" else "--optimize-"] + |> withOptimization optimizeLibrary |> asLibrary FSharp """ @@ -124,7 +124,7 @@ let main _ = """ |> withReferences [library] |> withDebug - |> withOptions [if optimizeConsumer then "--optimize+" else "--optimize-"] + |> withOptimization optimizeConsumer |> compileExeAndRun |> shouldSucceed |> withExitCode 0 From e2622196574d109b02d072f3b338895ecccfb10b Mon Sep 17 00:00:00 2001 From: perf-bundle Date: Wed, 9 Sep 2026 15:01:29 +0200 Subject: [PATCH 5/5] Restore complete task IL fixture assertions Restore full lowered Test fixtures instead of MoveNext-only fragments, preserving factory, state, accessor and helper checks. Keep source programs and compiler options unchanged. Clarify that the renamed mandatory-inlining cache retains frame-local behavior as well as resumable templates. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/Compiler/Optimize/Optimizer.fs | 8 +- .../CodeGen/EmittedIL/TaskGeneratedCode.fs | 558 ++++++++++++++++++ 2 files changed, 560 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 8e6f236e757..f2c9503055a 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -441,7 +441,6 @@ type cenv = specializedInlineVals: HashMultiMap - /// Cache for 'HasForcedInlineBody' forcedInlineVals: Dictionary signatureHidingInfo: SignatureHidingInfo @@ -2469,11 +2468,8 @@ let instrIsFrameLocal instr = | I_localloc -> true | _ -> false -/// The FSharp.Core values expanding to frame-local IL are marked [] and so are -/// always inlined. A user 'inline' function wrapping one inherits the property but not the -/// attribute - the callee is already inlined into the recorded body, leaving only its IL - so -/// recover it from the body and propagate it through further wrappers. -/// See https://github.com/dotnet/fsharp/issues/20063. +/// Frame-local IL and resumable templates must remain in the caller's method. +/// Inline wrappers inherit this requirement even when they do not inherit the callee's attributes. let rec HasForcedInlineBody cenv env (vref: ValRef) = let stamp = vref.Stamp diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs index dbdac18c609..028e86d9141 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs @@ -36,6 +36,19 @@ let testTask() = task { return 1 } """, (fun verifier -> verifier.VerifyIL [ """ +.class public abstract auto ansi sealed Test + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar sealed nested assembly beforefieldinit specialname testTask@4 + extends [runtime]System.ValueType + implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, + class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Data + .field public int32 ResumptionPoint .method public strict virtual instance void MoveNext() cil managed { .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext @@ -98,6 +111,80 @@ let testTask() = task { return 1 } IL_005a: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) IL_005f: ret } + + .method public strict virtual instance void SetStateMachine(class [runtime]System.Runtime.CompilerServices.IAsyncStateMachine state) cil managed + { + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_000b: ldarg.1 + IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_0011: ret + } + + .method public strict virtual instance int32 get_ResumptionPoint() cil managed + { + .override method instance int32 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_ResumptionPoint() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: ret + } + + .method public strict virtual instance valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 get_Data() cil managed + { + .override method instance !0 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_Data() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ret + } + + .method public strict virtual instance void set_Data(valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 'value') cil managed + { + .override method instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::set_Data(!0) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0007: ret + } + + } + + .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed + { + + .maxstack 4 + .locals init (valuetype Test/testTask@4 V_0, + valuetype Test/testTask@4& V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj Test/testTask@4 + IL_0008: ldloca.s V_0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0011: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_0016: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_001b: ldloc.1 + IL_001c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0021: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0026: ldloc.1 + IL_0027: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start(!!0&) + IL_002c: ldloc.1 + IL_002d: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0032: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0037: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_003c: ret + } + +} """ ])) @@ -197,6 +284,21 @@ let testTask(t: Task) = task { let! res = t in return res+1 } """, (fun verifier -> verifier.VerifyIL [ """ +.class public abstract auto ansi sealed Test + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar sealed nested assembly beforefieldinit specialname testTask@4 + extends [runtime]System.ValueType + implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, + class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Data + .field public int32 ResumptionPoint + .field public class [runtime]System.Threading.Tasks.Task`1 t + .field public valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 awaiter .method public strict virtual instance void MoveNext() cil managed { .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext @@ -360,6 +462,83 @@ let testTask(t: Task) = task { let! res = t in return res+1 } IL_0107: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) IL_010c: ret } + + .method public strict virtual instance void SetStateMachine(class [runtime]System.Runtime.CompilerServices.IAsyncStateMachine state) cil managed + { + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_000b: ldarg.1 + IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_0011: ret + } + + .method public strict virtual instance int32 get_ResumptionPoint() cil managed + { + .override method instance int32 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_ResumptionPoint() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: ret + } + + .method public strict virtual instance valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 get_Data() cil managed + { + .override method instance !0 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_Data() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ret + } + + .method public strict virtual instance void set_Data(valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 'value') cil managed + { + .override method instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::set_Data(!0) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0007: ret + } + + } + + .method public static class [runtime]System.Threading.Tasks.Task`1 testTask(class [runtime]System.Threading.Tasks.Task`1 t) cil managed + { + + .maxstack 4 + .locals init (valuetype Test/testTask@4 V_0, + valuetype Test/testTask@4& V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj Test/testTask@4 + IL_0008: ldloca.s V_0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldarg.0 + IL_000d: stfld class [runtime]System.Threading.Tasks.Task`1 Test/testTask@4::t + IL_0012: ldloc.1 + IL_0013: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0018: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_001d: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0022: ldloc.1 + IL_0023: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0028: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_002d: ldloc.1 + IL_002e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start(!!0&) + IL_0033: ldloc.1 + IL_0034: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0039: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_003e: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_0043: ret + } + +} """ ])) @@ -485,6 +664,19 @@ let testTask() = task { try 1+1 finally System.Console.WriteLine("finally") } """, (fun verifier -> verifier.VerifyIL [ """ +.class public abstract auto ansi sealed Test + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar sealed nested assembly beforefieldinit specialname testTask@4 + extends [runtime]System.ValueType + implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, + class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Data + .field public int32 ResumptionPoint .method public strict virtual instance void MoveNext() cil managed { .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext @@ -590,6 +782,117 @@ let testTask() = task { try 1+1 finally System.Console.WriteLine("finally") } IL_0090: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) IL_0095: ret } + + .method public strict virtual instance void SetStateMachine(class [runtime]System.Runtime.CompilerServices.IAsyncStateMachine state) cil managed + { + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_000b: ldarg.1 + IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_0011: ret + } + + .method public strict virtual instance int32 get_ResumptionPoint() cil managed + { + .override method instance int32 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_ResumptionPoint() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: ret + } + + .method public strict virtual instance valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 get_Data() cil managed + { + .override method instance !0 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_Data() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ret + } + + .method public strict virtual instance void set_Data(valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 'value') cil managed + { + .override method instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::set_Data(!0) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0007: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@4-1' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .field static assembly initonly class Test/'testTask@4-1' @_instance + .method assembly specialname rtspecialname instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + { + + .maxstack 8 + IL_0000: nop + IL_0001: ldstr "finally" + IL_0006: call void [runtime]System.Console::WriteLine(string) + IL_000b: ldnull + IL_000c: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void Test/'testTask@4-1'::.ctor() + IL_0005: stsfld class Test/'testTask@4-1' Test/'testTask@4-1'::@_instance + IL_000a: ret + } + + } + + .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed + { + + .maxstack 4 + .locals init (valuetype Test/testTask@4 V_0, + valuetype Test/testTask@4& V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj Test/testTask@4 + IL_0008: ldloca.s V_0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0011: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_0016: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_001b: ldloc.1 + IL_001c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0021: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0026: ldloc.1 + IL_0027: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start(!!0&) + IL_002c: ldloc.1 + IL_002d: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0032: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0037: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_003c: ret + } + +} """ ])) @@ -719,6 +1022,19 @@ let testTask() = task { try 1 with e -> System.Console.WriteLine("with"); 2 } """, (fun verifier -> verifier.VerifyIL [ """ +.class public abstract auto ansi sealed Test + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar sealed nested assembly beforefieldinit specialname testTask@4 + extends [runtime]System.ValueType + implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, + class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Data + .field public int32 ResumptionPoint .method public strict virtual instance void MoveNext() cil managed { .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext @@ -822,6 +1138,80 @@ let testTask() = task { try 1 with e -> System.Console.WriteLine("with"); 2 } IL_0088: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) IL_008d: ret } + + .method public strict virtual instance void SetStateMachine(class [runtime]System.Runtime.CompilerServices.IAsyncStateMachine state) cil managed + { + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_000b: ldarg.1 + IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_0011: ret + } + + .method public strict virtual instance int32 get_ResumptionPoint() cil managed + { + .override method instance int32 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_ResumptionPoint() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@4::ResumptionPoint + IL_0006: ret + } + + .method public strict virtual instance valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 get_Data() cil managed + { + .override method instance !0 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_Data() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0006: ret + } + + .method public strict virtual instance void set_Data(valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 'value') cil managed + { + .override method instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::set_Data(!0) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0007: ret + } + + } + + .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed + { + + .maxstack 4 + .locals init (valuetype Test/testTask@4 V_0, + valuetype Test/testTask@4& V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj Test/testTask@4 + IL_0008: ldloca.s V_0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0011: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_0016: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_001b: ldloc.1 + IL_001c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0021: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0026: ldloc.1 + IL_0027: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start(!!0&) + IL_002c: ldloc.1 + IL_002d: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@4::Data + IL_0032: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0037: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_003c: ret + } + +} """ ])) @@ -937,6 +1327,19 @@ let testTask() = task { while x > 4 do System.Console.WriteLine("loop") } """, (fun verifier -> verifier.VerifyIL [ """ +.class public abstract auto ansi sealed Test + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto autochar sealed nested assembly beforefieldinit specialname testTask@5 + extends [runtime]System.ValueType + implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, + class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .field public valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Data + .field public int32 ResumptionPoint .method public strict virtual instance void MoveNext() cil managed { .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext @@ -1022,6 +1425,161 @@ let testTask() = task { while x > 4 do System.Console.WriteLine("loop") } IL_007d: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) IL_0082: ret } + + .method public strict virtual instance void SetStateMachine(class [runtime]System.Runtime.CompilerServices.IAsyncStateMachine state) cil managed + { + .override [runtime]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_000b: ldarg.1 + IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) + IL_0011: ret + } + + .method public strict virtual instance int32 get_ResumptionPoint() cil managed + { + .override method instance int32 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_ResumptionPoint() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 Test/testTask@5::ResumptionPoint + IL_0006: ret + } + + .method public strict virtual instance valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 get_Data() cil managed + { + .override method instance !0 class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::get_Data() + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0006: ret + } + + .method public strict virtual instance void set_Data(valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 'value') cil managed + { + .override method instance void class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1>::set_Data(!0) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0007: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit 'testTask@5-1' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .field static assembly initonly class Test/'testTask@5-1' @_instance + .method assembly specialname rtspecialname instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + IL_0006: ret + } + + .method public strict virtual instance bool Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + { + + .maxstack 8 + IL_0000: call int32 Test::get_x() + IL_0005: ldc.i4.4 + IL_0006: cgt + IL_0008: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void Test/'testTask@5-1'::.ctor() + IL_0005: stsfld class Test/'testTask@5-1' Test/'testTask@5-1'::@_instance + IL_000a: ret + } + + } + + .field static assembly int32 x@4 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .method public specialname static int32 get_x() cil managed + { + + .maxstack 8 + IL_0000: ldsfld int32 Test::x@4 + IL_0005: ret + } + + .method public specialname static void set_x(int32 'value') cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: stsfld int32 Test::x@4 + IL_0006: ret + } + + .method public static class [runtime]System.Threading.Tasks.Task`1 testTask() cil managed + { + + .maxstack 4 + .locals init (valuetype Test/testTask@5 V_0, + valuetype Test/testTask@5& V_1) + IL_0000: ldloca.s V_0 + IL_0002: initobj Test/testTask@5 + IL_0008: ldloca.s V_0 + IL_000a: stloc.1 + IL_000b: ldloc.1 + IL_000c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0011: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() + IL_0016: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_001b: ldloc.1 + IL_001c: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0021: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0026: ldloc.1 + IL_0027: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start(!!0&) + IL_002c: ldloc.1 + IL_002d: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 Test/testTask@5::Data + IL_0032: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder + IL_0037: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() + IL_003c: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$Test::init@ + IL_0006: ldsfld int32 ''.$Test::init@ + IL_000b: pop + IL_000c: ret + } + + .method assembly static void staticInitialization@() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: stsfld int32 Test::x@4 + IL_0006: ret + } + + .property int32 x() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .set void Test::set_x(int32) + .get int32 Test::get_x() + } +} """ ])) #endif