-
Notifications
You must be signed in to change notification settings - Fork 842
Description
Long time ago I was trying to define generic constants, something like the existing GenericZero and GenericOne, but involving a method constraint of a typar and a specific type since we can't simulate static member outside the F# compiler.
But writing those signatures were not possible because of this limitation the only solution I found was involving a phantom type:
type M() =
static member ($) (x:string, M) = ""
static member ($) (x:int , M) = 0
static member ($) (x:float , M) = 0.0
let inline empty< ^R, ^M when (^R or ^M) : (static member ($) : ^R * M -> ^R) and ^M :> M> =
let m = M()
((^R or ^M) : (static member ($): ^R * M -> ^R ) (Unchecked.defaultof<'R>, m))
let a :int = empty< _ , M >
let b :string = empty< _ , M >
But now that there is a PR which solves that issue I tried again using that version and found that in fact that limitation was hiding a bug in the type inference.
Repro steps
. Download the fixed F# compiler
. type build
. open it with Visual Studio
. Set FSIANYCPU as Start Project
. Press F5
. Paste this code:
type M() =
static member ($) (x:string, M) = ""
static member ($) (x:int , M) = 0
static member ($) (x:float , M) = 0.0
let inline empty< ^R when ( ^R or M) : (static member ( $ ) : ^R * M -> ^R)> =
let m = M()
Unchecked.defaultof< ^R> $ m: ^R
Expected behavior
val inline empty< ^R when ( ^R or M) : (static member ( $ ) : ^R * M -> ^R) > :
^R when ( ^R or M) : (static member ( $ ) : ^R * M -> ^R)
Actual behavior
It fails to compile with this error:
Unchecked.defaultof< ^R> $ (m:M) : ^R;;
----^^^^^^^^^^^^^^^^^^^^^^^^
stdin(155,5): error FS0001: A type parameter is missing a constraint 'when ( ^R or ^_arg2) : (static member ( $ ) : ^R * ^_arg2 -> ^R)'
Known workarounds
No workaround found apart from the phantom type solution above mentioned which is very ugly.
Related information
Branch:
BTW: why in cases like this (even without the fix) the compiler complains about a missing constraint instead of inferring it for you as it does normally?