Skip to content

Backwards compatibility broken #18344

Open
Open
@gusty

Description

@gusty

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

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<option<_>  > , _mthd: IsAltLeftZero) = Option.isSome t.Value
    static member        IsAltLeftZero (t: ref<voption<_>  >, _mthd: IsAltLeftZero) = ValueOption.isSome t.Value

    static member        IsAltLeftZero (t: ref<Result<_,_>> , _mthd: IsAltLeftZero) = match t.Value with (Ok _        ) -> true | _ -> false
    static member        IsAltLeftZero (t: ref<Choice<_,_>> , _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<IsAltLeftZero>, 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

> 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 fsprojects/FSharpPlus#613) that I will be really surprised if this affects only F#+ code.

Metadata

Metadata

Assignees

Labels

Area-Compiler-SRTPbugs in SRTP inference, resolution, witness passing, code genBugImpact-High(Internal MS Team use only) Describes an issue with extreme impact on existing code.

Type

Projects

Status

New

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions