@@ -7855,42 +7855,69 @@ and CheckAnonRecdExprDuplicateFields (elems: Ident array) =
78557855 errorR(Error (FSComp.SR.tcAnonRecdDuplicateFieldId(uc1.idText), uc1.idRange))))
78567856
78577857// Check '{| .... |}'
7858- and TcAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, optOrigSynExpr, unsortedFieldIdsAndSynExprsGiven , mWholeExpr) =
7858+ and TcAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, optOrigSynExpr, recordFields: SynExprRecordField list , mWholeExpr) =
78597859 match optOrigSynExpr with
78607860 | None ->
7861- TcNewAnonRecdExpr cenv overallTy env tpenv (isStruct, unsortedFieldIdsAndSynExprsGiven , mWholeExpr)
7861+ TcNewAnonRecdExpr cenv overallTy env tpenv (isStruct, recordFields , mWholeExpr)
78627862
78637863 | Some orig ->
78647864 // Ideally we should also check for duplicate field IDs in the TcCopyAndUpdateAnonRecdExpr case, but currently the logic is too complex to guarantee a proper error reporting
78657865 // So here we error instead errorR to avoid cascading internal errors
7866- unsortedFieldIdsAndSynExprsGiven
7867- |> List.countBy (fun (fId, _, _ ) -> textOfLid fId.LongIdent)
7866+ recordFields
7867+ |> List.countBy (fun (SynExprRecordField(fieldName = ( fId, _)) ) -> textOfLid fId.LongIdent)
78687868 |> List.iter (fun (label, count) ->
78697869 if count > 1 then error (Error (FSComp.SR.tcAnonRecdDuplicateFieldId(label), mWholeExpr)))
78707870
7871- TcCopyAndUpdateAnonRecdExpr cenv overallTy env tpenv (isStruct, orig, unsortedFieldIdsAndSynExprsGiven , mWholeExpr)
7871+ TcCopyAndUpdateAnonRecdExpr cenv overallTy env tpenv (isStruct, orig, recordFields , mWholeExpr)
78727872
7873- and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, unsortedFieldIdsAndSynExprsGiven , mWholeExpr) =
7873+ and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, recordFields: SynExprRecordField list , mWholeExpr) =
78747874
78757875 let g = cenv.g
7876- let unsortedFieldSynExprsGiven = unsortedFieldIdsAndSynExprsGiven |> List.map (fun (_, _, fieldExpr) -> fieldExpr)
7877- let unsortedFieldIds = unsortedFieldIdsAndSynExprsGiven |> List.map (fun (synLongIdent, _, _) -> synLongIdent.LongIdent[0]) |> List.toArray
7878- let anonInfo, sortedFieldTys = UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv mWholeExpr overallTy isStruct unsortedFieldIds
7876+
7877+ // For new anonymous records, each field label must be a single identifier.
7878+ // If a long identifier is given, report an error and skip that entry for typechecking purposes.
7879+ // Also normalize missing expressions to an error expression to keep traversal stable.
7880+ let validFields : (Ident * SynExpr * SynLongIdent) list =
7881+ recordFields
7882+ |> List.choose (fun (SynExprRecordField(fieldName = (synLongIdent, _); expr = e; range = mField)) ->
7883+ match synLongIdent.LongIdent with
7884+ | [ id ] ->
7885+ let exprGiven =
7886+ match e with
7887+ | Some e -> e
7888+ | None -> SynExpr.FromParseError(SynExpr.Const(SynConst.Unit, mField), mField)
7889+ Some(id, exprGiven, synLongIdent)
7890+ | [] ->
7891+ // Should not occur for anonymous record expressions; silently skip with a diagnostic.
7892+ errorR (Error(FSComp.SR.parsInvalidAnonRecdType(), synLongIdent.Range))
7893+ None
7894+ | _ ->
7895+ // Nested labels are only valid in copy-and-update; not allowed for new anonymous records
7896+ errorR (Error(FSComp.SR.parsInvalidAnonRecdType(), synLongIdent.Range))
7897+ None)
7898+
7899+ let unsortedFieldSynExprsGiven = validFields |> List.map (fun (_, e, _) -> e)
7900+
7901+ let unsortedFieldIds = validFields |> List.map (fun (id, _, _) -> id) |> List.toArray
7902+
7903+ let anonInfo, sortedFieldTys =
7904+ UnifyAnonRecdTypeAndInferCharacteristics env.eContextInfo cenv env.DisplayEnv mWholeExpr overallTy isStruct unsortedFieldIds
78797905
78807906 if unsortedFieldIds.Length > 1 then
78817907 CheckAnonRecdExprDuplicateFields unsortedFieldIds
78827908
78837909 // Sort into canonical order
78847910 let sortedIndexedArgs =
7885- unsortedFieldIdsAndSynExprsGiven
7911+ validFields
78867912 |> List.indexed
78877913 |> List.sortBy (fun (i,_) -> unsortedFieldIds[i].idText)
78887914
78897915 // Map from sorted indexes to unsorted indexes
78907916 let sigma = sortedIndexedArgs |> List.map fst |> List.toArray
7891- let sortedFieldExprs = sortedIndexedArgs |> List.map snd
7917+ let sortedFieldTriples = sortedIndexedArgs |> List.map snd
78927918
7893- sortedFieldExprs |> List.iteri (fun j (synLongIdent, _, _) ->
7919+ sortedFieldTriples
7920+ |> List.iteri (fun j (_, _, synLongIdent) ->
78947921 let m = rangeOfLid synLongIdent.LongIdent
78957922 let item = Item.AnonRecdField(anonInfo, sortedFieldTys, j, m)
78967923 CallNameResolutionSink cenv.tcSink (m, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Use, env.eAccessRights))
@@ -7903,11 +7930,12 @@ and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, unsortedField
79037930
79047931 let flexes = unsortedFieldTys |> List.map (fun _ -> true)
79057932
7906- let unsortedCheckedArgs, tpenv = TcExprsWithFlexes cenv env mWholeExpr tpenv flexes unsortedFieldTys unsortedFieldSynExprsGiven
7933+ let unsortedCheckedArgs, tpenv =
7934+ TcExprsWithFlexes cenv env mWholeExpr tpenv flexes unsortedFieldTys unsortedFieldSynExprsGiven
79077935
79087936 mkAnonRecd g mWholeExpr anonInfo unsortedFieldIds unsortedCheckedArgs unsortedFieldTys, tpenv
79097937
7910- and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (origExpr, blockSeparator), unsortedFieldIdsAndSynExprsGiven , mWholeExpr) =
7938+ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (origExpr, blockSeparator), recordFields: SynExprRecordField list , mWholeExpr) =
79117939 // The fairly complex case '{| origExpr with X = 1; Y = 2 |}'
79127940 // The origExpr may be either a record or anonymous record.
79137941 // The origExpr may be either a struct or not.
@@ -7926,14 +7954,17 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or
79267954 if not (isAppTy g origExprTy || isAnonRecdTy g origExprTy) then
79277955 error (Error (FSComp.SR.tcCopyAndUpdateNeedsRecordType(), mOrigExpr))
79287956
7929- // Expand expressions with respect to potential nesting
7957+ // Expand expressions with respect to potentially nesting
79307958 let unsortedFieldIdsAndSynExprsGiven =
7931- unsortedFieldIdsAndSynExprsGiven
7932- |> List.map (fun (synLongIdent, _, exprBeingAssigned ) ->
7959+ recordFields
7960+ |> List.map (fun (SynExprRecordField(fieldName = ( synLongIdent, _); expr = e) ) ->
79337961 match synLongIdent.LongIdent with
79347962 | [] -> error(Error(FSComp.SR.nrUnexpectedEmptyLongId(), mWholeExpr))
7935- | [ id ] -> ([], id), Some exprBeingAssigned
7936- | lid -> TransformAstForNestedUpdates cenv env origExprTy lid exprBeingAssigned (origExpr, blockSeparator))
7963+ | [ id ] -> ([], id), e
7964+ | lid ->
7965+ match e with
7966+ | Some exprBeingAssigned -> TransformAstForNestedUpdates cenv env origExprTy lid exprBeingAssigned (origExpr, blockSeparator)
7967+ | None -> List.frontAndBack lid, None)
79377968 |> GroupUpdatesToNestedFields
79387969
79397970 let unsortedFieldSynExprsGiven = unsortedFieldIdsAndSynExprsGiven |> List.choose snd
0 commit comments