diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index 57bc1578db3..3ff7b03658a 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -1,5 +1,6 @@ ### Fixed +* Disallow calling abstract methods directly on interfaces. ([PR #16319](https://github.com/dotnet/fsharp/pull/16319)) * Fix a false positive of the `[]` analysis in combination with `yield!`. ([PR #16933](https://github.com/dotnet/fsharp/pull/16933)) * Improve error reporting: ambiguous override method in object expression. ([PR #16985](https://github.com/dotnet/fsharp/pull/16985)) * Don't blow the stack when traversing deeply nested sequential expressions. ([PR #16882](https://github.com/dotnet/fsharp/pull/16882)) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 4f7b56ebf11..6c7b88cc7c9 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -9955,9 +9955,9 @@ and TcMethodApplication let finalCalledMeth = let callerArgs = { Unnamed = unnamedCurriedCallerArgs ; Named = namedCurriedCallerArgs } - let postArgumentTypeCheckingCalledMethGroup = - preArgumentTypeCheckingCalledMethGroup |> List.map (fun (minfo, minst, pinfoOpt, usesParamArrayConversion) -> + preArgumentTypeCheckingCalledMethGroup + |> List.map (fun (minfo, minst, pinfoOpt, usesParamArrayConversion) -> let callerTyArgs = match tyArgsOpt with | Some tyargs -> minfo.AdjustUserTypeInstForFSharpStyleIndexedExtensionMembers tyargs diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 2667ea6ccfc..be51f822da3 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -2944,8 +2944,17 @@ and ResolveOverloading let calledMethOpt, errors, calledMethTrace = match calledMethGroup, candidates with - | _, [calledMeth] when not isOpConversion -> - Some calledMeth, CompleteD, NoTrace + | _, [calledMeth] when not isOpConversion -> + // See what candidates we have based on name and arity, and check for static/virtual/abstract + // OK: static virtual TResult operator checked i.e. IAdditionOperators.op_CheckedAddition + // Error: static abstract TResult operator i.e. IAdditionOperators.op_Addition + match calledMeth.Method with + | ILMeth(ilMethInfo= ilMethInfo) when ilMethInfo.IsStatic && ilMethInfo.IsVirtual && methodName.Contains("op_") -> + if ilMethInfo.IsAbstract then + None, ErrorD (Error (FSComp.SR.csMethodNotFound(methodName), m)), NoTrace + else + Some calledMeth, CompleteD, NoTrace + | _ -> Some calledMeth, CompleteD, NoTrace | [], _ when not isOpConversion -> None, ErrorD (Error (FSComp.SR.csMethodNotFound(methodName), m)), NoTrace diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs index d3d7be2cf36..cf58beda731 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -1183,4 +1183,33 @@ let execute = IPrintable.Say("hello") |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] |> withLangVersion80 |> typecheck - |> shouldSucceed \ No newline at end of file + |> shouldSucceed + + [] + let ``Accessing to IWSAM(System.Numerics non virtual) produces a compilation error`` () = + Fsx """ +open System.Numerics + +IAdditionOperators.op_Addition (3, 6) + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> compile + |> shouldFail + |> withSingleDiagnostic (Error 509, Line 4, Col 1, Line 4, Col 38, "Method or object constructor 'op_Addition' not found") + + [] + let ``Accessing to IWSAM(System.Numerics virtual member) compiles and runs`` () = + Fsx """ +open System.Numerics + +let res = IAdditionOperators.op_CheckedAddition (3, 6) + +printf "%A" res""" + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> asExe + |> compile + |> shouldSucceed + |> run + |> verifyOutput "9" \ No newline at end of file