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

Backwards compatibility broken #18344

Open
gusty opened this issue Feb 27, 2025 · 2 comments
Open

Backwards compatibility broken #18344

gusty opened this issue Feb 27, 2025 · 2 comments
Labels
Area-Compiler-SRTP bugs in SRTP inference, resolution, witness passing, code gen Bug Impact-High (Internal MS Team use only) Describes an issue with extreme impact on existing code. Needs-Triage
Milestone

Comments

@gusty
Copy link
Contributor

gusty commented Feb 27, 2025

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.

@github-actions github-actions bot added this to the Backlog milestone Feb 27, 2025
@T-Gro T-Gro added Impact-High (Internal MS Team use only) Describes an issue with extreme impact on existing code. Area-Compiler-SRTP bugs in SRTP inference, resolution, witness passing, code gen labels Feb 27, 2025
@T-Gro
Copy link
Member

T-Gro commented Feb 27, 2025

To summarize:
Lib 9, Consumer 8 -> this is the main scenario detected as being broken
Lib 9, Consumer also 9 -> works
Lib 8, Consumer 9 -> works

And the problem arises for consumers passing in Option<> only ?
(because my first-glance hypothesis is this affects types that UseNullAsTrueValue)

@gusty
Copy link
Contributor Author

gusty commented Feb 27, 2025

No, I think it's rather:

Lib 8, Consumer 9 -> this is the main scenario detected as being broken
Lib 9, Consumer also 9 -> works
Lib 9, Consumer 8 -> works (although not 100% sure about this one)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compiler-SRTP bugs in SRTP inference, resolution, witness passing, code gen Bug Impact-High (Internal MS Team use only) Describes an issue with extreme impact on existing code. Needs-Triage
Projects
Status: New
Development

No branches or pull requests

2 participants