Skip to content

Unnecessary(?) breaking change in FSharp.Core 9.0.100: ofObj now requires not struct as well as null #18320

@pleaseletmesearch

Description

@pleaseletmesearch

This code works with FSharp.Core 8.0.100:

module Foo =
    let failIfNull<'a when 'a : null> (a : 'a) : 'a =
        a |> Option.ofObj |> Option.orFail "hi"

In FSharp.Core 9.0.100, it does not compile:

error FS0001: Type mismatch. Expecting a� ''a -> 'b' �but given a� ''a -> 'a option' �A type parameter is missing a constraint 'when 'a: not struct'

The null constraint should surely already imply not struct? The docs at https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/generics/constraints say "This [not null] generic constraint does allow value types, since those can never be null.", which suggests that the null constraint logically implies the not struct constraint.

Repro steps

Thing.fsproj

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>netstandard2.0</TargetFramework></PropertyGroup>
<ItemGroup><Compile Include="Thing.fs" /></ItemGroup>
<ItemGroup><PackageReference Update="FSharp.Core" Version="9.0.100" /></ItemGroup>
</Project>

Thing.fs

namespace Blah

module Foo =
    let inline orFail (err:  string) (option : 'a Option) =
        match option with
        | Some a -> a
        | None -> failwith err

    let failIfNull<'a when 'a : null> (a : 'a) : 'a =
        a |> Option.ofObj |> orFail "hi"

Observe the compile error; then downgrade FSharp.Core to 8.0.100 and observe the compile success.

Known workarounds

  • Edit user code to add the (apparently redundant?) constraint not struct.
  • Don't upgrade FSharp.Core.

Provide a description of any known workarounds.

Related information

I'm using SDK 9.0.200 on linux-x64.

Metadata

Metadata

Assignees

Type

Projects

Status

Done

Relationships

None yet

Development

No branches or pull requests

Issue actions