Unable to write SRTP constraints for method
When writing the same inline method using statically resolved type parameters two times, first without specifying any type parameters and letting the compiler figure everything out, then by explicitly stating the type parameters and constraints, I can only get the first approach to work.
Repro steps
Place the following type into VS or VS Code.
type Summer () =
member inline _this.SumBy (items, selector) =
Seq.fold (fun acc item ->
acc + selector item
) LanguagePrimitives.GenericZero items
member inline _this.SumBy'<'T, ^U, ^V
when (^V or ^U) : (static member (+) : ^V * ^U -> ^V)
and ^V : (static member Zero : ^V)
> (items : 'T seq, selector : 'T -> ^U) : ^V =
Seq.fold (fun acc item ->
acc + selector item
) LanguagePrimitives.GenericZero items
The acc in the line acc + selector item of SumBy' will be underlined.
Expected behavior
Both SumBy and SumBy' should work.
Actual behavior
SumBy' shows the following:
Known workarounds
Letting the compiler figure everything out. I hope I didn't miss anything obvious...
Or you can do what's described in this comment.
Related information
- Windows 10
- .NET 4.7
- VS 15.8.3 as well as VS Code 1.27.1 with Ionide 3.25.4
Related to #392 and likely a bug, @dsyme do you agree?
Another example for the same effect:
let inline plus< ^T1, ^T2, ^T3 when (^T1 or ^T2) : (static member (+) : ^T1 * ^T2 -> ^T3)> (x: ^T1) (y: ^T2) : ^T3 =
x + y
@TIHan interesting, your example is reported as an error in both VS & VS Code, while my example is reported only as a warning, and will run.
While digging around a bit more, I just noticed this comment in the F# source code: This helps the somewhat complicated type inference for AverageByNullable and SumByNullable, by making both type in a '+' the same.
And indeed, when I use this, the error in @TIHan 's example is gone (after editing the constraint as suggested by the compiler):
let inline plus' (x:'T) (y:'T) = Checked.(+) x y
let inline plus< ^T1, ^T2 when ^T1 : (static member (+) : ^T1 * ^T1 -> ^T2)> (x: ^T1) (y: ^T1) : ^T2 =
plus' x y
I do agree that being explicit should be ok in these cases. So I consider this a bug