未验证 提交 1874b39d 编写于 作者: A Adam Boniecki 提交者: GitHub

Fix anon records duplicate fields (#13142)

* Add unit test for duplicate fields

Related issue: https://github.com/dotnet/fsharp/issues/11743

* Add new error code and message

* Add a fix in TcAnonRecdExpr

* Add another unit test - Update and copy syntax

* Change error message to include field id

* Add unit test for anon record type annotation

* Add check for duplicate labels in type annotations

* Improve error messages

Also switch from errorR to error in SynType case (SynExpr already used
error)
Co-authored-by: NAdam <me@example.com>
上级 4a7c9234
......@@ -4654,6 +4654,12 @@ and TcAnonRecdType cenv newOk checkConstraints occ env tpenv isStruct args m =
let unsortedFieldIds = args |> List.map fst |> List.toArray
let anonInfo = AnonRecdTypeInfo.Create(cenv.thisCcu, tupInfo, unsortedFieldIds)
// Check for duplicate field IDs
unsortedFieldIds
|> Array.countBy (fun fieldId -> fieldId.idText)
|> Array.iter (fun (idText, count) ->
if count > 1 then error (Error (FSComp.SR.tcAnonRecdTypeDuplicateFieldId(idText), m)))
// Sort into canonical order
let sortedFieldTys, sortedCheckedArgTys = List.zip args argsR |> List.indexed |> List.sortBy (fun (i,_) -> unsortedFieldIds[i].idText) |> List.map snd |> List.unzip
......@@ -7455,6 +7461,12 @@ and TcRecdExpr cenv (overallTy: TType) env tpenv (inherits, withExprOpt, synRecd
// Check '{| .... |}'
and TcAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, optOrigSynExpr, unsortedFieldIdsAndSynExprsGiven, mWholeExpr) =
// Check for duplicate field IDs
unsortedFieldIdsAndSynExprsGiven
|> List.countBy (fun (fId, _, _) -> fId.idText)
|> List.iter (fun (label, count) ->
if count > 1 then error (Error (FSComp.SR.tcAnonRecdDuplicateFieldId(label), mWholeExpr)))
match optOrigSynExpr with
| None ->
TcNewAnonRecdExpr cenv overallTy env tpenv (isStruct, unsortedFieldIdsAndSynExprsGiven, mWholeExpr)
......
......@@ -1642,3 +1642,5 @@ reprStateMachineInvalidForm,"The state machine has an unexpected form"
3519,tcInlineIfLambdaUsedOnNonInlineFunctionOrMethod,"The 'InlineIfLambda' attribute may only be used on parameters of inlined functions of methods whose type is a function or F# delegate type."
3520,invalidXmlDocPosition,"XML comment is not placed on a valid language element."
3521,tcInvalidMemberDeclNameMissingOrHasParen,"Invalid member declaration. The name of the member is missing or has parentheses."
3522,tcAnonRecdDuplicateFieldId,"The field '%s' appears multiple times in this record expression."
3523,tcAnonRecdTypeDuplicateFieldId,"The field '%s' appears multiple times in this anonymous record type."
\ No newline at end of file
......@@ -617,6 +617,11 @@
<target state="translated">Tato funkce se v této verzi jazyka F# nepodporuje. Abyste mohli tuto funkci používat, možná bude nutné přidat /langversion:preview.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Toto je nesprávný anonymní záznam. Měl by mít pole {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Neplatná deklarace typu anonymního záznamu</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Atributy nejde použít pro rozšíření typů.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Dieses Feature wird in dieser Version von F# nicht unterstützt. Möglicherweise müssen Sie "/langversion:preview" hinzufügen, um dieses Feature zu verwenden.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Dies ist der falsche anonyme Datensatz. Er muss folgende Felder umfassen: {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Ungültige Deklaration für anonymen Datensatztyp.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Attribute können nicht auf Typerweiterungen angewendet werden.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Esta versión de F# no admite esta característica. Es posible que tenga que agregar /langversion:preview para usarla.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Este es un registro anónimo incorrecto. Debe tener los campos {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Declaración de tipo de registro anónimo no válido.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Los atributos no se pueden aplicar a las extensiones de tipo.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Cette fonctionnalité n'est pas prise en charge dans cette version de F#. Vous devrez peut-être ajouter /langversion:preview pour pouvoir utiliser cette fonctionnalité.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Il s'agit de l'enregistrement anonyme incorrect. Il doit contenir les champs {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Déclaration de type d'enregistrement anonyme non valide.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Impossible d'appliquer des attributs aux extensions de type.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Questa funzionalità non è supportata in questa versione di F#. Per usare questa funzionalità, potrebbe essere necessario aggiungere /langversion:preview.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Si tratta del record anonimo errato. Deve includere i campi {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">La dichiarazione di tipo Record anonimo non è valida.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Gli attributi non possono essere applicati a estensioni di tipo.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">この機能は、このバージョンの F# ではサポートされていません。この機能を使用するには、/langversion:preview の追加が必要な場合があります。</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">この匿名レコードは正しくありません。フィールド {0} を含んでいる必要があります。</target>
......@@ -637,6 +642,11 @@
<target state="translated">匿名レコードの型宣言が無効です。</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">属性を型拡張に適用することはできません。</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">이 기능은 이 F# 버전에서 지원되지 않습니다. 이 기능을 사용하기 위해 /langversion:preview를 추가해야 할 수도 있습니다.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">잘못된 익명 레코드입니다. {0} 필드가 있어야 합니다.</target>
......@@ -637,6 +642,11 @@
<target state="translated">익명 레코드 형식 선언이 잘못되었습니다.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">형식 확장에 특성을 적용할 수 없습니다.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Ta funkcja nie jest obsługiwana w tej wersji języka F#. Aby korzystać z tej funkcji, może być konieczne dodanie parametru /langversion:preview.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">To jest nieprawidłowy rekord anonimowy. Powinien zawierać pola {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Nieprawidłowa deklaracja typu rekordu anonimowego.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Atrybutów nie można stosować do rozszerzeń typu.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Este recurso não tem suporte nesta versão do F#. Talvez seja necessário adicionar /langversion:preview para usar este recurso.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Este é o registro anônimo errado. Ele deve ter os campos {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Declaração inválida de tipo de Registro Anônimo.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Os atributos não podem ser aplicados às extensões de tipo.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Эта функция не поддерживается в данной версии F#. Возможно, потребуется добавить/langversion:preview, чтобы использовать эту функцию.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Неправильная анонимная запись. Она должна содержать поля {0}.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Недопустимое объявление типа анонимной записи.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Атрибуты не могут быть применены к расширениям типа.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">Bu özellik, bu F# sürümünde desteklenmiyor. Bu özelliği kullanabilmeniz için /langversion:preview eklemeniz gerekebilir.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">Bu anonim kayıt yanlış. Kayıt, {0} alanlarını içermelidir.</target>
......@@ -637,6 +642,11 @@
<target state="translated">Anonim Kayıt türü bildirimi geçersiz.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">Öznitelikler tür uzantılarına uygulanamaz.</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">此版本的 F# 不支持此功能。你可能需要添加 /langversion:preview 才可使用此功能。</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">此匿名记录不正确。它应具有字段 {0}。</target>
......@@ -637,6 +642,11 @@
<target state="translated">匿名记录类型声明无效。</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">属性不可应用于类型扩展。</target>
......
......@@ -617,6 +617,11 @@
<target state="translated">此版本的 F# 不支援此功能。您可能需要新增 /langversion:preview 才能使用此功能。</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdDuplicateFieldId">
<source>The field '{0}' appears multiple times in this record expression.</source>
<target state="new">The field '{0}' appears multiple times in this record expression.</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdFieldNameDifferent">
<source>This is the wrong anonymous record. It should have the fields {0}.</source>
<target state="translated">此為錯誤的匿名記錄。其應有欄位 {0}。</target>
......@@ -637,6 +642,11 @@
<target state="translated">匿名記錄型別宣告無效。</target>
<note />
</trans-unit>
<trans-unit id="tcAnonRecdTypeDuplicateFieldId">
<source>The field '{0}' appears multiple times in this anonymous record type.</source>
<target state="new">The field '{0}' appears multiple times in this anonymous record type.</target>
<note />
</trans-unit>
<trans-unit id="tcAugmentationsCannotHaveAttributes">
<source>Attributes cannot be applied to type extensions.</source>
<target state="translated">屬性無法套用到類型延伸模組。</target>
......
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
namespace FSharp.Compiler.ComponentTests.Conformance
open Xunit
open FSharp.Test
open FSharp.Test.Compiler
module AnonymousRecord =
[<Fact>]
let ``Anonymous Records with duplicate labels`` () =
FSharp """
namespace FSharpTest
module AnonRecd =
let v = {| A = 1; A = 2 |}
"""
|> compile
|> shouldFail
|> withErrorCode 3522
|> withMessage "The field 'A' appears multiple times in this record expression."
[<Fact>]
let ``Anonymous Records with duplicate labels - Copy and update expression`` () =
FSharp """
namespace FSharpTest
module AnonRecd =
let v = {| {| y = 3 |} with y = 2; y = 4 |}
"""
|> compile
|> shouldFail
|> withErrorCode 3522
[<Fact>]
let ``Anonymous Record type annotation with duplicate labels`` () =
FSharp """
namespace FSharpTest
module AnonRecd =
let (f : {| A : int; A : string |} option) = None
"""
|> compile
|> shouldFail
|> withErrorCode 3523
\ No newline at end of file
......@@ -83,6 +83,7 @@
<Compile Include="Conformance\PatternMatching\Simple.fs" />
<Compile Include="Conformance\Printing\Printing.fs" />
<Compile Include="Conformance\PseudoCustomAttributes\PseudoCustomAttributes.fs" />
<Compile Include="Conformance\RecordTypes\AnonymousRecords.fs" />
<Compile Include="Conformance\RecordTypes\RecordTypes.fs" />
<Compile Include="Conformance\StructTypes\StructTypes.fs" />
<Compile Include="Conformance\TypesAndTypeConstraints\CheckingSyntacticTypes\CheckingSyntacticTypes.fs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册