Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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,3 +1,4 @@
### Fixed

Various parenthesization API fixes. ([PR #16977](https://github.com/dotnet/fsharp/pull/16977))
* Disallow calling abstract methods directly on interfaces. ([PR #16319](https://github.com/dotnet/fsharp/pull/16319))
* Various parenthesization API fixes. ([PR #16977](https://github.com/dotnet/fsharp/pull/16977))
20 changes: 17 additions & 3 deletions src/Compiler/Checking/ConstraintSolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2942,10 +2942,24 @@ 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 ->
// Don't want to make available via completion, as it will lead to the compile time error e.g. not usable if it's non-virtual
None, ErrorD (Error (FSComp.SR.chkStaticAbstractInterfaceMembers(), 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 interface member can be accessed only on a type parameter."
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 interface member can be accessed only on a type parameter.")

[<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 # AssemblyVersion01.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 interface member can be accessed only on a type parameter.")
(Error 3866, Line 13, Col 82, Line 13, Col 126, "A static abstract interface member can be accessed only on a type parameter.")
(Error 3866, Line 15, Col 82, Line 15, Col 129, "A static abstract interface member can be accessed only on a type parameter.")
]