Skip to content

error FS0073: internal error: Undefined or unsolved type variable when using generic type annotations on DU of DUs with static members requiring 2+ inputs #6648

@swatalla

Description

@swatalla

When attempting to create a discriminated union with a generic type annotation whose cases are types of other generic discriminated unions, the following error FS0073: internal error: Undefined or unsolved type variable: ^_?155636 is thrown after adding static members that require more than 1 input (e.g. op_Subtraction, in the provided example).

Repro steps

Provide the steps required to reproduce the problem

  1. Run the following code in VS2019 FSI
type SomeUnion1<'T> =
    | SomeCase1a of 'T[]
    | SomeCase1b of 'T[]

    static member inline (~-) x =
        match x with
        | SomeCase1a a -> 
            a |> Array.map (fun b -> -b) |> SomeCase1a
        | SomeCase1b b -> 
            b |> Array.map (fun c -> -c) |> SomeCase1b

    static member inline (-) (a, b) =
        match a, b with
        | SomeCase1a x, SomeCase1a y
        | SomeCase1a x, SomeCase1b y ->
            (x, y) ||> Array.map2 (fun u v -> u - v) |> SomeCase1a
        | SomeCase1b x, SomeCase1a y
        | SomeCase1b x, SomeCase1b y ->
            (x, y) ||> Array.map2 (fun u v -> u - v) |> SomeCase1b

type SomeUnion2<'T> =
    | SomeCase2a of 'T[][]
    | SomeCase2b of 'T[][]

    static member inline (~-) x =
        match x with
        | SomeCase2a a -> 
            a |> Array.map (Array.map (fun b -> -b)) |> SomeCase2a
        | SomeCase2b b -> 
            b |> Array.map (Array.map (fun c -> -c)) |> SomeCase2b

    static member inline (-) (a, b) =
        match a, b with
        | SomeCase2a x, SomeCase2a y
        | SomeCase2a x, SomeCase2b y ->
            (x, y) ||> Array.map2 (Array.map2 (fun u v -> u - v)) |> SomeCase2a
        | SomeCase2b x, SomeCase2a y
        | SomeCase2b x, SomeCase2b y ->
            (x, y) ||> Array.map2 (Array.map2 (fun u v -> u - v)) |> SomeCase2b

type UnionOfUnions<'T> =
    | ParentCase1 of SomeUnion1<'T>
    | ParentCase2 of SomeUnion2<'T>

    static member inline (~-) x =
        match x with
        | ParentCase1 a -> -a |> ParentCase1
        | ParentCase2 a -> -a |> ParentCase2

    static member inline (-) (a, b) =
        match a, b with
        | ParentCase1 x, ParentCase1 y -> x - y |> ParentCase1
        | ParentCase2 x, ParentCase2 y -> x - y |> ParentCase2
        | _, _ -> failwith "Cannot subtract these"

Expected behavior

The expected behavior presumably should not throw the internal error. The following example, without the op_Subtraction static member, successfully runs in FSI:

type SomeUnion1<'T> =
    | SomeCase1a of 'T[]
    | SomeCase1b of 'T[]

    static member inline (~-) x =
        match x with
        | SomeCase1a a -> 
            a |> Array.map (fun b -> -b) |> SomeCase1a
        | SomeCase1b b -> 
            b |> Array.map (fun c -> -c) |> SomeCase1b

type SomeUnion2<'T> =
    | SomeCase2a of 'T[][]
    | SomeCase2b of 'T[][]

    static member inline (~-) x =
        match x with
        | SomeCase2a a -> 
            a |> Array.map (Array.map (fun b -> -b)) |> SomeCase2a
        | SomeCase2b b -> 
            b |> Array.map (Array.map (fun c -> -c)) |> SomeCase2b

type UnionOfUnions<'T> =
    | ParentCase1 of SomeUnion1<'T>
    | ParentCase2 of SomeUnion2<'T>

    static member inline (~-) x =
        match x with
        | ParentCase1 a -> -a |> ParentCase1
        | ParentCase2 a -> -a |> ParentCase2

The following input examples can confirm this:

> let case1bTest = Array.init 5 (fun x -> double (x-1)) |> SomeCase1b |> ParentCase1
val case1bTest : UnionOfUnions<double> =
  ParentCase1 (SomeCase1b [|-1.0; 0.0; 1.0; 2.0; 3.0|])
> -case1bTest;;
val it : UnionOfUnions<double> =
  ParentCase1 (SomeCase1b [|1.0; 0.0; -1.0; -2.0; -3.0|])

> let case2aTest = Array.init 6 (fun x -> double (x+2)) |> Array.chunkBySize 2 |> SomeCase2a |> ParentCase2
val case2aTest : UnionOfUnions<double> =
  ParentCase2 (SomeCase2a [|[|2.0; 3.0|]; [|4.0; 5.0|]; [|6.0; 7.0|]|])
> -case2aTest;;
val it : UnionOfUnions<double> =
  ParentCase2 (SomeCase2a [|[|-2.0; -3.0|]; [|-4.0; -5.0|]; [|-6.0; -7.0|]|])

Actual behavior

Running the code snippet given in the Repro section of this issue yields an error:

> error FS0073: internal error: Undefined or unsolved type variable:  ^_?155636

Known workarounds

This problem may be circumvented by not using generic type parameters.

Related information

Provide any related information

  • Operating system - Windows 10
  • Branch - F# 4.6
  • .NET Runtime, CoreCLR or Mono Version
  • Editing Tools (e.g. Visual Studio Version) - VS2019 16.0.1
  • Links to F# RFCs or entries on https://github.com/fsharp/fslang-suggestions
  • Links to performance testing scripts
  • Indications of severity

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