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.82k stars 773 forks source link

"Complex" generic constraints from c# interface can't be implemented #7607

Open manofstick opened 4 years ago

manofstick commented 4 years ago

The following works:

// csharp
public interface FromCSharp
{
    void F<Enumerable>(Enumerable source)
        where Enumerable : System.Collections.IEnumerable;
}

// fsharp
type C<'T>() =
    interface FromCSharp with
        member __.F<'Enumerable
                when 'Enumerable :> System.Collections.IEnumerable
            > (e:'Enumerable) : unit = ()

The following more complex example doesn't (i.e. it introduces another generic type at the interface level):

// csharp
public interface FromCSharp<T>
{
    void F<Enumerable>(Enumerable source)
        where Enumerable : System.Collections.Generic.IEnumerable<T>;
}
// fsharp
type C<'T>() =
    interface FromCSharp<'T> with
        member __.F<'Enumerable
                when 'Enumerable :> System.Collections.Generic.IEnumerable<'T>
            > (e:'Enumerable) : unit = ()

It fails with the following compliation error:

The member 'F<'Enumerable when 'Enumerable :> Collections.Generic.IEnumerable<'T>> : #Collections.Generic.IEnumerable<'T> -> unit' does not have the correct type to override the corresponding abstract method.

If you define the interface in fsharp it does work (even in a different assembly):

type FromFSharp<'T> =
    abstract F<'Enumerable
        when 'Enumerable :> System.Collections.Generic.IEnumerable<'T>> : 'Enumerable -> unit

type C<'T>() =
    interface FromFSharp<'T> with
        member __.F<'Enumerable
                when 'Enumerable :> System.Collections.Generic.IEnumerable<'T>
            > (e:'Enumerable) : unit = ()

No known work around, other than to define all interfaces in fsharp, which is obviously not always an option.

dsyme commented 3 years ago

@manofstick Thanks for this bug report