dotnet / dotnet/fsharp

Nullness issue - Additional type hints needed in Computation Expression

Open
#17,776 2 comments 1 reaction 0 assignees View on GitHub
Area-Nullness Feature Improvement
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

### Issue description

I found a couple of examples where type hints are needed inside the FsToolkit.ErrorHandling `option` CE with `--checknulls`` turned on.

I'm providing some example code, and comments where the type hints need to be added. This compiles without the extra hints when `--checknulls`` is not specified.

### Choose one or more from the following categories of impact

- [ ] Unexpected nullness warning (false positive in nullness checking, code uses --checknulls and langversion:preview).
- [ ] Missing nullness warning in a case which can produce nulls (false negative, code uses --checknulls and langversion:preview).
- [ ] Breaking change related to older `null` constructs in code not using the checknulls switch.
- [ ] Breaking change related to generic code and explicit type constraints (`null`, `not null`).
- [X] Type inference issue (i.e. code worked without type annotations before, and applying the --checknulls enforces type annotations).
- [ ] C#/F# interop issue related to nullness metadata.
- [ ] Other (none of the categories above apply).

### Operating System

Windows (Default)

### What .NET runtime/SDK kind are you seeing the issue on

.NET SDK (.NET Core, .NET 5+)

### .NET Runtime/SDK version

9.0.100-rc.1.24452.12

### Reproducible code snippet and actual behavior

```F#
module Program

open FSharp.UMX
open FsToolkit.ErrorHandling

type [] m
type [] r

type P = | P
type S = | S

let doThing (a: float) (b:float) =
()

let x (mr : (float*float) option) : unit =
option {
// Needs annotation
//let! (m:float,r:float) = mr
let! (m, r) = mr

let r = UMX.castr
doThing r m
}
|> ignore

let y (s : S option ) (p : P option)=
option {
// Needs annotation
//let! (_s : S) = s
let! _s = s

// Needs annotation
//let! (_p : P) = p
let! _p = p

()
} |> ignore

[]
let main argv =
0
```

```text
Nullness failed with 3 error(s) (0.9s)
D:\Git\Temp\Nullness\Nullness\Program.fs(21,17): error FS0041: A unique overload for method 'cast' could not be determined based on type information prior to this program point. A type annotation may be needed.Known type of argument: 'aCandidates: - static member UMX.cast: x: DateTime<'m1> -> DateTime<'m2> - static member UMX.cast: x: DateTimeOffset<'m1> -> DateTimeOffset<'m2> - static member UMX.cast: x: Guid<'m1> -> Guid<'m2> - static member UMX.cast: x: TimeSpan<'m1> -> TimeSpan<'m2> - static member UMX.cast: x: bool<'m1> -> bool<'m2> - static member UMX.cast: x: byte<'m1> -> byte<'m2> - static member UMX.cast: x: decimal<'m1> -> decimal<'m2> - static member UMX.cast: x: float32<'m1> -> float32<'m2> - static member UMX.cast: x: float<'m1> -> float<'m2> - static member UMX.cast: x: int16<'m1> -> int16<'m2> - static member UMX.cast: x: int64<'m1> -> int64<'m2> - static member UMX.cast: x: int<'m1> -> int<'m2> - static member UMX.cast: x: string<'m1> -> string<'m2> - static member UMX.cast: x: uint64<'m1> -> uint64<'m2>
D:\Git\Temp\Nullness\Nullness\Program.fs(34,9): error FS0041: A unique overload for method 'Bind' could not be determined based on type information prior to this program point. A type annotation may be needed.Known types of arguments: P option * ('a -> unit option)Candidates: - member OptionBuilder.Bind: input: 'input option * [] binder: ('input -> 'output option) -> 'output option - member OptionBuilder.Bind: m: 'input * [] binder: ('input -> 'output option) -> 'output option when 'input: null
D:\Git\Temp\Nullness\Nullness\Program.fs(30,9): error FS0041: A unique overload for method 'Bind' could not be determined based on type information prior to this program point. A type annotation may be needed.Known types of arguments: S option * ('a -> 'b)Candidates: - member OptionBuilder.Bind: input: 'input option * [] binder: ('input -> 'output option) -> 'output option - member OptionBuilder.Bind: m: 'input * [] binder: ('input -> 'output option) -> 'output option when 'input: null
```

### Possible workarounds

_No response_

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.