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/Checking/MethodOverrides.fs b/src/Compiler/Checking/MethodOverrides.fs index f467dc8db25..9593ff9bb02 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 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/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 new file mode 100644 index 00000000000..f45e1bf1f45 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Expressions/ObjectExpressions/ObjectExpressions.fs @@ -0,0 +1,324 @@ +// 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 cannot 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 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 + +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 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") + ] + + [] + 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 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.") + ] + + [] + 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 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.") + ] + + [] + 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 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."); + ] + + [] + 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 + |> 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`` () = + 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 + |> 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`` () = + 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 + |> compileExeAndRun + |> 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 0685988d23c..7a5b9991113 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,164 +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 - |> 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 ...'.") - ] - - [] - 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 - |> 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 ...'.") - ] - - [] - 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`` () = @@ -1298,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 diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 50d81f50ee7..1c835b603da 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -78,6 +78,7 @@ +