@@ -13,7 +13,11 @@ open FSharp.Compiler.Text.Range
1313open FSharp.Compiler .TypedTree
1414open FSharp.Compiler .Xml
1515open FSharp.Compiler .SyntaxTrivia
16- open TypedTreeOps
16+
17+ [<RequireQualifiedAccess; NoEquality; NoComparison>]
18+ type SynExprOrSpreadValue =
19+ | SynExpr of SynExpr
20+ | SpreadValue of TType * Expr
1721
1822/// Merges updates to nested record fields on the same level in record copy-and-update.
1923///
@@ -29,21 +33,23 @@ open TypedTreeOps
2933/// which we here convert to
3034///
3135/// { x with A = { x.A with B = 10; C = "" } }
32- let GroupUpdatesToNestedFields ( fields : (( Ident list * Ident ) * SynExpr option ) list ) =
36+ let GroupUpdatesToNestedFields ( fields : (( Ident list * Ident ) * SynExprOrSpreadValue option ) list ) =
3337 let rec groupIfNested res xs =
3438 match xs with
3539 | [] -> res
3640 | [ x ] -> x :: res
3741 | x :: y :: ys ->
3842 match x, y with
39- | ( lidwid, Some( SynExpr.Record( baseInfo, copyInfo, fields1, m))), (_, Some( SynExpr.Record( recordFields = fields2))) ->
43+ | ( lidwid, Some( SynExprOrSpreadValue.SynExpr( SynExpr.Record( baseInfo, copyInfo, fields1, m)))),
44+ (_, Some( SynExprOrSpreadValue.SynExpr( SynExpr.Record( recordFields = fields2)))) ->
4045 let reducedRecd =
41- ( lidwid, Some( SynExpr.Record( baseInfo, copyInfo, fields1 @ fields2, m)))
46+ ( lidwid, Some( SynExprOrSpreadValue. SynExpr( SynExpr .Record( baseInfo, copyInfo, fields1 @ fields2, m) )))
4247
4348 groupIfNested res ( reducedRecd :: ys)
44- | ( lidwid, Some( SynExpr.AnonRecd( isStruct, copyInfo, fields1, m, trivia))), (_, Some( SynExpr.AnonRecd( recordFields = fields2))) ->
49+ | ( lidwid, Some( SynExprOrSpreadValue.SynExpr( SynExpr.AnonRecd( isStruct, copyInfo, fields1, m, trivia)))),
50+ (_, Some( SynExprOrSpreadValue.SynExpr( SynExpr.AnonRecd( recordFields = fields2)))) ->
4551 let reducedRecd =
46- ( lidwid, Some( SynExpr.AnonRecd( isStruct, copyInfo, fields1 @ fields2, m, trivia)))
52+ ( lidwid, Some( SynExprOrSpreadValue. SynExpr( SynExpr .AnonRecd( isStruct, copyInfo, fields1 @ fields2, m, trivia) )))
4753
4854 groupIfNested res ( reducedRecd :: ys)
4955 | _ -> groupIfNested ( x :: res) ( y :: ys)
@@ -118,18 +124,28 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
118124 | Item.AnonRecdField(
119125 anonInfo = {
120126 AnonRecdTypeInfo.TupInfo = TupInfo.Const isStruct
121- }) ->
122- let fields = [ LongIdentWithDots([ fieldId ], []), None, nestedField ]
127+ }
128+ range = m) ->
129+ let fields =
130+ [
131+ SynExprAnonRecordFieldOrSpread.Field(
132+ SynExprAnonRecordField( LongIdentWithDots([ fieldId ], []), None, nestedField, m),
133+ None
134+ )
135+ ]
136+
123137 SynExpr.AnonRecd( isStruct, copyInfo outerFieldId, fields, outerFieldId.idRange, { OpeningBraceRange = range0 })
124138 | _ ->
125139 let fields =
126140 [
127- SynExprRecordField(
128- ( LongIdentWithDots([ fieldId ], []), true ),
129- None,
130- Some nestedField,
131- unionRanges fieldId.idRange nestedField.Range,
132- None
141+ SynExprRecordFieldOrSpread.Field(
142+ SynExprRecordField(
143+ ( LongIdentWithDots([ fieldId ], []), true ),
144+ None,
145+ Some nestedField,
146+ unionRanges fieldId.idRange nestedField.Range,
147+ None
148+ )
133149 )
134150 ]
135151
@@ -148,8 +164,15 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
148164
149165 let outerFieldId = ident ( outerFieldId.idText, outerFieldId.idRange.MakeSynthetic())
150166
151- ( accessIds, outerFieldId),
152- Some( synExprRecd ( recdExprCopyInfo ( fields |> List.map fst) withExpr) outerFieldId rest exprBeingAssigned)
167+ let recdExpr =
168+ match exprBeingAssigned with
169+ | SynExprOrSpreadValue.SynExpr synExpr ->
170+ Some(
171+ SynExprOrSpreadValue.SynExpr( synExprRecd ( recdExprCopyInfo ( fields |> List.map fst) withExpr) outerFieldId rest synExpr)
172+ )
173+ | SynExprOrSpreadValue.SpreadValue _ -> Some exprBeingAssigned
174+
175+ ( accessIds, outerFieldId), recdExpr
153176
154177/// When the original expression in copy-and-update is more complex than `{ x with ... }`, like `{ f () with ... }`,
155178/// we bind it first, so that it's not evaluated multiple times during a nested update
0 commit comments