Skip to content

Compilation fails depending on runtime path (???) #7384

@gusty

Description

@gusty

I will demonstrate a short piece of code, using SRTPs and overload resolution, where the compilation will either succeed or fail, depending on the runtime execution path.

Repro steps

let compiles = true

type A<'t> = A of 't
type B<'t> = B of 't

type Bind = Bind with
    static member (>>=) (A t, f: 'T -> A<'U> ) = f t
    static member (>>=) (B t, f: 'T -> B<'U> ) = f t
    static member inline Invoke (source: 'MT) (binder: 'T -> 'MU) : 'MU =
        let inline call (_mthd: 'M, input: 'I, _output: 'R, f) = ((^M or ^I or ^R) : (static member (>>=) : _*_ -> _) input, f)
        call (Bind, source, Unchecked.defaultof<'MU>, binder)

type Result = Result with
    static member Return (_: A<'a>) = A
    static member Return (_: B<'a>) = B
    static member inline Invoke (x: 'T) : 'MT =
        let inline call (_mthd: ^M, output: ^R) = ((^M or ^R) : (static member Return : _ -> _) output)
        call (Result, Unchecked.defaultof<'MT>) x

type T<'m>    () = class end
type U<'m,'t> () = class end

let inline createT (_: 'mit) =
    let _  = if compiles then Bind.Invoke (Result.Invoke Unchecked.defaultof<'t> : 'mt) ((fun _ -> Result.Invoke (U<'mt,'t>()))) else Unchecked.defaultof<'mit>
    T() : T<'mt>

type T<'m> with static member inline Return (_) = fun (_:'t) -> U() |> Result.Invoke |> createT

// test
let (u: T<A<unit>>) = Result.Invoke ()  // works !!!  Now try with compiles = false (???)

Expected behavior

Should compile or not (hopefully the former) regardless of the content of compiles.

Actual behavior

It compiles if compiles = true but when compiles = false it fails with error FS0073: internal error: Undefined or unsolved type variable: ^_?21440

Known workarounds

Use compile = true but it will execute unnecessarily some piece of code that is used only to drive type inference to create the desired constraints.

Related information

I've tested it in many environments and different versions of F#. Actually I'm seeing this since long time ago (4 years at least) but it's the first time I manage to create a minimal repro.

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions