Skip to content

Internal error, LocallyAbortOperationThatFailsToResolveOverload with SRTP #7217

@realvictorprm

Description

@realvictorprm

With certain SRTP constructions the compiler produces an FSharp.Compiler.ConstraintSolver+LocallyAbortOperationThatFailsToResolveOverload
internal error.

Repro steps

The naming in the snippet was modified to obfuscate the real logic as this was an experiment for a customer.

module TargetA =

    [<RequireQualifiedAccess>]
    type TransformerKind =
        | A
        | B

    type M1 = int

    type M2 = float

    type Target() =

        member __.TransformM1 (kind: TransformerKind) : M1[] option = [| 0 |] |> Some
        member __.TransformM2 (kind: TransformerKind) : M2[] option = [| 1. |] |> Some

    type TargetA =

        static member instance : Target option = None

        static member inline Transform(_: ^r, _: TargetA) = fun (kind:TransformerKind) -> TargetA.instance.Value.TransformM1 kind : ^r
        static member inline Transform(_: ^r, _: TargetA) = fun (kind:TransformerKind) ->  TargetA.instance.Value.TransformM2 kind : ^r

        static member inline Transform(kind: TransformerKind) =
            let inline call2(a:^a, b:^b) = ((^a or ^b) : (static member Transform: _ * _ -> _) b, a)
            let inline call (a: 'a) = fun (x: 'x) -> call2(a, Unchecked.defaultof<'r>) x : 'r
            call Unchecked.defaultof<TargetA> kind

    let inline Transform kind = TargetA.Transform kind

module TargetB =
    [<RequireQualifiedAccess>]
    type TransformerKind =
        | C
        | D

    type M1 = | M1

    type M2 = | M2

    type Target() =

        member __.TransformM1 (kind: TransformerKind) = [| M1 |] |> Some
        member __.TransformM2 (kind: TransformerKind) = [| M2 |] |> Some

    type TargetB =

        static member instance : Target option = None
    
        static member inline Transform(_: ^r, _: TargetB) = fun (kind:TransformerKind) -> TargetB.instance.Value.TransformM1 kind : ^r
        static member inline Transform(_: ^r, _: TargetB) = fun (kind:TransformerKind) -> TargetB.instance.Value.TransformM2 kind : ^r

        static member inline Transform(kind: TransformerKind) =
            let inline call2(a:^a, b:^b) = ((^a or ^b) : (static member Transform: _ * _ -> _) b, a)
            let inline call (a: 'a) = fun (x: 'x) -> call2(a, Unchecked.defaultof<'r>) x : 'r
            call Unchecked.defaultof<TargetB> kind
    let inline Transform kind = TargetB.Transform kind

module Superpower =

    type Transformer =
        
        static member inline Transform(_: ^f, _: TargetB.TargetB, _: Transformer) = fun x -> TargetB.Transform x : ^f
        
        static member inline Transform(_: ^r, _: TargetA.TargetA, _: Transformer) = fun x -> TargetA.Transform x : ^r

        static member inline YeahTransform kind =
            let inline call2(a:^a, b:^b, c: ^c) = ((^a or ^b or ^c) : (static member Transform: _ * _ * _ -> _) c, b, a)
            let inline call (a: 'a) = fun (x: 'x) -> call2(a, Unchecked.defaultof<_>, Unchecked.defaultof<'r>) x : 'r
            call Unchecked.defaultof<Transformer> kind 

module Examples =
    let a kind = Superpower.Transformer.YeahTransform kind : TargetA.M1[]
    let b = Superpower.Transformer.YeahTransform TargetA.TransformerKind.A : TargetA.M2[] option
    let c = Superpower.Transformer.YeahTransform TargetB.TransformerKind.C : TargetB.M1[] option
    let d = Superpower.Transformer.YeahTransform TargetA.TransformerKind.A : TargetA.M1[] option

Expected behavior

Compiler shows possible overloads error.

Actual behavior

Compiler fails with an internal error message:

Type constraint mismatch when applying the default type 'obj' for a type inference variable. internal error: Exception of type 'FSharp.Compiler.ConstraintSolver+LocallyAbortOperationThatFailsToResolveOverload' was thrown. Consider adding further type constraintsF# Compiler(71)

Known workarounds

Just know what you're doing and use the correct overloads or just don't use SRTP's in such a bad manner 😂

Related information

Provide any related information (optional):

.NET Core SDK (gemäß "global.json"):
 Version:   2.2.300
 Commit:    73efd5bd87

Laufzeitumgebung:
 OS Name:     ubuntu
 OS Version:  18.10
 OS Platform: Linux
 RID:         ubuntu.18.10-x64
 Base Path:   /usr/share/dotnet/sdk/2.2.300/

Host (useful for support):
  Version: 2.2.5
  Commit:  0a3c9209c0

.NET Core SDKs installed:
  2.2.300 [/usr/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.2.5 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.5 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.5 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions