From b74d8da2da278eed53a1a1c229cc08dccbb11abd Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Tue, 14 Nov 2023 21:22:29 +0000 Subject: [PATCH 1/7] No diagnostic about static member in object expression --- src/Compiler/Checking/MethodOverrides.fs | 5 +++-- .../IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs | 10 ++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Compiler/Checking/MethodOverrides.fs b/src/Compiler/Checking/MethodOverrides.fs index f467dc8db25..6519c2b78b6 100644 --- a/src/Compiler/Checking/MethodOverrides.fs +++ b/src/Compiler/Checking/MethodOverrides.fs @@ -379,8 +379,9 @@ module DispatchSlotChecking = // error reporting path let compiledSig = CompiledSigOfMeth g amap m dispatchSlot - let noimpl() = - missingOverloadImplementation.Add((isReqdTyInterface, lazy NicePrint.stringOfMethInfo infoReader m denv dispatchSlot)) + let noimpl() = + if (isObjExpr && dispatchSlot.IsInstance) || dispatchSlot.IsInstance then + missingOverloadImplementation.Add((isReqdTyInterface, lazy NicePrint.stringOfMethInfo infoReader m denv dispatchSlot)) match overrides |> List.filter (IsPartialMatch g dispatchSlot compiledSig) with | [] -> 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 0685988d23c..84cfaee354c 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -1189,10 +1189,7 @@ consoleLogger.Log("Hello World") |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] |> withLangVersion80 |> compile - |> shouldFail - |> withDiagnostics [ - (Error 366, Line 7, Col 5, Line 10, Col 6, "No implementation was given for 'static abstract ILogger.Execute: string -> unit'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") - ] + |> shouldSucceed [] let ``Produces an error when implementing only instance members from IWSAM(Interface attribute) in an object expression`` () = @@ -1213,10 +1210,7 @@ consoleLogger.Log("Hello World") |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] |> withLangVersion80 |> compile - |> shouldFail - |> withDiagnostics [ - (Error 366, Line 8, Col 5, Line 11, Col 6, "No implementation was given for 'static abstract ILogger.Execute: string -> unit'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") - ] + |> shouldSucceed [] let ``No error when implementing only instance members from a type(Interface attribute) in an object expression`` () = From c8e9de237688eecce2f60ec8794e8aa74a73d12c Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Thu, 16 Nov 2023 11:51:52 +0000 Subject: [PATCH 2/7] Move object expressions tests to its own file and improve testing in general --- .../ObjectExpression/ObjectExpression.fs | 318 ++++++++++++++++++ .../IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs | 153 --------- .../FSharp.Compiler.ComponentTests.fsproj | 1 + 3 files changed, 319 insertions(+), 153 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs new file mode 100644 index 00000000000..54df9972c6a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs @@ -0,0 +1,318 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Conformance.Expressions + +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +module ObjectExpressionsTests = + + [] + let ``Object expression ca not implement unnamed interface`` () = + Fsx """ +type IFirst = + abstract member MyMember: unit -> int + +let x = { new _ with member this.MyMember() = 42 } + """ + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 772, Line 5, Col 11, Line 5, Col 16, "'new' must be used with a named type") + ] + + [] + let ``Object expression implementing an interface without members`` () = + Fsx """ +type IFirst = interface end + +let implementer() ={ new IFirst } + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Parameterized object expression implementing an interface with members`` () = + Fsx """ +type AsString = + abstract member asString: unit -> string + +type SomeDu = + | A of int + | B of string + | C of float + +let implSomeDU someDu = + { new AsString with + member self.asString () = + match someDu with + | A a -> string a + | B b -> b + | C c -> string c } + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Object expression can not implement an abstract class having no abstract members.`` () = + Fsx """ +[] +type Foo() = class end + +let foo = { new Foo() } // Approved suggestion to allow this https://github.com/fsharp/fslang-suggestions/issues/632 + +// hacky workaround +let foo = { new Foo() with member __.ToString() = base.ToString() } + """ + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 738, Line 5, Col 11, Line 5, Col 24, "Invalid object expression. Objects without overrides or interfaces should use the expression form 'new Type(args)' without braces.") + (Error 740, Line 5, Col 11, Line 5, Col 24, "Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq { ... }'") + ] + + [] + let ``Object expression can not implementin an interface when it contains a method with no types that can refer to the type for which the implementation is being used`` () = + Fsx """ +type AsString = + abstract member asString: unit -> string + +type AsString2<'T> = + abstract member asString: 'T -> string + +type SomeDu = + | A of int + | B of string + | C of float + interface AsString + with member self.asString () = + match self with + | A a -> string a + | B b -> b + | C c -> string c + interface AsString2 + with member self.asString x = + if not (x = self) then failwith "argument must be the member container" + match self with + | A a -> string a + | B b -> b + | C c -> string c + +//this expression was expected to have type AsString but here has type SomeDU +let implSomeDU = + {new AsString with + member self.asString () = + match self with + | A a -> string a + | B b -> b + | C c -> string c} + """ + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 1, Line 31, Col 15, Line 31, Col 18, "This expression was expected to have type + 'AsString' +but here has type + 'SomeDu' ") + ] + + [] + let ``Object expression implementing multiple interfaces`` () = + Fsx """ +// Define two interfaces +type IFirst = + abstract F : unit -> unit + abstract G : unit -> unit + +type ISecond = + inherit IFirst + abstract H : unit -> unit + abstract J : unit -> unit + +// This object expression implements both interfaces. +let implementer() = + { new ISecond with + member this.H() = () + member this.J() = () + interface IFirst with + member this.F() = () + member this.G() = () } + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Object expression implementing an interface`` () = + Fsx """ +type IOperation = + abstract member Execute: unit -> unit + abstract member Execute1: unit -> bool + abstract member Property: int + +let objExpr = + { new IOperation with + member this.Execute() = () + member this.Execute1() = false + member this.Property = 0 } + """ + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``Produce an error when one leaves out keyword "static" when implementing IWSAM in an object expression`` () = + Fsx """ +type IOperation = + static abstract member Execute: unit -> unit + abstract member Execute2: unit -> unit + +let objExpr = + { new IOperation with + member _.Execute() = () + member _.Execute2() = () } + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 17, Line 8, Col 18, Line 8, Col 25, "The member 'Execute: unit -> unit' does not have the correct type to override the corresponding abstract method. Non-static member is expected."); + (Error 783, Line 7, Col 11, Line 7, Col 21, "At least one override did not correctly implement its corresponding abstract member") + ] + + [] + let ``Produce an error when one leaves keyword "static" when implementing IWSAM in an object expression`` () = + Fsx """ +type IOperation = + static abstract member Execute: unit -> unit + abstract member Execute2: unit -> unit + +let _ = + { new IOperation with + static member Execute() = () + member _.Execute2() = () + } + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3860, Line 8, Col 23, Line 8, Col 30, "Static members are not allowed in object expressions.") + ] + + [] + let ``Produce an error when one leaves keyword "static" when implementing multiple IWSAM in an object expression`` () = + Fsx """ +type IOperation = + static abstract member Execute: unit -> unit + static abstract member Execute2: unit -> unit + +let _ = + { new IOperation with + static member Execute() = () + static member Execute2() = () + } + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3860, Line 8, Col 23, Line 8, Col 30, "Static members are not allowed in object expressions."); + (Error 3860, Line 9, Col 23, Line 9, Col 31, "Static members are not allowed in object expressions.") + ] + + [] + let ``Produce an error when one leaves keyword "static" when implementing static and not static members in an object expression`` () = + Fsx """ +type IOperation = + static abstract member Execute: unit -> unit + abstract member Execute1: unit -> unit + static abstract member Execute2: unit -> unit + abstract member Execute3: bool + +let _ = + { new IOperation with + static member Execute() = () + member this.Execute1() = () + static member Execute2() = () + member this.Execute3 = true + } + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3860, Line 10, Col 23, Line 10, Col 30, "Static members are not allowed in object expressions."); + (Error 3860, Line 12, Col 23, Line 12, Col 31, "Static members are not allowed in object expressions."); + ] + + [] + let ``No error when implementing only instance members from IWSAM in an object expression`` () = + Fsx """ +type ILogger = + abstract member Log: string -> unit + static abstract member Execute: string -> unit + +let consoleLogger = + { new ILogger with + member this.Log(message: string) = + printfn "%s" message + } + +consoleLogger.Log("Hello World") + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> compile + |> shouldSucceed + + [] + let ``No error when implementing only instance members from IWSAM(Interface attribute) in an object expression`` () = + Fsx """ +[] +type ILogger = + abstract member Log: string -> unit + static abstract member Execute: string -> unit + +let consoleLogger = + { new ILogger with + member this.Log(message: string) = + printfn "%s" message + } + +consoleLogger.Log("Hello World") + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> compile + |> shouldSucceed + + [] + let ``No error when implementing only instance members from a type(Interface attribute) in an object expression`` () = + Fsx """ +[] +type ILogger = + abstract member Log: string -> unit + static member Execute x = x + +let consoleLogger = + { new ILogger with + member this.Log(message: string) = + printf "%A" message + } + +consoleLogger.Log("Hello World") + """ + |> withLangVersion80 + |> compile + |> shouldSucceed \ No newline at end of file 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 84cfaee354c..05667f6205c 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -114,7 +114,6 @@ let main _ = |> withLangVersion60 |> signaturesShouldContain "val g0: x: obj -> obj" - [] [() = (^T : (static member StaticProperty: int) ())")>] [ int) >() = (^T : (static member get_StaticProperty: unit -> int) ())")>] @@ -1079,158 +1078,6 @@ module StaticAbstractBug = (Error 855, Line 13, Col 25, Line 13, Col 32, "No abstract or interface member was found that corresponds to this override") (Error 855, Line 17, Col 25, Line 17, Col 32, "No abstract or interface member was found that corresponds to this override") ] - - [] - let ``Produce an error when one leaves out keyword "static" when implementing IWSAM in an object expression`` () = - Fsx """ -module StaticAbstractBug = - type IOperation = - static abstract member Execute: unit -> unit - abstract member Execute2: unit -> unit - - let objExpr = - { new IOperation with - member _.Execute() = () - member _.Execute2() = () } - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldFail - |> withDiagnostics [ - (Error 17, Line 9, Col 22, Line 9, Col 29, "The member 'Execute: unit -> unit' does not have the correct type to override the corresponding abstract method. Non-static member is expected.") - (Error 783, Line 8, Col 15, Line 8, Col 25, "At least one override did not correctly implement its corresponding abstract member") - ] - - [] - let ``Produce an error when one leaves keyword "static" when implementing IWSAM in an object expression`` () = - Fsx """ -type IOperation = - static abstract member Execute: unit -> unit - abstract member Execute2: unit -> unit - -let _ = - { new IOperation with - static member Execute() = () - member _.Execute2() = () - } - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldFail - |> withDiagnostics [ - (Error 3860, Line 8, Col 23, Line 8, Col 30, "Static members are not allowed in object expressions.") - ] - - [] - let ``Produce an error when one leaves keyword "static" when implementing multiple IWSAM in an object expression`` () = - Fsx """ -type IOperation = - static abstract member Execute: unit -> unit - static abstract member Execute2: unit -> unit - -let _ = - { new IOperation with - static member Execute() = () - static member Execute2() = () - } - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldFail - |> withDiagnostics [ - (Error 3860, Line 8, Col 23, Line 8, Col 30, "Static members are not allowed in object expressions."); - (Error 3860, Line 9, Col 23, Line 9, Col 31, "Static members are not allowed in object expressions.") - ] - - [] - let ``Produce an error when one leaves keyword "static" when implementing static and not static members in an object expression`` () = - Fsx """ -type IOperation = - static abstract member Execute: unit -> unit - abstract member Execute1: unit -> unit - static abstract member Execute2: unit -> unit - abstract member Execute3: bool - -let _ = - { new IOperation with - static member Execute() = () - member this.Execute1() = () - static member Execute2() = () - member this.Execute3 = true - } - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldFail - |> withDiagnostics [ - (Error 3860, Line 10, Col 23, Line 10, Col 30, "Static members are not allowed in object expressions."); - (Error 3860, Line 12, Col 23, Line 12, Col 31, "Static members are not allowed in object expressions."); - ] - - [] - let ``Produces an error when implementing only instance members from IWSAM in an object expression`` () = - Fsx """ -type ILogger = - abstract member Log: string -> unit - static abstract member Execute: string -> unit - -let consoleLogger = - { new ILogger with - member this.Log(message: string) = - printfn "%s" message - } - -consoleLogger.Log("Hello World") - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldSucceed - - [] - let ``Produces an error when implementing only instance members from IWSAM(Interface attribute) in an object expression`` () = - Fsx """ -[] -type ILogger = - abstract member Log: string -> unit - static abstract member Execute: string -> unit - -let consoleLogger = - { new ILogger with - member this.Log(message: string) = - printfn "%s" message - } - -consoleLogger.Log("Hello World") - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldSucceed - - [] - let ``No error when implementing only instance members from a type(Interface attribute) in an object expression`` () = - Fsx """ -[] -type ILogger = - abstract member Log: string -> unit - static member Execute x = x - -let consoleLogger = - { new ILogger with - member this.Log(message: string) = - printf "%A" message - } - -consoleLogger.Log("Hello World") - """ - |> withLangVersion80 - |> compile - |> shouldSucceed [] let ``Produces errors when includes keyword "static" when implementing a generic interface in a type`` () = diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 50d81f50ee7..cfd7b002b9f 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -78,6 +78,7 @@ + From eaab54ab17ed0be26c2fe601178b6c4ef25e99aa Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Thu, 16 Nov 2023 16:51:48 +0000 Subject: [PATCH 3/7] Update src/Compiler/Checking/MethodOverrides.fs Co-authored-by: Adam Boniecki <20281641+abonie@users.noreply.github.com> --- src/Compiler/Checking/MethodOverrides.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler/Checking/MethodOverrides.fs b/src/Compiler/Checking/MethodOverrides.fs index 6519c2b78b6..9593ff9bb02 100644 --- a/src/Compiler/Checking/MethodOverrides.fs +++ b/src/Compiler/Checking/MethodOverrides.fs @@ -380,7 +380,7 @@ module DispatchSlotChecking = let compiledSig = CompiledSigOfMeth g amap m dispatchSlot let noimpl() = - if (isObjExpr && dispatchSlot.IsInstance) || dispatchSlot.IsInstance then + if dispatchSlot.IsInstance then missingOverloadImplementation.Add((isReqdTyInterface, lazy NicePrint.stringOfMethInfo infoReader m denv dispatchSlot)) match overrides |> List.filter (IsPartialMatch g dispatchSlot compiledSig) with From ee65c25a84e47c091db4b4e79d6ea20bd1ae9c29 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Fri, 17 Nov 2023 19:09:44 +0000 Subject: [PATCH 4/7] Update tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs Co-authored-by: Petr --- .../Expressions/ObjectExpression/ObjectExpression.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs index 54df9972c6a..6f27484d8fa 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs @@ -9,7 +9,7 @@ open FSharp.Test.Compiler module ObjectExpressionsTests = [] - let ``Object expression ca not implement unnamed interface`` () = + let ``Object expression cannot implement unnamed interface`` () = Fsx """ type IFirst = abstract member MyMember: unit -> int From 2a85f4a389d20479f0fcd537af0d5dc3b371e9f7 Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Fri, 17 Nov 2023 19:10:40 +0000 Subject: [PATCH 5/7] Renaming --- .../ObjectExpressions.fs} | 2 +- .../FSharp.Compiler.ComponentTests.fsproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/{ObjectExpression/ObjectExpression.fs => ObjectExpressions/ObjectExpressions.fs} (98%) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs similarity index 98% rename from tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs rename to tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs index 54df9972c6a..795fb1f2b36 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpression/ObjectExpression.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs @@ -77,7 +77,7 @@ let foo = { new Foo() with member __.ToString() = base.ToString() } ] [] - let ``Object expression can not implementin an interface when it contains a method with no types that can refer to the type for which the implementation is being used`` () = + let ``Object expression can not implementing an interface when it contains a method with no types that can refer to the type for which the implementation is being used`` () = Fsx """ type AsString = abstract member asString: unit -> string diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index cfd7b002b9f..1c835b603da 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -78,7 +78,7 @@ - + From fe596017640ddb5fe4e53f8a1694f2837288f3af Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Fri, 17 Nov 2023 21:31:45 +0000 Subject: [PATCH 6/7] more tests --- .../IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) 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 05667f6205c..7a5b9991113 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -1139,4 +1139,49 @@ module StaticAbstractBug = (Error 3855, Line 12, Col 27, Line 12, Col 34, "No static abstract member was found that corresponds to this override") (Error 3859, Line 13, Col 27, Line 13, Col 35, "No static abstract property was found that corresponds to this override") (Error 3859, Line 14, Col 27, Line 14, Col 35, "No static abstract property was found that corresponds to this override") - ] \ No newline at end of file + ] + + [] + let ``No error when implementing interfaces with static members by using class types`` () = + Fsx """ +type IPrintable = + abstract member Print: unit -> unit + static abstract member Log: string -> string + +type SomeClass1(x: int, y: float) = + member this.GetPrint() = (this :> IPrintable).Print() + + interface IPrintable with + member this.Print() = printfn $"%d{x} %f{y}" + static member Log(s: string) = s + +let someClass = SomeClass1(1, 2.0) :> IPrintable +let someClass1 = SomeClass1(1, 2.0) + +someClass.Print() +someClass1.GetPrint() + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] + let ``No error when implementing interfaces with static members and IWSAM by using class types`` () = + Fsx """ +[] +type IPrintable = + static abstract member Log: string -> string + static member Say(s: string) = s + +type SomeClass1() = + interface IPrintable with + static member Log(s: string) = s + +let someClass1 = SomeClass1() +let execute = IPrintable.Say("hello") + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withLangVersion80 + |> typecheck + |> shouldSucceed \ No newline at end of file From 423d8d4ab8b669cf357c08875680c608ddf126ed Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Mon, 20 Nov 2023 13:19:26 +0000 Subject: [PATCH 7/7] Improve error message and tests --- src/Compiler/Checking/CheckExpressions.fs | 4 ++++ src/Compiler/FSComp.txt | 2 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.de.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.es.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.fr.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.it.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.ja.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.ko.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.pl.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.ru.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.tr.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 4 ++-- .../ObjectExpressions/ObjectExpressions.fs | 22 ++++++++++++------- 16 files changed, 45 insertions(+), 35 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 5c2239b073e..4b4bb2b4025 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -7033,6 +7033,10 @@ and TcObjectExpr (cenv: cenv) env tpenv (objTy, realObjTy, argopt, binds, extraI // 2. check usage conditions overridesAndVirts |> List.iter (fun (m, implTy, dispatchSlots, dispatchSlotsKeyed, availPriorOverrides, overrides) -> let overrideSpecs = overrides |> List.map fst + let hasStaticMembers = dispatchSlots |> List.exists (fun reqdSlot -> not reqdSlot.MethodInfo.IsInstance) + + if hasStaticMembers then + errorR(Error(FSComp.SR.chkStaticMembersOnObjectExpressions(), mObjTy)) DispatchSlotChecking.CheckOverridesAreAllUsedOnce (env.DisplayEnv, g, cenv.infoReader, true, implTy, dispatchSlotsKeyed, availPriorOverrides, overrideSpecs) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index c96c6929194..371d9c1b45d 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1730,4 +1730,4 @@ featureUnmanagedConstraintCsharpInterop,"Interop between C#'s and F#'s unmanaged 3584,tcDotLambdaAtNotSupportedExpression,"Shorthand lambda syntax is only supported for atomic expressions, such as method, property, field or indexer on the implied '_' argument. For example: 'let f = _.Length'." 3855,tcNoStaticMemberFoundForOverride,"No static abstract member was found that corresponds to this override" 3859,tcNoStaticPropertyFoundForOverride,"No static abstract property was found that corresponds to this override" -3860,chkStaticMembersOnObjectExpressions,"Static members are not allowed in object expressions." \ No newline at end of file +3860,chkStaticMembersOnObjectExpressions,"Object expressions cannot implement interfaces with static abstract members or declare static members." \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 64231d9d694..c0d088ea3f9 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index c689aaa5840..3803d2bf627 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index b4427cbcaf7..fa96a65979a 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 349e8ad63fd..e21b188aa68 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 55c55facb7e..72a5376bedb 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 0c06cac0f88..7aadd7ccd3a 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 3d9583d3222..a9a6edf8c68 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 65dca15b653..fcc032441fe 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index ba4b50a2c6a..d56df03beb9 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index e3963936887..7a1e4262565 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index a1e87d37ec8..724de8db79c 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index a9ed1325b64..a10b2125d6e 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 6bef41283f5..ad37f7fdc29 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -123,8 +123,8 @@ - Static members are not allowed in object expressions. - Static members are not allowed in object expressions. + Object expressions cannot implement interfaces with static abstract members or declare static members. + Object expressions cannot implement interfaces with static abstract members or declare static members. diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs index b4755890c66..f45e1bf1f45 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs @@ -183,6 +183,7 @@ let objExpr = |> typecheck |> shouldFail |> withDiagnostics [ + (Error 3860, Line 7, Col 11, Line 7, Col 21, "Object expressions cannot implement interfaces with static abstract members or declare static members.") (Error 17, Line 8, Col 18, Line 8, Col 25, "The member 'Execute: unit -> unit' does not have the correct type to override the corresponding abstract method. Non-static member is expected."); (Error 783, Line 7, Col 11, Line 7, Col 21, "At least one override did not correctly implement its corresponding abstract member") ] @@ -205,7 +206,8 @@ let _ = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3860, Line 8, Col 23, Line 8, Col 30, "Static members are not allowed in object expressions.") + (Error 3860, Line 7, Col 11, Line 7, Col 21, "Object expressions cannot implement interfaces with static abstract members or declare static members."); + (Error 3860, Line 8, Col 23, Line 8, Col 30, "Object expressions cannot implement interfaces with static abstract members or declare static members.") ] [] @@ -226,8 +228,9 @@ let _ = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3860, Line 8, Col 23, Line 8, Col 30, "Static members are not allowed in object expressions."); - (Error 3860, Line 9, Col 23, Line 9, Col 31, "Static members are not allowed in object expressions.") + (Error 3860, Line 7, Col 11, Line 7, Col 21, "Object expressions cannot implement interfaces with static abstract members or declare static members.") + (Error 3860, Line 8, Col 23, Line 8, Col 30, "Object expressions cannot implement interfaces with static abstract members or declare static members."); + (Error 3860, Line 9, Col 23, Line 9, Col 31, "Object expressions cannot implement interfaces with static abstract members or declare static members.") ] [] @@ -252,8 +255,9 @@ let _ = |> typecheck |> shouldFail |> withDiagnostics [ - (Error 3860, Line 10, Col 23, Line 10, Col 30, "Static members are not allowed in object expressions."); - (Error 3860, Line 12, Col 23, Line 12, Col 31, "Static members are not allowed in object expressions."); + (Error 3860, Line 9, Col 11, Line 9, Col 21, "Object expressions cannot implement interfaces with static abstract members or declare static members.") + (Error 3860, Line 10, Col 23, Line 10, Col 30, "Object expressions cannot implement interfaces with static abstract members or declare static members."); + (Error 3860, Line 12, Col 23, Line 12, Col 31, "Object expressions cannot implement interfaces with static abstract members or declare static members."); ] [] @@ -274,7 +278,8 @@ consoleLogger.Log("Hello World") |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] |> withLangVersion80 |> compile - |> shouldSucceed + |> shouldFail + |> withSingleDiagnostic (Error 3860, Line 7, Col 11, Line 7, Col 18, "Object expressions cannot implement interfaces with static abstract members or declare static members.") [] let ``No error when implementing only instance members from IWSAM(Interface attribute) in an object expression`` () = @@ -295,7 +300,8 @@ consoleLogger.Log("Hello World") |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] |> withLangVersion80 |> compile - |> shouldSucceed + |> shouldFail + |> withSingleDiagnostic (Error 3860, Line 8, Col 11, Line 8, Col 18, "Object expressions cannot implement interfaces with static abstract members or declare static members.") [] let ``No error when implementing only instance members from a type(Interface attribute) in an object expression`` () = @@ -314,5 +320,5 @@ let consoleLogger = consoleLogger.Log("Hello World") """ |> withLangVersion80 - |> compile + |> compileExeAndRun |> shouldSucceed \ No newline at end of file