From 18d620a268bb5617b6cb65f0a7e3118a48f9d9a9 Mon Sep 17 00:00:00 2001 From: kerams Date: Wed, 21 Jun 2023 17:15:51 +0200 Subject: [PATCH 1/2] Improve diagnostics for malformed anonymous records --- src/Compiler/Checking/CheckExpressions.fs | 3 --- src/Compiler/pars.fsy | 5 +++- .../Types/RecordTypes/AnonymousRecords.fs | 24 ++++++++++++++++++- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index f18525f47f2..9cbc9dc9264 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -4353,9 +4353,6 @@ and TcTypeOrMeasure kindOpt (cenv: cenv) newOk checkConstraints occ (iwsam: Warn | SynType.Tuple(isStruct, segments, m) -> TcTupleType kindOpt cenv newOk checkConstraints occ env tpenv isStruct segments m - | SynType.AnonRecd(_, [],m) -> - error(Error((FSComp.SR.tcAnonymousTypeInvalidInDeclaration()), m)) - | SynType.AnonRecd(isStruct, args, m) -> TcAnonRecdType cenv newOk checkConstraints occ env tpenv isStruct args m diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index da62e142c25..32201fd824e 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -5879,7 +5879,10 @@ atomTypeOrAnonRecdType: flds |> List.choose (function | (SynField([], false, Some id, ty, false, _xmldoc, None, _m, _trivia)) -> Some(id, ty) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) - SynType.AnonRecd(isStruct, flds2, rhs parseState 1) } + + match flds2 with + | [] -> SynType.FromParseError(rhs parseState 1) + | _ -> SynType.AnonRecd(isStruct, flds2, rhs parseState 1) } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */ diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs index 32ec8b2962e..e9dbe8ffd43 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/RecordTypes/AnonymousRecords.fs @@ -42,4 +42,26 @@ module AnonRecd = """ |> compile |> shouldFail - |> withErrorCode 3523 \ No newline at end of file + |> withErrorCode 3523 + + [] + let ``Anonymous record types with parser errors or no fields do not produce overlapping diagnostics`` () = + FSharp """ +module AnonRecd + +type ContactMethod = + | Address of {| Line1 : string; Line 2 : string; Postcode : string |} + +let (x: {| |}) = () + +type ErrorResponse = + { error: {| type : string + message : string |} } +""" + |> typecheck + |> shouldFail + |> withDiagnostics [ + Error 10, Line 5, Col 42, Line 5, Col 43, "Unexpected integer literal in field declaration. Expected ':' or other token." + Error 10, Line 7, Col 12, Line 7, Col 14, "Unexpected symbol '|}' in field declaration. Expected identifier or other token." + Error 10, Line 10, Col 17, Line 10, Col 21, "Incomplete structured construct at or before this point in field declaration. Expected identifier or other token." + ] \ No newline at end of file From 5e537e6a8ea439bb047cfd2aa3d358aba4f6fd94 Mon Sep 17 00:00:00 2001 From: kerams Date: Wed, 21 Jun 2023 17:43:30 +0200 Subject: [PATCH 2/2] Rework --- src/Compiler/Checking/CheckExpressions.fs | 4 ++++ src/Compiler/pars.fsy | 5 +---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 9cbc9dc9264..d63598d532f 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -4353,6 +4353,10 @@ and TcTypeOrMeasure kindOpt (cenv: cenv) newOk checkConstraints occ (iwsam: Warn | SynType.Tuple(isStruct, segments, m) -> TcTupleType kindOpt cenv newOk checkConstraints occ env tpenv isStruct segments m + | SynType.AnonRecd(fields = []) -> + // The parser takes care of error messages + NewErrorType(), tpenv + | SynType.AnonRecd(isStruct, args, m) -> TcAnonRecdType cenv newOk checkConstraints occ env tpenv isStruct args m diff --git a/src/Compiler/pars.fsy b/src/Compiler/pars.fsy index 32201fd824e..da62e142c25 100644 --- a/src/Compiler/pars.fsy +++ b/src/Compiler/pars.fsy @@ -5879,10 +5879,7 @@ atomTypeOrAnonRecdType: flds |> List.choose (function | (SynField([], false, Some id, ty, false, _xmldoc, None, _m, _trivia)) -> Some(id, ty) | _ -> reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsInvalidAnonRecdType()); None) - - match flds2 with - | [] -> SynType.FromParseError(rhs parseState 1) - | _ -> SynType.AnonRecd(isStruct, flds2, rhs parseState 1) } + SynType.AnonRecd(isStruct, flds2, rhs parseState 1) } /* Any tokens in this grammar must be added to the lex filter rule 'peekAdjacentTypars' */ /* See the F# specification "Lexical analysis of type applications and type parameter definitions" */