Skip to content

Infinite cycle in type inference #9523

@gusty

Description

@gusty

AFAIK Infinite cycles in type inference are considered bugs. Here's one.

Repro steps

let listToString c lst = List.map c lst  |> fun x -> System.String.Join (",", x) : string
let t2ToString c1 c2    ((x,y))   = "(" +  c1 x + ", " + c2 y + ")"
let t3ToString c1 c2 c3 ((x,y,z)) = "(" +  c1 x + ", " + c2 y + ", " + c3 z + ")"

type Enc = Enc with

    static member inline Invoke (x: 't) : string =
        let inline call (a: ^a, b: ^b) = ((^a or ^b) : (static member Encode: ^b * _ -> string) b, a)
        call (Enc, x)

    static member        Encode (x: string , _:Enc) = string x
    static member        Encode (x: int    , _:Enc) = string x
    static member inline Encode (x: 't list, _:Enc) = listToString  Enc.Invoke x : string
    static member inline Encode (t, _: Enc) = t2ToString Enc.Invoke Enc.Invoke t
    static member inline Encode (t, _: Enc) = t3ToString Enc.Invoke Enc.Invoke Enc.Invoke t
    static member inline Encode (t: 'T, _:obj) = Enc.Invoke (^T: (static member ToDict: ^T * _ -> list<string*string>) (t, Enc)) : string

let inline invoke f x = let inline call (_:^A, x:'B) = ((^A or ^B) : (static member Invoke : _-> _) x) in call (f, x)


type Person = { Id: int; Children: Person list } with
    static member inline ToDict (x: Person, encoder) =
        [
            "Id"      , invoke encoder x.Id
            "Children", invoke encoder x.Children
        ]

let p = { Person.Id = 0; Children = [] }

let s = Enc.Invoke p

Expected behavior

Compile.

Actual behavior

~vs1BD9.fsx(30,20): error FS0465: Type inference problem too complicated (maximum iteration depth reached). Consider adding further type annotations.

Known workarounds

None that I know

Related information

Changing the field type Person list to int list compiles fine, because the record no longer have recursive references.

  • Operating system
  • .NET Runtime kind (.NET Core, .NET Framework, Mono)
  • Editing Tools (e.g. Visual Studio Version, Visual Studio)

All versions of F# (including previews for F# 5.0), all platforms as far I could test

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    New

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions