Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nullness issue - compilation broken by FS0001 when enabling nullness checks #18034

Open
1 of 7 tasks
johnnyggalt opened this issue Nov 19, 2024 · 5 comments
Open
1 of 7 tasks
Labels
Area-Nullness Issues related to handling of Nullable Reference Types Bug Triage-Investigate
Milestone

Comments

@johnnyggalt
Copy link

Issue description

A specific scenario is broken by enabling nullness checking, manifesting as FS0001.

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).
  • 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

.NET 9

Reproducible code snippet and actual behavior

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="Program.fs" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="FSharpPlus" Version="1.6.1" />
  </ItemGroup>

</Project>
open FSharpPlus

let parseInt () : Result<int, string> =
    Ok 42

type SomeRecordWrapper = {
    Value: int
}

let repro () =
    let result =
        monad {
            let! parsed = parseInt ()
            return {
                Value = parsed
            }
        }

    match result with
    | Ok _ ->
        ()
    | Error _ ->
        ()

With Nullable enabled, this results in:

0>Program.fs(20,7): Error FS0001 : '.Delay' does not support the type 'Result<SomeRecordWrapper,'a>', because the latter lacks the required (real or built-in) member 'Delay'
0>Program.fs(19,11): Warning FS0025 : Incomplete pattern matches on this expression.

With Nullable disabled, the code compiles fine.

Possible workarounds

None that I know of.

@johnnyggalt johnnyggalt added Area-Nullness Issues related to handling of Nullable Reference Types Bug Needs-Triage labels Nov 19, 2024
@github-actions github-actions bot added this to the Backlog milestone Nov 19, 2024
@T-Gro T-Gro removed their assignment Nov 20, 2024
@T-Gro
Copy link
Member

T-Gro commented Nov 20, 2024

I am confused about the source line of the error, like 20 is the " | Ok " match clause, isn't it?

@johnnyggalt
Copy link
Author

@T-Gro that's correct. It seems to me that the combination of null checking and the specifics of my scenario is causing the compiler to get confused.

@T-Gro
Copy link
Member

T-Gro commented Nov 20, 2024

Some previous defaults of type inference, such as falling back to 'obj' in some cases, are no longer possible with nullness due to the difference between obj and objnull.
This should be validate with trying similar code with and without explicit annotations for the usages of the Result.

Looking at the code, it should be able to derive type of Result to be <int,string> (non nullable string) .

@johnnyggalt
Copy link
Author

@T-Gro if I explicitly type the result, it does compile:

    let result: Result<SomeRecordWrapper, string> =
        ...

Whilst this should get me past my issue, it feels off to me. At the very least, the compiler error message is hella confusing. But on top of that, if I don't explicitly type result it still correctly inferred, so the explicit typing feels unnecessary from that perspective:

Image

@T-Gro
Copy link
Member

T-Gro commented Nov 25, 2024

It does indeed.

It has to do with the constraints implied by the use of "monad" CE - not that it has an issue in it, but rather the compiler solving constraints wrong for it in the presence of nullable changes.

We definitely first need to check this with a smaller isolated computation expression (= a trimmed down version of "monad"), to minimize the suspects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Nullness Issues related to handling of Nullable Reference Types Bug Triage-Investigate
Projects
Status: New
Development

No branches or pull requests

3 participants