dotnet / dotnet/fsharp

Compilation fails depending on runtime path (???)

Open
#7,384 6 comments 0 reactions 0 assignees View on GitHub
Area-Compiler-SRTP Bug Impact-Medium
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

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>) = 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.

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.