The compiler infers the wrong type.
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
In some situations the compiler tries to unify a type argument contained in a generic type with the generic type itself.
#### Repro steps
```
open System
open System.Collections.Generic
let pInt = Int32.TryParse >> function (true, x) -> Some x | _ -> None
let pString (x:string) =
match x.Trim() with
| x when x.[0..0] = "\"" && x.[x.Length-1..x.Length-1] = "\"" -> Some x.[1..x.Length-2]
| _ -> None
let pTuple2 p1 p2 (x:string) =
match x.Trim() with
| x when x.[0..0] = "(" && x.[x.Length-1..x.Length-1] = ")" ->
let x = x.[1..x.Length-2]
match x.Split(',') with
| [|a; b|] -> match (p1 a, p2 b) with (Some a, Some b) -> Some (a, b) | _ -> None
| _ -> None
| _ -> None
let pList (p:string -> 'a option) (x:string) =
match x.Trim() with
| x when x.[0..0] = "[" && x.[x.Length-1..x.Length-1] = "]" ->
let x = x.[1..x.Length-2]
let x = x.Split(';') |> Array.map p
if x |> Array.forall (fun x -> x.IsSome) then
Some (Array.choose id x |> Array.toList)
else None
| _ -> None
type TryParseCs = TryParseCs with
static member TryParse (_: int ) = pInt
static member TryParse (_: string) = pString
let inline iTryParse (a: ^a, b: ^b) = ((^a or ^b) : (static member TryParse: ^b -> (string -> ^b option)) b)
let inline tryParse (x: string) : 'a option = iTryParse (TryParseCs, Unchecked.defaultof<'a>) x
type TryParseCs with
static member inline TryParse (_: IDictionary) : string -> option> =
pList (pTuple2 pString tryParse) >> function
| Some x -> Some (dict x )
| _ -> None
static member inline TryParse (_: 'a ResizeArray) : string -> option<'a ResizeArray> = pList tryParse >> function
| Some x -> Some (ResizeArray<_>(x))
| _ -> None
```
#### Expected behavior
```
val inline tryParse :
x:string -> ^a option
when (TryParseCs or ^a) : (static member TryParse : ^a ->
string ->
^a option)
```
#### Actual behavior
It doesn't compile
```
~vs4AFB.fsx(43,98): error FS0043: Type mismatch. Expecting a
string -> 'a option
but given a
string -> ResizeArray<'a> option
The resulting type would be infinite when unifying ''a' and 'ResizeArray<'a>'
```
#### Known workarounds
At the end of the code add this overload:
```
static member TryParse (_: 'a Tuple) : string -> option> = fun _ -> Some (Tuple<'a>(Unchecked.defaultof<'a>))
```
#### Related information
This was reported as a [bug in Fleece](https://github.com/mausch/Fleece/issues/3).
Contributor guide
Assessment
This issue has not been assessed yet.