From ef57ea64e4cfc0c6a9d92aabbca3d6cc1ea6f004 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 29 Jan 2023 13:57:08 +0100 Subject: [PATCH 1/8] Warn when record update expression changes all fields --- src/Compiler/Checking/CheckExpressions.fs | 9 ++++++-- 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 ++++ .../Diagnostics/Records.fs | 23 +++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + 17 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 4c1c47f53b..532d98714e 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -6565,8 +6565,13 @@ and TcRecordConstruction (cenv: cenv) (overallTy: TType) env tpenv withExprInfoO let ns1 = NameSet.ofList (List.map fst fldsList) let ns2 = NameSet.ofList (List.map (fun x -> x.rfield_id.idText) fspecs) - if withExprInfoOpt.IsNone && not (Zset.subset ns2 ns1) then - error (MissingFields(Zset.elements (Zset.diff ns2 ns1), m)) + match withExprInfoOpt with + | None -> + if not (Zset.subset ns2 ns1) then + error(MissingFields(Zset.elements (Zset.diff ns2 ns1), m)) + | _ -> + if oldFldsList.IsEmpty then + warning(Error(FSComp.SR.tcCopyAndUpdateRecordChangesAllFields(fullDisplayTextOfTyconRef tcref), m)) if not (Zset.subset ns1 ns2) then error (Error(FSComp.SR.tcExtraneousFieldsGivenValues(), m)) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 46379fc0eb..06619bd4fe 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1672,4 +1672,5 @@ featureEscapeBracesInFormattableString,"Escapes curly braces before calling Form 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." 3557,chkAbstractMembersDeclarationsOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Abstract member declarations are not allowed." -3558,chkExplicitFieldsDeclarationsOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Explicit field declarations are not allowed." \ No newline at end of file +3558,chkExplicitFieldsDeclarationsOnStaticClasses,"If a type uses both [] and [] attributes, it means it is static. Explicit field declarations are not allowed." +3560,tcCopyAndUpdateRecordChangesAllFields,"This copy-and-update record expression changes all fields of record type '%s'. Consider using the record construction syntax instead." \ 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 be4e61a8fe..1226dda820 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -872,6 +872,11 @@ Atributy nejde použít pro rozšíření typů. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Syntaxe expr1[expr2] se používá pro indexování. Pokud chcete povolit indexování, zvažte možnost přidat anotaci typu, nebo pokud voláte funkci, přidejte mezeru, třeba expr1 [expr2]. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 5d662b8bf2..818d8a9fc1 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -872,6 +872,11 @@ Attribute können nicht auf Typerweiterungen angewendet werden. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Die Syntax "expr1[expr2]" wird für die Indizierung verwendet. Fügen Sie ggf. eine Typanmerkung hinzu, um die Indizierung zu aktivieren, oder fügen Sie beim Aufrufen einer Funktion ein Leerzeichen hinzu, z. B. "expr1 [expr2]". diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 1ddc22b847..88d5ab8580 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -872,6 +872,11 @@ Los atributos no se pueden aplicar a las extensiones de tipo. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. La sintaxis "expr1[expr2]" se usa para la indexación. Considere la posibilidad de agregar una anotación de tipo para habilitar la indexación, si se llama a una función, agregue un espacio, por ejemplo, "expr1 [expr2]". diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index a7b82e5117..1ba00503ae 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -872,6 +872,11 @@ Impossible d'appliquer des attributs aux extensions de type. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. La syntaxe « expr1[expr2] » est utilisée pour l’indexation. Envisagez d’ajouter une annotation de type pour activer l’indexation, ou si vous appelez une fonction, ajoutez un espace, par exemple « expr1 [expr2] ». diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index fcd590c3b3..4a1f56b932 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -872,6 +872,11 @@ Gli attributi non possono essere applicati a estensioni di tipo. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. La sintassi 'expr1[expr2]' viene usata per l'indicizzazione. Provare ad aggiungere un'annotazione di tipo per abilitare l'indicizzazione oppure se la chiamata a una funzione aggiunge uno spazio, ad esempio 'expr1 [expr2]'. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index b064cc8d2b..a0ebb10251 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -872,6 +872,11 @@ 属性を型拡張に適用することはできません。 + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 構文 'expr1[expr2]' はインデックス作成に使用されます。インデックスを有効にするために型の注釈を追加するか、関数を呼び出す場合には、'expr1 [expr2]' のようにスペースを入れます。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 41fced8e04..43696edd2c 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -872,6 +872,11 @@ 형식 확장에 특성을 적용할 수 없습니다. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 인덱싱에는 'expr1[expr2]' 구문이 사용됩니다. 인덱싱을 사용하도록 설정하기 위해 형식 주석을 추가하는 것을 고려하거나 함수를 호출하는 경우 공백을 추가하세요(예: 'expr1 [expr2]'). diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 764d818dcd..43bb9c6d7c 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -872,6 +872,11 @@ Atrybutów nie można stosować do rozszerzeń typu. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Do indeksowania używana jest składnia „expr1[expr2]”. Rozważ dodanie adnotacji typu, aby umożliwić indeksowanie, lub jeśli wywołujesz funkcję dodaj spację, np. „expr1 [expr2]”. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index da8982c32a..5dfd57ccab 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -872,6 +872,11 @@ Os atributos não podem ser aplicados às extensões de tipo. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. A sintaxe 'expr1[expr2]' é usada para indexação. Considere adicionar uma anotação de tipo para habilitar a indexação ou, se chamar uma função, adicione um espaço, por exemplo, 'expr1 [expr2]'. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 2982795500..8792d67580 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -872,6 +872,11 @@ Атрибуты не могут быть применены к расширениям типа. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Для индексирования используется синтаксис "expr1[expr2]". Рассмотрите возможность добавления аннотации типа для включения индексации или при вызове функции добавьте пробел, например "expr1 [expr2]". diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 3f3bb5dee6..116811e2bb 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -872,6 +872,11 @@ Öznitelikler tür uzantılarına uygulanamaz. + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. Söz dizimi “expr1[expr2]” dizin oluşturma için kullanılıyor. Dizin oluşturmayı etkinleştirmek için bir tür ek açıklama eklemeyi düşünün veya bir işlev çağırıyorsanız bir boşluk ekleyin, örn. “expr1 [expr2]”. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 3601169ca3..6ed5f81aef 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -872,6 +872,11 @@ 属性不可应用于类型扩展。 + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 语法“expr1[expr2]”用于索引。考虑添加类型批注来启用索引,或者在调用函数添加空格,例如“expr1 [expr2]”。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index b767cad878..b7f168333e 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -872,6 +872,11 @@ 屬性無法套用到類型延伸模組。 + + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + This copy-and-update record expression changes all fields of record type '{0}'. Consider using the record construction syntax instead. + + The syntax 'expr1[expr2]' is used for indexing. Consider adding a type annotation to enable indexing, or if calling a function add a space, e.g. 'expr1 [expr2]'. 語法 'expr1[expr2]' 已用於編製索引。請考慮新增類型註釋來啟用編製索引,或是呼叫函式並新增空格,例如 'expr1 [expr2]'。 diff --git a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs new file mode 100644 index 0000000000..e51d12eb57 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module FSharp.Compiler.ComponentTests.Diagnostics.Records + +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +[] +let ``Warning emitted when record update syntax changes all fields``() = + Fsx """ +module Records + +type R = { F1: int; F2: string } + +let updateOk r = { r with F1 = 1 } +let updateWarn r = { r with F1 = 1; F2 = "" } + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 3560, Line 7, Col 20, Line 7, Col 46, "This copy-and-update record expression changes all fields of record type 'Records.R'. Consider using the record construction syntax instead.") + ] \ 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 c244723eb7..f2e4de6576 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -205,6 +205,7 @@ + From f3bed6d6917c53f31d5fa644b7139a9262bd9c91 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 29 Jan 2023 16:21:19 +0100 Subject: [PATCH 2/8] Address new warning in FSharp.Core --- src/FSharp.Core/Linq.fs | 6 +++--- src/FSharp.Core/async.fs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FSharp.Core/Linq.fs b/src/FSharp.Core/Linq.fs index 040ccebfa9..bdca8e9bab 100644 --- a/src/FSharp.Core/Linq.fs +++ b/src/FSharp.Core/Linq.fs @@ -725,7 +725,7 @@ module LeafExpressionConverter = | Patterns.NewDelegate(delegateTy, vs, b) -> let vsP = List.map ConvVarToLinq vs - let env = {env with varEnv = List.foldBack2 (fun (v:Var) vP -> Map.add v (vP |> asExpr)) vs vsP env.varEnv } + let env = { varEnv = List.foldBack2 (fun (v:Var) vP -> Map.add v (vP |> asExpr)) vs vsP env.varEnv } let bodyP = ConvExprToLinqInContext env b Expression.Lambda(delegateTy, bodyP, vsP) |> asExpr @@ -768,7 +768,7 @@ module LeafExpressionConverter = | Patterns.Let (v, e, b) -> let vP = ConvVarToLinq v - let envinner = { env with varEnv = Map.add v (vP |> asExpr) env.varEnv } + let envinner = { varEnv = Map.add v (vP |> asExpr) env.varEnv } let bodyP = ConvExprToLinqInContext envinner b let eP = ConvExprToLinqInContext env e let ty = Expression.GetFuncType [| v.Type; b.Type |] @@ -777,7 +777,7 @@ module LeafExpressionConverter = | Patterns.Lambda(v, body) -> let vP = ConvVarToLinq v - let env = { env with varEnv = Map.add v (vP |> asExpr) env.varEnv } + let env = { varEnv = Map.add v (vP |> asExpr) env.varEnv } let bodyP = ConvExprToLinqInContext env body let lambdaTy, tyargs = if bodyP.Type = typeof then diff --git a/src/FSharp.Core/async.fs b/src/FSharp.Core/async.fs index e907040c94..2cfed9bc67 100644 --- a/src/FSharp.Core/async.fs +++ b/src/FSharp.Core/async.fs @@ -316,7 +316,7 @@ type AsyncActivation<'T>(contents: AsyncActivationContents<'T>) = /// Produce a new execution context for a composite async member ctxt.WithContinuations(cont, econt, ccont) = AsyncActivation<'T> - { contents with + { cont = cont aux = { ctxt.aux with From e7a9b07ed59bf82a6ba729e2b63458b4c445b6f8 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 29 Jan 2023 16:50:10 +0100 Subject: [PATCH 3/8] Address new warning in FSharp.Compiler.Service --- src/Compiler/TypedTree/TypedTreeOps.fs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index b87db718b3..17ce2d8e02 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -5983,14 +5983,14 @@ and remapUnionCases ctxt tmenv (x: TyconUnionData) = x.UnionCasesAsList |> List.map (remapUnionCase ctxt tmenv) |> Construct.MakeUnionCases and remapFsObjData ctxt tmenv x = - { x with - fsobjmodel_kind = - (match x.fsobjmodel_kind with - | TFSharpDelegate slotsig -> TFSharpDelegate (remapSlotSig (remapAttribs ctxt tmenv) tmenv slotsig) - | TFSharpClass | TFSharpInterface | TFSharpStruct | TFSharpEnum -> x.fsobjmodel_kind) - fsobjmodel_vslots = x.fsobjmodel_vslots |> List.map (remapValRef tmenv) - fsobjmodel_rfields = x.fsobjmodel_rfields |> remapRecdFields ctxt tmenv } - + { + fsobjmodel_kind = + match x.fsobjmodel_kind with + | TFSharpDelegate slotsig -> TFSharpDelegate (remapSlotSig (remapAttribs ctxt tmenv) tmenv slotsig) + | TFSharpClass | TFSharpInterface | TFSharpStruct | TFSharpEnum -> x.fsobjmodel_kind + fsobjmodel_vslots = x.fsobjmodel_vslots |> List.map (remapValRef tmenv) + fsobjmodel_rfields = x.fsobjmodel_rfields |> remapRecdFields ctxt tmenv + } and remapTyconRepr ctxt tmenv repr = match repr with From 44ea025964e7c505117e560768534a2b2adf3bb3 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 29 Jan 2023 16:56:35 +0100 Subject: [PATCH 4/8] Address new warning in FSharp.Test.Utilities --- tests/FSharp.Test.Utilities/Compiler.fs | 2 +- tests/FSharp.Test.Utilities/ProjectGeneration.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 8ea26ea602..5909c705e8 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -244,7 +244,7 @@ module rec Compiler = let private getWarnings diagnostics = diagnostics |> List.filter (fun e -> match e.Error with Warning _ -> true | _ -> false) let private adjustRange (range: Range) (adjust: int) : Range = - { range with + { StartLine = range.StartLine - adjust StartColumn = range.StartColumn + 1 EndLine = range.EndLine - adjust diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index c9b21c4e4f..4e2e482390 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -141,7 +141,7 @@ type SyntheticProject = ) |> Async.RunSynchronously - { baseOptions with + { ProjectFileName = this.ProjectFileName ProjectId = None SourceFiles = From 7f0b7fd805eb838f9bdaffef06b7aff500d80c54 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 29 Jan 2023 19:15:23 +0100 Subject: [PATCH 5/8] Disable warning by default --- src/Compiler/Driver/CompilerDiagnostics.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 4b78aa9b9f..09ad7b3b1f 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -380,6 +380,7 @@ type PhasedDiagnostic with | 3389 -> false // tcBuiltInImplicitConversionUsed - off by default | 3390 -> false // xmlDocBadlyFormed - off by default | 3395 -> false // tcImplicitConversionUsedForMethodArg - off by default + | 3560 -> false // tcCopyAndUpdateRecordChangesAllFields - off by default | _ -> (severity = FSharpDiagnosticSeverity.Info) || (severity = FSharpDiagnosticSeverity.Warning && level >= x.WarningLevel) From 41a36bd9fa02169fbf9556c2d30e6cae7b8dbc48 Mon Sep 17 00:00:00 2001 From: kerams Date: Sun, 29 Jan 2023 22:21:05 +0100 Subject: [PATCH 6/8] Guard the warning behind a language feature --- src/Compiler/Checking/CheckExpressions.fs | 2 +- src/Compiler/Driver/CompilerDiagnostics.fs | 1 - src/Compiler/FSComp.txt | 1 + src/Compiler/Facilities/LanguageFeatures.fs | 3 +++ src/Compiler/Facilities/LanguageFeatures.fsi | 1 + 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 +++++ tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs | 1 + 19 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 532d98714e..431cc277a9 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -6570,7 +6570,7 @@ and TcRecordConstruction (cenv: cenv) (overallTy: TType) env tpenv withExprInfoO if not (Zset.subset ns2 ns1) then error(MissingFields(Zset.elements (Zset.diff ns2 ns1), m)) | _ -> - if oldFldsList.IsEmpty then + if oldFldsList.IsEmpty && g.langVersion.SupportsFeature LanguageFeature.WarningWhenCopyAndUpdateRecordChangesAllFields then warning(Error(FSComp.SR.tcCopyAndUpdateRecordChangesAllFields(fullDisplayTextOfTyconRef tcref), m)) if not (Zset.subset ns1 ns2) then diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index 09ad7b3b1f..4b78aa9b9f 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -380,7 +380,6 @@ type PhasedDiagnostic with | 3389 -> false // tcBuiltInImplicitConversionUsed - off by default | 3390 -> false // xmlDocBadlyFormed - off by default | 3395 -> false // tcImplicitConversionUsedForMethodArg - off by default - | 3560 -> false // tcCopyAndUpdateRecordChangesAllFields - off by default | _ -> (severity = FSharpDiagnosticSeverity.Info) || (severity = FSharpDiagnosticSeverity.Warning && level >= x.WarningLevel) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 06619bd4fe..3b93a97945 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1561,6 +1561,7 @@ featureErrorForNonVirtualMembersOverrides,"Raises errors for non-virtual members featureWarningWhenInliningMethodImplNoInlineMarkedFunction,"Raises warnings when 'let inline ... =' is used together with [] attribute. Function is not getting inlined." featureArithmeticInLiterals,"Allow arithmetic and logical operations in literals" featureErrorReportingOnStaticClasses,"Error reporting on static classes" +featureWarningWhenCopyAndUpdateRecordChangesAllFields,"Raises warnings when an copy-and-update record expression changes all fields of a record." 3353,fsiInvalidDirective,"Invalid directive '#%s %s'" 3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index e7654bea42..424e949eed 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -61,6 +61,7 @@ type LanguageFeature = | EscapeDotnetFormattableStrings | ArithmeticInLiterals | ErrorReportingOnStaticClasses + | WarningWhenCopyAndUpdateRecordChangesAllFields /// LanguageVersion management type LanguageVersion(versionText) = @@ -138,6 +139,7 @@ type LanguageVersion(versionText) = LanguageFeature.EscapeDotnetFormattableStrings, previewVersion LanguageFeature.ArithmeticInLiterals, previewVersion LanguageFeature.ErrorReportingOnStaticClasses, previewVersion + LanguageFeature.WarningWhenCopyAndUpdateRecordChangesAllFields, previewVersion ] @@ -252,6 +254,7 @@ type LanguageVersion(versionText) = | LanguageFeature.EscapeDotnetFormattableStrings -> FSComp.SR.featureEscapeBracesInFormattableString () | LanguageFeature.ArithmeticInLiterals -> FSComp.SR.featureArithmeticInLiterals () | LanguageFeature.ErrorReportingOnStaticClasses -> FSComp.SR.featureErrorReportingOnStaticClasses () + | LanguageFeature.WarningWhenCopyAndUpdateRecordChangesAllFields -> FSComp.SR.featureWarningWhenCopyAndUpdateRecordChangesAllFields () /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index d070a8b4e3..714639147b 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -51,6 +51,7 @@ type LanguageFeature = | EscapeDotnetFormattableStrings | ArithmeticInLiterals | ErrorReportingOnStaticClasses + | WarningWhenCopyAndUpdateRecordChangesAllFields /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 1226dda820..a84daa2f7c 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -382,6 +382,11 @@ reprezentace struktury aktivních vzorů + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Vyvolá upozornění, když se použije „let inline ... =“ společně s atributem [<MethodImpl(MethodImplOptions.NoInlining)>]. Funkce není vkládána. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 818d8a9fc1..994c9dd8fc 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -382,6 +382,11 @@ Strukturdarstellung für aktive Muster + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Löst Warnungen aus, wenn „let inline ... =“ zusammen mit dem Attribut [<MethodImpl(MethodImplOptions.NoInlining)>] verwendet wird. Die Funktion wird nicht inline gesetzt. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 88d5ab8580..8ce6500b04 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -382,6 +382,11 @@ representación de struct para modelos activos + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Genera advertencias cuando se usa "let inline ... =" junto con el atributo [<MethodImpl(MethodImplOptions.NoInlining)>]. La función no se está insertando. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 1ba00503ae..b2f47de7f5 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -382,6 +382,11 @@ représentation de structure pour les modèles actifs + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Génère des avertissements lorsque « let inline ... = » est utilisé avec l’attribut [<MethodImpl(MethodImplOptions.NoInlining)>]. La fonction n’est pas inlined. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 4a1f56b932..181b7c2af0 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -382,6 +382,11 @@ rappresentazione struct per criteri attivi + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Genera avvisi quando 'let inline ... =' viene usato insieme all'attributo [<MethodImpl(MethodImplOptions.NoInlining)>]. La funzione non viene resa inline. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index a0ebb10251..1d0befd9d0 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -382,6 +382,11 @@ アクティブなパターンの構造体表現 + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. 'let inline ... =' が [<MethodImpl(MethodImplOptions.NoInlining)>] 属性と一緒に使用されるときに警告を生成します。関数はインライン化されていません。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 43696edd2c..f0994b5ce0 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -382,6 +382,11 @@ 활성 패턴에 대한 구조체 표현 + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. 'let inline ... ='을(를) [<MethodImpl(MethodImplOptions.NoInlining)>] 특성과 함께 사용하는 경우 경고를 발생합니다. 함수가 인라인되지 않습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 43bb9c6d7c..9c284a6eec 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -382,6 +382,11 @@ reprezentacja struktury aktywnych wzorców + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Zgłasza ostrzeżenia, gdy element „let inline ... =” jest używany razem z atrybutem [<MethodImpl(MethodImplOptions.NoInlining)>]. Funkcja nie jest wstawiana. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 5dfd57ccab..487648e59c 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -382,6 +382,11 @@ representação estrutural para padrões ativos + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Gera avisos quando 'let inline ... =' é usado junto com o atributo [<MethodImpl(MethodImplOptions.NoInlining)>]. A função não está sendo embutida. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 8792d67580..59282204b6 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -382,6 +382,11 @@ представление структуры для активных шаблонов + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. Выдает предупреждения, когда используется параметр "let inline ... =" вместе с атрибутом [<MethodImpl(MethodImplOptions.NoInlining)>]. Функция не встраивается. diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 116811e2bb..2a9bb02dcf 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -382,6 +382,11 @@ etkin desenler için yapı gösterimi + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. [<MethodImpl(MethodImplOptions.NoInlining)>] özniteliği ile birlikte 'let inline ... =' kullanıldığında uyarı verir. İşlev satır içine alınmıyor. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 6ed5f81aef..e5fb4f3931 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -382,6 +382,11 @@ 活动模式的结构表示形式 + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. 当 "let inline ... =" 与 [<MethodImpl(MethodImplOptions.NoInlining)>] 属性一起使用时引发警告。函数未内联。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index b7f168333e..8f3a2a6c7d 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -382,6 +382,11 @@ 現用模式的結構表示法 + + Raises warnings when an copy-and-update record expression changes all fields of a record. + Raises warnings when an copy-and-update record expression changes all fields of a record. + + Raises warnings when 'let inline ... =' is used together with [<MethodImpl(MethodImplOptions.NoInlining)>] attribute. Function is not getting inlined. 當 'let inline ... =' 與 [<MethodImpl(MethodImplOptions.NoInlining)>] 屬性一起使用時引發警告。函數未內嵌。 diff --git a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs index e51d12eb57..0f0e82cf4a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs +++ b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs @@ -16,6 +16,7 @@ type R = { F1: int; F2: string } let updateOk r = { r with F1 = 1 } let updateWarn r = { r with F1 = 1; F2 = "" } """ + |> withLangVersionPreview |> typecheck |> shouldFail |> withDiagnostics [ From 0649669b212d53bf0b354c8a8ff209c98c2545b0 Mon Sep 17 00:00:00 2001 From: kerams Date: Tue, 31 Jan 2023 17:39:44 +0100 Subject: [PATCH 7/8] Add DiagnosticEnabledWithLanguageFeature --- src/Compiler/Checking/CheckExpressions.fs | 5 ++-- src/Compiler/Driver/CompilerDiagnostics.fs | 13 ++++++-- src/Compiler/Facilities/DiagnosticsLogger.fs | 6 ++++ src/Compiler/Facilities/DiagnosticsLogger.fsi | 6 ++++ .../Diagnostics/Records.fs | 30 +++++++++++++++++++ 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 431cc277a9..332cea0987 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -6570,8 +6570,9 @@ and TcRecordConstruction (cenv: cenv) (overallTy: TType) env tpenv withExprInfoO if not (Zset.subset ns2 ns1) then error(MissingFields(Zset.elements (Zset.diff ns2 ns1), m)) | _ -> - if oldFldsList.IsEmpty && g.langVersion.SupportsFeature LanguageFeature.WarningWhenCopyAndUpdateRecordChangesAllFields then - warning(Error(FSComp.SR.tcCopyAndUpdateRecordChangesAllFields(fullDisplayTextOfTyconRef tcref), m)) + if oldFldsList.IsEmpty then + let enabledByLangFeature = g.langVersion.SupportsFeature LanguageFeature.WarningWhenCopyAndUpdateRecordChangesAllFields + warning(ErrorEnabledWithLanguageFeature(FSComp.SR.tcCopyAndUpdateRecordChangesAllFields(fullDisplayTextOfTyconRef tcref), m, enabledByLangFeature)) if not (Zset.subset ns1 ns2) then error (Error(FSComp.SR.tcExtraneousFieldsGivenValues(), m)) diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index c0f373553e..f57b44c471 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -128,6 +128,7 @@ type Exception with | LetRecEvaluatedOutOfOrder (_, _, _, m) | DiagnosticWithText (_, _, m) | DiagnosticWithSuggestions (_, _, m, _, _) + | DiagnosticEnabledWithLanguageFeature (_, _, m, _) | SyntaxError (_, m) | InternalError (_, m) | InterfaceNotRevealed (_, _, m) @@ -330,6 +331,7 @@ type Exception with | WrappedError (e, _) -> e.DiagnosticNumber | DiagnosticWithText (n, _, _) -> n | DiagnosticWithSuggestions (n, _, _, _, _) -> n + | DiagnosticEnabledWithLanguageFeature (n, _, _, _) -> n | Failure _ -> 192 | IllegalFileNameChar (fileName, invalidChar) -> fst (FSComp.SR.buildUnexpectedFileNameCharacter (fileName, string invalidChar)) #if !NO_TYPEPROVIDERS @@ -353,6 +355,7 @@ type PhasedDiagnostic with | DefensiveCopyWarning _ -> 5 | DiagnosticWithText (n, _, _) + | DiagnosticEnabledWithLanguageFeature (n, _, _, _) | DiagnosticWithSuggestions (n, _, _, _, _) -> // 1178, tcNoComparisonNeeded1, "The struct, record or union type '%s' is not structurally comparable because the type parameter %s does not satisfy the 'comparison' constraint..." // 1178, tcNoComparisonNeeded2, "The struct, record or union type '%s' is not structurally comparable because the type '%s' does not satisfy the 'comparison' constraint...." @@ -382,8 +385,11 @@ type PhasedDiagnostic with | 3395 -> false // tcImplicitConversionUsedForMethodArg - off by default | 3559 -> false // typrelNeverRefinedAwayFromTop - off by default | _ -> - (severity = FSharpDiagnosticSeverity.Info) - || (severity = FSharpDiagnosticSeverity.Warning && level >= x.WarningLevel) + match x.Exception with + | DiagnosticEnabledWithLanguageFeature (_, _, _, enabled) -> enabled + | _ -> + (severity = FSharpDiagnosticSeverity.Info) + || (severity = FSharpDiagnosticSeverity.Warning && level >= x.WarningLevel) /// Indicates if a diagnostic should be reported as an informational member x.ReportAsInfo(options, severity) = @@ -1655,7 +1661,8 @@ type Exception with os.AppendString(NonUniqueInferredAbstractSlot4E().Format) - | DiagnosticWithText (_, s, _) -> os.AppendString s + | DiagnosticWithText (_, s, _) + | DiagnosticEnabledWithLanguageFeature (_, s, _, _) -> os.AppendString s | DiagnosticWithSuggestions (_, s, _, idText, suggestionF) -> os.AppendString(ConvertValLogicalNameToDisplayNameCore s) diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fs b/src/Compiler/Facilities/DiagnosticsLogger.fs index af937a2815..83f59e5216 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fs +++ b/src/Compiler/Facilities/DiagnosticsLogger.fs @@ -113,6 +113,9 @@ exception DiagnosticWithSuggestions of number: int * message: string * range: ra | DiagnosticWithSuggestions (_, msg, _, _, _) -> msg | _ -> "impossible" +/// A diagnostic that is raised when enabled manually, or by default with a language feature +exception DiagnosticEnabledWithLanguageFeature of number: int * message: string * range: range * enabledByLangFeature: bool + /// The F# compiler code currently uses 'Error(...)' in many places to create /// an DiagnosticWithText as an exception even if it's a warning. /// @@ -126,6 +129,9 @@ let Error ((n, text), m) = DiagnosticWithText(n, text, m) let ErrorWithSuggestions ((n, message), m, id, suggestions) = DiagnosticWithSuggestions(n, message, m, id, suggestions) +let ErrorEnabledWithLanguageFeature ((n, message), m, enabledByLangFeature) = + DiagnosticEnabledWithLanguageFeature (n, message, m, enabledByLangFeature) + let inline protectAssemblyExploration dflt f = try f () diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fsi b/src/Compiler/Facilities/DiagnosticsLogger.fsi index 0ac4c90583..05f2de148c 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fsi +++ b/src/Compiler/Facilities/DiagnosticsLogger.fsi @@ -44,6 +44,9 @@ val StopProcessing<'T> : exn /// Represents a diagnostic exeption whose text comes via SR.* exception DiagnosticWithText of number: int * message: string * range: range +/// A diagnostic that is raised when enabled manually, or by default with a language feature +exception DiagnosticEnabledWithLanguageFeature of number: int * message: string * range: range * enabledByLangFeature: bool + /// Creates a diagnostic exeption whose text comes via SR.* val Error: (int * string) * range -> exn @@ -77,6 +80,9 @@ exception DiagnosticWithSuggestions of /// Creates a DiagnosticWithSuggestions whose text comes via SR.* val ErrorWithSuggestions: (int * string) * range * string * Suggestions -> exn +/// Creates a DiagnosticEnabledWithLanguageFeature whose text comes via SR.* +val ErrorEnabledWithLanguageFeature: (int * string) * range * bool -> exn + val inline protectAssemblyExploration: dflt: 'T -> f: (unit -> 'T) -> 'T val inline protectAssemblyExplorationF: dflt: (string * string -> 'T) -> f: (unit -> 'T) -> 'T diff --git a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs index 0f0e82cf4a..094345b1ae 100644 --- a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs +++ b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs @@ -21,4 +21,34 @@ let updateWarn r = { r with F1 = 1; F2 = "" } |> shouldFail |> withDiagnostics [ (Warning 3560, Line 7, Col 20, Line 7, Col 46, "This copy-and-update record expression changes all fields of record type 'Records.R'. Consider using the record construction syntax instead.") + ] + +[] +let ``Warning not emitted when record update syntax changes all fields in lang70``() = + Fsx """ +module Records + +type R = { F1: int; F2: string } + +let updateWarn r = { r with F1 = 1; F2 = "" } + """ + |> withLangVersion70 + |> typecheck + |> shouldSucceed + +[] +let ``Warning emitted when record update syntax changes all fields when enabled manually in lang70``() = + Fsx """ +module Records + +type R = { F1: int; F2: string } + +let updateWarn r = { r with F1 = 1; F2 = "" } + """ + |> withLangVersion70 + |> withOptions ["--warnon:FS3560"] + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 3560, Line 6, Col 20, Line 6, Col 46, "This copy-and-update record expression changes all fields of record type 'Records.R'. Consider using the record construction syntax instead.") ] \ No newline at end of file From f844bf0ac75c2c91c02719adf0adc89904c3d852 Mon Sep 17 00:00:00 2001 From: kerams Date: Tue, 31 Jan 2023 17:49:33 +0100 Subject: [PATCH 8/8] Format, add nowarn test --- src/Compiler/Facilities/DiagnosticsLogger.fsi | 6 +++++- .../Diagnostics/Records.fs | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fsi b/src/Compiler/Facilities/DiagnosticsLogger.fsi index 05f2de148c..8357c00332 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fsi +++ b/src/Compiler/Facilities/DiagnosticsLogger.fsi @@ -45,7 +45,11 @@ val StopProcessing<'T> : exn exception DiagnosticWithText of number: int * message: string * range: range /// A diagnostic that is raised when enabled manually, or by default with a language feature -exception DiagnosticEnabledWithLanguageFeature of number: int * message: string * range: range * enabledByLangFeature: bool +exception DiagnosticEnabledWithLanguageFeature of + number: int * + message: string * + range: range * + enabledByLangFeature: bool /// Creates a diagnostic exeption whose text comes via SR.* val Error: (int * string) * range -> exn diff --git a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs index 094345b1ae..e5640db0f0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs +++ b/tests/FSharp.Compiler.ComponentTests/Diagnostics/Records.fs @@ -7,7 +7,7 @@ open FSharp.Test open FSharp.Test.Compiler [] -let ``Warning emitted when record update syntax changes all fields``() = +let ``Warning emitted when record update syntax changes all fields in lang preview``() = Fsx """ module Records @@ -36,6 +36,20 @@ let updateWarn r = { r with F1 = 1; F2 = "" } |> typecheck |> shouldSucceed +[] +let ``Warning not emitted when record update syntax changes all fields when disabled manually in lang preview``() = + Fsx """ +module Records + +type R = { F1: int; F2: string } + +let updateWarn r = { r with F1 = 1; F2 = "" } + """ + |> withLangVersionPreview + |> withOptions ["--nowarn:3560"] + |> typecheck + |> shouldSucceed + [] let ``Warning emitted when record update syntax changes all fields when enabled manually in lang70``() = Fsx """