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.88k stars 783 forks source link

No compile-time error for partial implementation of interface with static abstract members #17138

Closed brianrourkeboll closed 4 months ago

brianrourkeboll commented 4 months ago

There is no compile-time error if a type only partially implements an interface with static abstract members (IWSAM). If you try to use the partial implementation, a System.TypeLoadException is raised at runtime.

Repro steps

#nowarn "3535"

type IFace =
    static abstract P1 : int
    static abstract P2 : int

type T =
    interface IFace with
        static member P1 = 1

let inline p1<'T & #IFace> = 'T.P1

p1<T>

Runtime error:

Unhandled exception. System.TypeLoadException: Virtual static method 'get_P2' is not implemented on type 'T' from assembly 'ConsoleApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
   at <StartupCode$ConsoleApp1>.$Program.main@()

Expected behavior

There should be a compile-time error indicating that all abstract methods on the interface must be implemented.

Actual behavior

There is no compile-time error; there is an error at runtime instead.

Known workarounds

N/A

Related information

.NET 8/9 preview.

vzarytovskii commented 4 months ago

It's a regression, since this is what 8.0.100 gives me:

dotnet fsi

Microsoft (R) F# Interactive version ******** for F# 8.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> type IFace =
-     static abstract P1 : int

      static abstract P1 : int
  ----^^^^^^^^^^^^^^^

/Users/u/globaljson/stdin(2,5): warning FS3535: Declaring "interfaces with static abstract methods" is an advanced feature. See https://aka.ms/fsharp-iwsams for guidance. You can disable this warning by using '#nowarn "3535"' or '--nowarn:3535'.

-     static abstract P2 : int

      static abstract P2 : int
  ----^^^^^^^^^^^^^^^

/Users/u/globaljson/stdin(3,5): warning FS3535: Declaring "interfaces with static abstract methods" is an advanced feature. See https://aka.ms/fsharp-iwsams for guidance. You can disable this warning by using '#nowarn "3535"' or '--nowarn:3535'.

-
- type T =
-     interface IFace with
-         static member P1 = 1
-
- let inline p1<'T & #IFace> = 'T.P1
- ;;

      interface IFace with
  --------------^^^^^

/Users/u/globaljson/stdin(6,15): error FS0366: No implementation was given for 'static abstract IFace.P2: int'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.
vzarytovskii commented 4 months ago

And 8.0.201 has the issue, so it happened somewhere in-between

edgarfgp commented 4 months ago

@vzarytovskii I have seen this few week ago. I think we would need to remove the IsInstance check here https://github.com/dotnet/fsharp/blob/7b0586c89f8ceffe72e6c78a4a430648f45a7b27/src/Compiler/Checking/MethodOverrides.fs#L383

vzarytovskii commented 4 months ago

@vzarytovskii I have seen this few week ago. I think we would need to remove the IsInstance check here

https://github.com/dotnet/fsharp/blob/7b0586c89f8ceffe72e6c78a4a430648f45a7b27/src/Compiler/Checking/MethodOverrides.fs#L383

It might be it, however PR it was introduced in wasn't in 17.9 (8.0.201).

Update: nvm, I didn't fetch the branch