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

Nullness issue - Spurious nullness warning with flexible type #18056

Open glchapman opened 6 days ago

glchapman commented 6 days ago

Issue description

I get a nullness warning with the following:

let dispose (x: IDisposable | null) : unit =
    match x with
    | null -> ()
    | d -> d.Dispose()

let useThing (thing: #IDisposable) =
    try
        printfn "%O" thing
    finally
        dispose thing // warning generated

Since the dispose function allows null, I do not think a warning should be generated. No warning is generated for a non-flexible type, e.g.:

let useThing (thing: IDisposable) =
    try
        printfn "%O" thing
    finally
        dispose thing // no warning generated 

Choose one or more from the following categories of impact

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

net9.0

Reproducible code snippet and actual behavior

No response

Possible workarounds

No response

glchapman commented 6 days ago

I just reread the section "Inference in generic code" from Nullable Reference Types in F# 9. I thought perhaps it meant that the following should work without a warning, but a warning is still generated

let useThing<'d when 'd: not struct and 'd :> IDisposable> (thing: 'd) =
    try
        printfn "%O" thing
    finally
        dispose thing // warning generated
T-Gro commented 5 days ago

Could you please also include which warning this produces incl. the range (= coordinates in code) for it?

glchapman commented 5 days ago

The warning is:

Program.fs(12,17): warning FS3261: Nullness warning: The types 'IDisposable' and 'IDisposable | null' do not have equivalent nullability.

In VSCode, thing in the last line (dispose thing) is highlighted.