dotnet / dotnet/fsharp

Backwards compatibility broken

Open
#18,344 15 comments 0 reactions 1 assignee Claimed by @T-Gro View on GitHub
Area-Compiler-SRTP Bug Impact-High
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

The following code is compiled differently in F#9, depending on which SDK is used ( 8 vs 9, in both cases targeting net8 )

```fsharp
type Default3 = class end
type Default2 = class inherit Default3 end
type Default1 = class inherit Default2 end

type IsAltLeftZero =
inherit Default1

static member inline IsAltLeftZero (_: ref<'T> when 'T : struct , _mthd: Default3) = false
static member inline IsAltLeftZero (_: ref<'T> when 'T : not struct, _mthd: Default2) = false

static member inline IsAltLeftZero (t: ref<'At> , _mthd: Default1) = (^At : (static member IsAltLeftZero : _ -> _) t.Value)
static member inline IsAltLeftZero (_: ref< ^t> when ^t: null and ^t: struct , _mthd: Default1) = ()

static member IsAltLeftZero (t: ref > , _mthd: IsAltLeftZero) = Option.isSome t.Value
static member IsAltLeftZero (t: ref >, _mthd: IsAltLeftZero) = ValueOption.isSome t.Value

static member IsAltLeftZero (t: ref> , _mthd: IsAltLeftZero) = match t.Value with (Ok _ ) -> true | _ -> false
static member IsAltLeftZero (t: ref> , _mthd: IsAltLeftZero) = match t.Value with (Choice1Of2 _) -> true | _ -> false

static member inline Invoke (x: 'At) : bool =
let inline call (mthd : ^M, input: ^I) =
((^M or ^I) : (static member IsAltLeftZero : _*_ -> _) (ref input), mthd)
call(Unchecked.defaultof, x)
```

Looking at the produced type for IsAltLeftZero there are some diffs in the `Invoke$W` method (I guess W stands for witness)
```
// F#8 => Boolean Invoke$W[At](FSharpFunc`2[At,Boolean], FSharpFunc`2[FSharpRef`1[At],FSharpFunc`2[IsAltLeftZero,Boolean]], At);
// F#9 => Boolean Invoke$W[At]( FSharpFunc`2[FSharpRef`1[At],FSharpFunc`2[IsAltLeftZero,Boolean]], At);
```

At the end of the day, the problem is when using the produced dll, from F# 9, the following call will fail when compiled with sdk 8

```fsharp
> IsAltLeftZero.Invoke None ;;

IsAltLeftZero.Invoke None ;;
---------------------^^^^

stdin(4,22): error FS0001: '.Invoke' does not support the type ''a option', because the latter lacks the required (real or built-in) member 'IsAltLeftZero'
```

**Known workarounds**

The only workaround is recompile everything in F#9

Note: I this is a major breaking change. Running SRTP code from FSharpPlus breaks in so many places (See https://github.com/fsprojects/FSharpPlus/issues/613) that I will be really surprised if this affects only F#+ code.

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.