dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.94k stars 788 forks source link

AsyncBuilder compiles invalid program #11066

Closed vukovinski closed 3 years ago

vukovinski commented 3 years ago

The following program compiles, yet throws an exception at runtime.

Repro steps

type IStep = interface end
type IProcessingStep =
    inherit IStep
    abstract member this.Invoke : ProcessingPipeline -> Async<ProcessingPipeline>
type ITerminalProcessingStep =
    inherit IStep
    abstract member this.Invoke : ProcessingPipeline -> Async<unit>

// given some concrete implementation classes, with exception catching

type ProcessingPipeline(state) =
    let (||>>) (aw_pipeline:Async<ProcessingPipeline>) (step:ProcessingPipeline -> Async<'T>) = async {
        let! pipeline = aw_pipeline
        return! step pipeline
    }
    ...
    member this.RunAsync() =
        let computation =
              async { return this }
              ||>> (ProcessingStep1 :> IProcessingStep).Invoke
              ||>> (ProcessingStep2 :> IProcessingStep).Invoke
              ||>> (ProcessingStep3 :> IProcessingStep).Invoke
              ||>> (ProcessingStep4 :> ITerminalProcessingStep).Invoke
        Async.Start computation

Provide the steps required to reproduce the problem:

  1. Compile
  2. Run
  3. Program halts, at (let's say) step 3.

If possible attach a zip file with the repro case. This often makes it easier for others to reproduce. The zip file should ideally represent the situation just before the call/step that is problematic.

Expected behavior

Program runs.

Actual behavior

Invalid Program Exception - Common Language Runtime detected an invalid program.

   at Processing.Processing-IProcessingStep-Invoke@170-5.Invoke(ProcessingPipeline ppl)
   at Processing.ErrorShunt@37.Invoke(Unit unitVar) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 38
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvoke[T,TResult](AsyncActivation`1 ctxt, TResult result1, FSharpFunc`2 part2) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 386
   at Processing.Processing-IProcessingStep-Invoke@161-3.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 161
   at Processing.computation@56-1.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 56
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.clo@21-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 21
   at Processing.RunAsync@67-2.Invoke(AsyncActivation`1 ctxt) in C:\Users\filip.vukovinski\Desktop\Repo\NBIoT.X\src\NBIoT.Service\Processing.fs:line 67
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 104
--- End of stack trace from previous location ---
   at Microsoft.FSharp.Control.AsyncPrimitives.Start@895-1.Invoke(ExceptionDispatchInfo edi)
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 104
   at Microsoft.FSharp.Control.TrampolineHolder.ExecuteWithTrampoline(FSharpFunc`2 firstAction) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 169
   at <StartupCode$FSharp-Core>.$Async.-ctor@155-1.Invoke(Object o) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\async.fs:line 157
   at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
   at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Known workarounds

Not sure how to proceed. Maybe will try using Task-based asynchronous model.

Related information

The decompiler agrees, but not sure if this is related.

2021-02-09 13_44_45-dnSpy v6 1 4 (64-bit)

vukovinski commented 3 years ago

Found the error in user code.