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.89k stars 782 forks source link

Incoherent behavior when using a task with a unit returning statement, between Release and Debug #13099

Open jp-fournier-dev opened 2 years ago

jp-fournier-dev commented 2 years ago

Please provide a succinct description of the issue.

When executing inside a task, a function that raises an exception is not called if the resulting expression ends in a property that has a unit value.

Provide the steps required to reproduce the problem:

  1. Run the attached code in debug, see that it does raise the exception with failwith using : dotnet run --configuration Debug
  2. Run the attached code in release, see that it does not raise the exception using : dotnet run --configuration Release
printfn "Hello from F#"

type SomeOutputType() =
    member x.End = ()

let someFunctionWithReturnType () = 
    failwith "This should be raised"
    SomeOutputType()

let theTaskAtHand () = 
    task {
        (someFunctionWithReturnType ()).End
    }

theTaskAtHand().Wait()

Provide a description of the expected behavior.

In both debug and release, the program fails after the exception is raised

Provide a description of the actual behavior observed.

In release, the exception is essentially ignored and nothing happens. Program exits successfully In debug, the exception is raised and the program fails

Provide a description of any known workarounds.

You can pretty easily change this by switching it to being a function like so : member x.End = ignore and calling said function. Using `member x.End() = () will not work

Doing so inside an async computation expression will result in the expected behavior with the original code

Provide any related information:

Operating system: Windows 10 NET Runtime kind : .NET 6.0.201

jp-fournier-dev commented 2 years ago

To add some context :

This seems more like and edge case, but still offers plenty of surprise when it happens

En3Tho commented 2 years ago

It seems that this function is not even called. state machine's MoveNext method from original code: image

when that line is changed to someFunctionWithReturnType() |> ignore image