Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/release-notes/.FSharp.Compiler.Service/8.0.400.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Fixed

* Various parenthesization API fixes. ([PR #16977](https://github.com/dotnet/fsharp/pull/16977))
* Disallow calling abstract methods directly on interfaces. ([Issue #14012](https://github.com/dotnet/fsharp/issues/14012), [Issue #16299](https://github.com/dotnet/fsharp/issues/16299), [PR #17021](https://github.com/dotnet/fsharp/pull/17021))
* Various parenthesization API fixes. ([PR #16977](https://github.com/dotnet/fsharp/pull/16977))
* Fix bug in optimization of for-loops over integral ranges with steps and units of measure. ([Issue #17025](https://github.com/dotnet/fsharp/issues/17025), [PR #17040](https://github.com/dotnet/fsharp/pull/17040))
* Fix calling an overridden virtual static method via the interface ([PR #17013](https://github.com/dotnet/fsharp/pull/17013))
19 changes: 16 additions & 3 deletions src/Compiler/Checking/ConstraintSolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2942,10 +2942,23 @@ and ResolveOverloading
let candidates = calledMethGroup |> List.filter (fun cmeth -> cmeth.IsCandidate(m, ad))

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 static/virtual/abstract

// If false then is a static method call directly on an interface e.g.
// IParsable.Parse(...)
// IAdditionOperators.(+)
// This is not allowed as Parse and (+) method are static abstract
let isStaticConstrainedCall =
match calledMeth.OptionalStaticType with
| Some ttype -> isTyparTy g ttype
| None -> false

match calledMeth.Method with
| ILMeth(ilMethInfo= ilMethInfo) when not isStaticConstrainedCall && ilMethInfo.IsStatic && ilMethInfo.IsAbstract ->
None, ErrorD (Error (FSComp.SR.chkStaticAbstractInterfaceMembers(ilMethInfo.ILName), m)), NoTrace
| _ -> Some calledMeth, CompleteD, NoTrace

| [], _ when not isOpConversion ->
None, ErrorD (Error (FSComp.SR.csMethodNotFound(methodName), m)), NoTrace
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1745,4 +1745,5 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [<Struct>] di
3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration."
3863,parsExpectingField,"Expecting record field"
3864,tooManyMethodsInDotNetTypeWritingAssembly,"The type '%s' has too many methods. Found: '%d', maximum: '%d'"
3865,parsOnlySimplePatternsAreAllowedInConstructors,"Only simple patterns are allowed in primary constructors"
3865,parsOnlySimplePatternsAreAllowedInConstructors,"Only simple patterns are allowed in primary constructors"
3866,chkStaticAbstractInterfaceMembers,"A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.%s)."
5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compiler/xlf/FSComp.txt.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#nowarn "64"
open System
open System.Numerics

module ConstrainedCall =
let ``'T.op_Addition``<'T & #IAdditionOperators<'T, 'T, 'T>> x y = 'T.op_Addition (x, y)
let ``'T.(+)``<'T & #IAdditionOperators<'T, 'T, 'T>> x y = 'T.(+) (x, y)
let ``'T.op_CheckedAddition``<'T & #IAdditionOperators<'T, 'T, 'T>> x y = 'T.op_CheckedAddition (x, y)
let ``'T.Parse``<'T & #IParsable<'T>> x = 'T.Parse (x, null)

module InterfaceCall =
let ``IAdditionOperators.op_Addition`` x y = IAdditionOperators.op_Addition (x, y)
let ``IAdditionOperators.(+)`` x y = IAdditionOperators.(+) (x, y)
let ``IAdditionOperators.op_CheckedAddition`` x y = IAdditionOperators.op_CheckedAddition (x, y)
let ``IParsable.Parse``<'T & #IParsable<'T>> x : 'T = IParsable.Parse (x, null)

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,18 @@ module TypesAndTypeConstraints_IWSAMsAndSRTPs =
|> asExe
|> withLangVersion70
|> withReferences [typesModule]

let verifyCompile compilation =
compilation
|> asExe
|> withOptions ["--nowarn:988"]
|> compile

let verifyCompileAndRun compilation =
compilation
|> asExe
|> withOptions ["--nowarn:988"]
|> compileAndRun

[<Fact>]
let ``Srtp call Zero property returns valid result`` () =
Expand Down Expand Up @@ -1183,4 +1195,50 @@ let execute = IPrintable.Say("hello")
|> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ]
|> withLangVersion80
|> typecheck
|> shouldSucceed
|> shouldSucceed

[<FactForNETCOREAPP>]
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 3866, Line 4, Col 1, Line 4, Col 38, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.op_Addition).")

[<FactForNETCOREAPP>]
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"

#if !NETCOREAPP
[<Theory(Skip = "IWSAMs are not supported by NET472.")>]
#else
// SOURCE=ConstrainedAndInterfaceCalls.fs # ConstrainedAndInterfaceCalls.fs
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"ConstrainedAndInterfaceCalls.fs"|])>]
#endif
let ``ConstrainedAndInterfaceCalls.fs`` compilation =
compilation
|> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ]
|> verifyCompile
|> shouldFail
|> withDiagnostics [
(Error 3866, Line 12, Col 82, Line 12, Col 126, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.op_Addition).")
(Error 3866, Line 13, Col 82, Line 13, Col 126, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.op_Addition).")
(Error 3866, Line 15, Col 82, Line 15, Col 129, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.Parse).")
]