dotnet / dotnet/fsharp

Inconistent and confusing error reporting for `else` branch in CE

Open
#8,593 0 comments 2 reactions 0 assignees View on GitHub
Area-Diagnostics Feature Request
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

I'm aware of https://github.com/dotnet/fsharp/issues/1103 and I mostly liked the changes. It even seems like now I even expect good error messages for some common errors, one (IMHO) particularly useful is:

```fsharp
let testHandler =
if 1 = 2 then
raise <| exn("test")
else

if 2 = 3 then
3
else

if 2 = 3 then
failwithf "some other"
else

"test" // FS0001 All branches of an 'if' expression must return values of the same type as the first branch, which here is 'int'. This branch returns a value of type 'string'
```

Now consider you have the following code (which compiles fine):

```fsharp
let testHandler =
if 1 = 2 then
raise <| exn("test")
else

if 2 = 3 then
failwithf "some other"
else

"test"
```

And assume you refactor this into an asynchronous (for example task based) function:

```fsharp
let testHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
if 1 = 2 then
raise <| exn("test")
else

if 2 = 3 then
failwithf "some other"
else

let! d = Task.Delay 100

return "test" // FS0001 This expression was expected to have type 'unit' but here it has type 'string'
}
```

As newcomers have no longer the ability to learn "reading" this compiler error they have no way of figuring out what the compiler is trying to tell them.

/cc @forki

**Expected behavior**

Make sure to have at least a friendly error here. (I'm not too worried about the code not compiling)

**Actual behavior**

Cryptic error message

**Known workarounds**

When you add a type hint it improves a bit (at least the correct lines are underlined):

```fsharp
let testHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
if 1 = 2 then
raise <| exn("test") // FS0001 Type mismatch. Expecting a 'FSharp.Control.Tasks.TaskBuilder.Step' but given a 'FSharp.Control.Tasks.TaskBuilder.Step' The type 'string' does not match the type 'unit'
else

if 2 = 3 then
failwithf "some other" // FS0001 Type mismatch. Expecting a 'FSharp.Control.Tasks.TaskBuilder.Step' but given a 'FSharp.Control.Tasks.TaskBuilder.Step' The type 'string' does not match the type 'unit'
else

let! d = Task.Delay 100

return "test"
} : Task
```

But you still are a bit confused about what `FSharp.Control.Tasks.TaskBuilder.Step` is.

**Related information**

Provide any related information (optional):

* Operating system: Win10
* .NET Runtime kind: All
* Editing Tools: Latest VS 2019

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.