dotnet / fsharp

The F# compiler, F# core library, F# language service, and F# tooling integration for Visual Studio
https://dotnet.microsoft.com/languages/fsharp
MIT License
3.94k stars 788 forks source link

Unable to write SRTP constraints for method #5620

Open nikonthethird opened 6 years ago

nikonthethird commented 6 years ago

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:

sumby

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

cartermp commented 6 years ago

Related to #392 and likely a bug, @dsyme do you agree?

TIHan commented 6 years ago

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
nikonthethird commented 6 years ago

@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.

error_warning

nikonthethird commented 6 years ago

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
dsyme commented 6 years ago

I do agree that being explicit should be ok in these cases. So I consider this a bug