-
Notifications
You must be signed in to change notification settings - Fork 850
Labels
Area-Compiler-StateMachinesSequence, list, task and other state machine compilationSequence, list, task and other state machine compilationBug
Milestone
Description
This is esoteric, I know.
Execute in interactive
open FSharp.Core.CompilerServices
open FSharp.Core.CompilerServices.StateMachineHelpers
open System.Runtime.CompilerServices
let inline MoveOnce(x: byref<'T> when 'T :> IAsyncStateMachine and 'T :> IResumableStateMachine<'Data>) =
x.MoveNext()
x.Data
let inline helper x =
ResumableCode<int, int>(fun sm ->
if __useResumableCode then
sm.Data <- x
true
else
failwith "unexpected dynamic branch at runtime")
let inline repro x =
if __useResumableCode then
__stateMachine<int, int>
(MoveNextMethodImpl<_>(fun sm ->
// helper function is not expanded correctly
(helper x).Invoke(&sm) |> ignore))
(SetStateMachineMethodImpl<_>(fun _ _ -> ()))
(AfterCode<_, _>(fun sm -> MoveOnce(&sm)))
else
failwith "overall state machine should be static"
repro 42expected result 42, actual: "unexpected dynamic branch at runtime"
The overall state machine compiles statically, no warning here. Yet at runtime the inlined helper function enters the dynamic branch which by then should have been erased but somehow survives the expansion.
The workaround is to bind the result to a __stack_ value:
let __stack_result = (helper x).Invoke(&sm)
ignore __stack_resultThe problem is:
It is not mentioned in the RFC.
Gives no warning at compile time.
At runtime can fail in mysterious ways, including but not limited to NREs.
Impact is low, but a fix should be uncomplicated.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Area-Compiler-StateMachinesSequence, list, task and other state machine compilationSequence, list, task and other state machine compilationBug
Type
Projects
Status
New