diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md index 7ef8842b72c..b24a17b85fb 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md @@ -1,5 +1,6 @@ ### Fixed +* Static abstract method on classes no longer yields internal error. ([Issue #17044](https://github.com/dotnet/fsharp/issues/17044), [PR #17055](https://github.com/dotnet/fsharp/pull/17055)) * 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), [PR #17048](https://github.com/dotnet/fsharp/pull/17048)) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index f1037f7f1bb..30f773f7478 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -3608,6 +3608,20 @@ module EstablishTypeDefinitionCores = elif not (isClassTy g ty) then errorR(Error(FSComp.SR.tcCannotInheritFromInterfaceType(), m))) + let abstractSlots = + [ for synValSig, memberFlags in slotsigs do + + let (SynValSig(range=m)) = synValSig + + CheckMemberFlags None NewSlotsOK OverridesOK memberFlags m + + let slots = fst (TcAndPublishValSpec (cenv, envinner, containerInfo, ModuleOrMemberBinding, Some memberFlags, tpenv, synValSig)) + // Multiple slots may be returned, e.g. for + // abstract P: int with get, set + + for slot in slots do + yield mkLocalValRef slot ] + let kind = match kind with | SynTypeDefnKind.Struct -> @@ -3632,6 +3646,9 @@ module EstablishTypeDefinitionCores = noCLIMutableAttributeCheck() structLayoutAttributeCheck(not isIncrClass) allowNullLiteralAttributeCheck() + for slot in abstractSlots do + if not slot.IsInstanceMember then + errorR(Error(FSComp.SR.chkStaticAbstractMembersOnClasses(), slot.Range)) TFSharpClass | SynTypeDefnKind.Delegate (ty, arity) -> noCLIMutableAttributeCheck() @@ -3666,21 +3683,7 @@ module EstablishTypeDefinitionCores = | (_, m, baseIdOpt) :: _ -> match baseIdOpt with | None -> Some(ident("base", m)) - | Some id -> Some id - - let abstractSlots = - [ for synValSig, memberFlags in slotsigs do - - let (SynValSig(range=m)) = synValSig - - CheckMemberFlags None NewSlotsOK OverridesOK memberFlags m - - let slots = fst (TcAndPublishValSpec (cenv, envinner, containerInfo, ModuleOrMemberBinding, Some memberFlags, tpenv, synValSig)) - // Multiple slots may be returned, e.g. for - // abstract P: int with get, set - - for slot in slots do - yield mkLocalValRef slot ] + | Some id -> Some id let baseValOpt = MakeAndPublishBaseVal cenv envinner baseIdOpt (superOfTycon g tycon) let safeInitInfo = ComputeInstanceSafeInitInfo cenv envinner thisTyconRef.Range thisTy @@ -4453,7 +4456,7 @@ module TcDeclarations = let slotsigs = members |> List.choose (function SynMemberDefn.AbstractSlot (slotSig = x; flags = y) -> Some(x, y) | _ -> None) - let members,_vals_Inherits_Abstractslots = SplitAutoProps members + let members, _vals_Inherits_Abstractslots = SplitAutoProps members let isConcrete = members |> List.exists (function diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index e5cabbdc7e3..d7dfe371f3e 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1746,4 +1746,5 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [] di 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" -3866,chkStaticAbstractInterfaceMembers,"A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.%s)." \ No newline at end of file +3866,chkStaticAbstractInterfaceMembers,"A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.%s)." +3867,chkStaticAbstractMembersOnClasses,"Classes cannot contain static abstract 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 a7f9808f488..1e331ca0c1e 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Objektové výrazy nemohou implementovat rozhraní se statickými abstraktními členy ani deklarovat statické členy. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 534e047744f..cb5bb611c16 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Objektausdrücke können keine Schnittstellen mit statischen abstrakten Membern implementieren oder statische Member deklarieren. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 5d2517d1ca9..5a5520af8d0 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Las expresiones de objeto no pueden implementar interfaces con miembros abstractos estáticos ni declarar miembros estáticos. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index f5c4358314a..95f24fd7db2 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Les expressions d’objet ne peuvent pas implémenter des interfaces avec des membres abstraits statiques ou déclarer des membres statiques. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 350f2decb87..a4468df7f8e 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Le espressioni di oggetto non possono implementare interfacce con membri astratti statici o dichiarare membri statici. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 376d3d8d592..358cf700cf0 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract 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 f4a42405fcb..5784d4264e1 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract 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 f081661bf4e..f2858d49504 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Wyrażenia obiektów nie mogą implementować interfejsów ze statycznymi abstrakcyjnymi elementami członkowskimi ani deklarować statycznych elementów członkowskich. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index b17c0b76d24..cdff3ed5b34 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Expressões de objeto não podem implementar interfaces com membros abstratos estáticos ou declarar membros estáticos. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 7f83d96d646..9d1790e8dc9 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract 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 f74a800f285..b8bdd5e9cc6 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. Nesne ifadeleri, statik soyut üyeler içeren arabirimleri uygulayamaz veya statik üyeleri bildiremez. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 19dae40d40a..f06487e86bd 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract 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 4f332483292..f80470220b3 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -127,6 +127,11 @@ A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.{0}). + + Classes cannot contain static abstract members. + Classes cannot contain static abstract members. + + Object expressions cannot implement interfaces with static abstract members or declare static members. 物件運算式無法實作具有靜態抽象成員的介面或宣告靜態成員。 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 48c54e2c11e..3e971a054b0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -1241,4 +1241,31 @@ printf "%A" res""" (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).") - ] \ No newline at end of file + ] + + [] + let ``Error message that explicitly disallows static abstract methods in abstract classes.`` () = + Fsx """ +[] +type A () = + static abstract M : unit -> unit + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3867, Line 4, Col 21, Line 4, Col 22, "Classes cannot contain static abstract members.") + ] + + [] + let ``Error message that explicitly disallows static abstract methods in classes.`` () = + Fsx """ +type A () = + static abstract M : unit -> unit + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 3867, Line 3, Col 21, Line 3, Col 22, "Classes cannot contain static abstract members.") + ]