From b452c1e1617162debd969e4fb70adc799914672b Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Wed, 11 Jan 2023 19:52:30 +0100 Subject: [PATCH 1/2] Compiler error when declaring abstract members on static classes --- src/Compiler/Checking/CheckDeclarations.fs | 5 ++ src/Compiler/FSComp.txt | 3 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.de.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.es.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.fr.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.it.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.ja.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.ko.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.pl.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.ru.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.tr.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 ++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 ++ .../Language/StaticClassTests.fs | 60 +++++++++++++++++++ 16 files changed, 132 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index a24af31c851..3738e715a4f 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -1778,6 +1778,11 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial mBinds scopem mutRecNSInfo (env let isStaticClass = HasFSharpAttribute cenv.g cenv.g.attrib_SealedAttribute tcref.Attribs && HasFSharpAttribute cenv.g cenv.g.attrib_AbstractClassAttribute tcref.Attribs if isStaticClass && cenv.g.langVersion.SupportsFeature(LanguageFeature.ErrorReportingOnStaticClasses) then ReportErrorOnStaticClass synMembers + match tyconOpt with + | Some tycon -> + for slot in tycon.FSharpObjectModelTypeInfo.fsobjmodel_vslots do + errorR(Error(FSComp.SR.chkAbstractMembersDeclarationsOnStaticClasses(), slot.Range)) + | None -> () let envForDecls = // This allows to implement protected interface methods if it's a DIM. diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 4d3678ab389..985fc02ed8f 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1670,4 +1670,5 @@ featureEscapeBracesInFormattableString,"Escapes curly braces before calling Form 3553,chkAdditionalConstructorOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Additional constructor is not allowed." 3554,chkInstanceMemberOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Instance members are not allowed." 3555,chkInstanceLetBindingOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Instance let bindings are not allowed." -3556,chkImplementingInterfacesOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed." \ No newline at end of file +3556,chkImplementingInterfacesOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed." +3557,chkAbstractMembersDeclarationsOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed." \ 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 5eb2e5b7bcc..7ec35130e20 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -22,6 +22,11 @@ Soubor {0} má nerozpoznanou příponu. Zdrojové soubory musí mít příponu .fs, .fsi, .fsx nebo .fsscript. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 10c00c7582c..529f4121b05 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -22,6 +22,11 @@ Die Dateierweiterung von „{0}“ wurde nicht erkannt. Quelldateien müssen die Erweiterung .fs, .fsi, .fsx oder .fsscript haben + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 0713184b7ba..12fb78b6006 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -22,6 +22,11 @@ No se reconoce la extensión de archivo de '{0}'. Los archivos de código fuente deben tener las extensiones .fs, .fsi, .fsx o .fsscript + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index a30598f065a..174c8732c85 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -22,6 +22,11 @@ L'extension de fichier de '{0}' n'est pas reconnue. Les fichiers sources doivent avoir l'extension .fs, .fsi, .fsx, ou .fsscript. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 3c4dd9c2af5..8873e9b8f31 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -22,6 +22,11 @@ Estensione di file di '{0}' non riconosciuta. I file di origine devono avere estensione .fs, .fsi, .fsx or .fsscript + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index e70f882b05f..bed5086303b 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -22,6 +22,11 @@ '{0}' のファイル拡張子は認識されません。ソース ファイルの拡張子は .fs、.fsi、.fsx、または .fsscript にする必要があります。 + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 9f3d1ea97f0..a4278c5d566 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -22,6 +22,11 @@ '{0}'의 파일 확장명을 인식할 수 없습니다. 원본 파일의 확장명은 .fs, .fsi, .fsx 또는 .fsscript여야 합니다. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 46c2f6d411f..6659d0bbe8c 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -22,6 +22,11 @@ Rozszerzenie pliku "{0}" nie zostało rozpoznane. Pliki źródłowe muszą mieć rozszerzenie .fs, .fsi, .fsx lub .fsscript + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index e5328d7942b..d4a1168226c 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -22,6 +22,11 @@ A extensão do arquivo de '{0}' não foi reconhecida. Os arquivos de origem devem ter a extensão .fs, .fsi, .fsx or .fsscript + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index c5ccb275eb7..57943e732a6 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -22,6 +22,11 @@ Расширение файла "{0}" не распознано. Исходные файлы должны иметь расширения FS, FSI, FSX или FSSCRIPT + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 0ec42cbff6a..d9f946f53ba 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -22,6 +22,11 @@ '{0}' kaynak dosyasının dosya uzantısı tanınmadı. Kaynak dosyaların uzantısı .fs, .fsi, .fsx veya .fsscript olmalıdır. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index e08ac7bd264..e0afd6beda1 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -22,6 +22,11 @@ 无法识别“{0}”的文件扩展名。源文件必须具有扩展名 .fs、.fsi、.fsx 或 .fsscript + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 07dcde699f0..70a4804ac47 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -22,6 +22,11 @@ 無法辨識 '{0}' 的副檔名。來源檔案的副檔名必須是 .fs、.fsi、.fsx 或 .fsscript。 + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Abstract member declarations are not allowed. + + If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. If a type uses both [<Sealed>] and [<AbstractClass>] attributes, it means it is static. Additional constructor is not allowed. diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs index 6a8589f5bea..59e0656c1e1 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs @@ -420,4 +420,64 @@ type C = |> shouldFail |> withDiagnostics [ (Error 3556, Line 7, Col 5, Line 8, Col 29, "If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed.") + ] + + [] + let ``Sealed and AbstractClass on a type implicit constructor declaring abstract members in Lang 70`` () = + Fsx """ +[] +type T = + abstract A : int + abstract B : int with get, set + abstract C : i:int -> int + abstract D : i:int -> int + """ + |> withLangVersion70 + |> compile + |> shouldSucceed + + [] + let ``Sealed and AbstractClass on a type declaring abstract members in Lang 70`` () = + Fsx """ +[] +type T() = + abstract A : int + abstract B : int with get, set + abstract C : i:int -> int + abstract D : i:int -> int + """ + |> withLangVersion70 + |> compile + |> shouldSucceed + + [] + let ``Sealed and AbstractClass on a type with implicit constructor declaring abstract members in Lang preview`` () = + Fsx """ +[] +type T = + abstract C : i:int -> int + abstract D : i:int -> int + """ + |> withLangVersionPreview + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 3557, Line 4, Col 14, Line 4, Col 15, "If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed.") + (Error 3557, Line 5, Col 14, Line 5, Col 15, "If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed.") + ] + + [] + let ``Sealed and AbstractClass on a type declaring abstract members in Lang preview`` () = + Fsx """ +[] +type T() = + abstract C : i:int -> int + abstract D : i:int -> int + """ + |> withLangVersionPreview + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 3557, Line 4, Col 14, Line 4, Col 15, "If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed.") + (Error 3557, Line 5, Col 14, Line 5, Col 15, "If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed.") ] \ No newline at end of file From 552fe6c663657ed0f27112f59e45851ceda4043b Mon Sep 17 00:00:00 2001 From: Edgar Gonzalez Date: Thu, 12 Jan 2023 16:59:38 +0100 Subject: [PATCH 2/2] Compiler error only for inteface instance member --- src/Compiler/Checking/CheckDeclarations.fs | 8 +- .../Language/StaticClassTests.fs | 75 ++++++++++++++++++- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 3738e715a4f..1c4ecb97c33 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -1668,8 +1668,12 @@ let private ReportErrorOnStaticClass (synMembers: SynMemberDefn list) = errorR(Error(FSComp.SR.chkInstanceMemberOnStaticClasses(), m)) | SynMemberDefn.LetBindings(isStatic = false; range = range) -> errorR(Error(FSComp.SR.chkInstanceLetBindingOnStaticClasses(), range)) - | SynMemberDefn.Interface(range = range) -> - errorR(Error(FSComp.SR.chkImplementingInterfacesOnStaticClasses(), range)) + | SynMemberDefn.Interface(members= Some(synMemberDefs)) -> + for mem in synMemberDefs do + match mem with + | SynMemberDefn.Member(SynBinding(valData = SynValData(memberFlags = Some memberFlags)), m) when memberFlags.MemberKind = SynMemberKind.Member && memberFlags.IsInstance -> + errorR(Error(FSComp.SR.chkImplementingInterfacesOnStaticClasses(), m)) + | _ -> () | _ -> () /// Check and generalize the interface implementations, members, 'let' definitions in a mutually recursive group of definitions. diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs index 59e0656c1e1..dc9f8dc0747 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/StaticClassTests.fs @@ -401,7 +401,7 @@ type C() = |> compile |> shouldFail |> withDiagnostics [ - (Error 3556, Line 7, Col 5, Line 8, Col 29, "If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed.") + (Error 3556, Line 8, Col 9, Line 8, Col 29, "If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed.") ] [] @@ -419,7 +419,7 @@ type C = |> compile |> shouldFail |> withDiagnostics [ - (Error 3556, Line 7, Col 5, Line 8, Col 29, "If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed.") + (Error 3556, Line 8, Col 9, Line 8, Col 29, "If a type uses both [] and [] attributes, it means it is static. Implementing interfaces is not allowed.") ] [] @@ -480,4 +480,73 @@ type T() = |> withDiagnostics [ (Error 3557, Line 4, Col 14, Line 4, Col 15, "If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed.") (Error 3557, Line 5, Col 14, Line 5, Col 15, "If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed.") - ] \ No newline at end of file + ] + + #if !NETCOREAPP + [] + #else + [] + #endif + let ``Sealed and AbstractClass on a type implementing an interface with static abstract members in Lang 70`` () = + Fsx """ +[] +type InputRetriever<'T when 'T:>InputRetriever<'T>> = + static abstract Read: unit -> string + +[] +type ConsoleRetriever = + interface InputRetriever with + static member Read() = + stdout.WriteLine("Please enter a value and press enter") + stdin.ReadLine() + """ + |> withNoWarn 3535 + |> withLangVersion70 + |> compile + |> shouldSucceed + + #if !NETCOREAPP + [] + #else + [] + #endif + let ``Sealed and AbstractClass on a type implicit constructor implementing an interface with static abstract members in Lang preview`` () = + Fsx """ +[] +type InputRetriever<'T when 'T:>InputRetriever<'T>> = + static abstract Read: unit -> string + +[] +type ConsoleRetriever = + interface InputRetriever with + static member Read() = + stdout.WriteLine("Please enter a value and press enter") + stdin.ReadLine() + """ + |> withNoWarn 3535 + |> withLangVersionPreview + |> compile + |> shouldSucceed + + #if !NETCOREAPP + [] + #else + [] + #endif + let ``Sealed and AbstractClass on a type implementing an interface with static abstract members in Lang preview`` () = + Fsx """ +[] +type InputRetriever<'T when 'T:>InputRetriever<'T>> = + static abstract Read: unit -> string + +[] +type ConsoleRetriever() = + interface InputRetriever with + static member Read() = + stdout.WriteLine("Please enter a value and press enter") + stdin.ReadLine() + """ + |> withNoWarn 3535 + |> withLangVersionPreview + |> compile + |> shouldSucceed \ No newline at end of file