@@ -13,7 +13,11 @@ open FSharp.Compiler.Text.Range
13
13
open FSharp.Compiler .TypedTree
14
14
open FSharp.Compiler .Xml
15
15
open FSharp.Compiler .SyntaxTrivia
16
- open TypedTreeOps
16
+
17
+ [<RequireQualifiedAccess; NoEquality; NoComparison>]
18
+ type SynExprOrSpreadValue =
19
+ | SynExpr of SynExpr
20
+ | SpreadValue of TType * Expr
17
21
18
22
/// Merges updates to nested record fields on the same level in record copy-and-update.
19
23
///
@@ -29,21 +33,23 @@ open TypedTreeOps
29
33
/// which we here convert to
30
34
///
31
35
/// { 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 ) =
33
37
let rec groupIfNested res xs =
34
38
match xs with
35
39
| [] -> res
36
40
| [ x ] -> x :: res
37
41
| x :: y :: ys ->
38
42
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)))) ->
40
45
let reducedRecd =
41
- ( lidwid, Some( SynExpr.Record( baseInfo, copyInfo, fields1 @ fields2, m)))
46
+ ( lidwid, Some( SynExprOrSpreadValue. SynExpr( SynExpr .Record( baseInfo, copyInfo, fields1 @ fields2, m) )))
42
47
43
48
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)))) ->
45
51
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) )))
47
53
48
54
groupIfNested res ( reducedRecd :: ys)
49
55
| _ -> groupIfNested ( x :: res) ( y :: ys)
@@ -118,18 +124,28 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
118
124
| Item.AnonRecdField(
119
125
anonInfo = {
120
126
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
+
123
137
SynExpr.AnonRecd( isStruct, copyInfo outerFieldId, fields, outerFieldId.idRange, { OpeningBraceRange = range0 })
124
138
| _ ->
125
139
let fields =
126
140
[
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
+ )
133
149
)
134
150
]
135
151
@@ -148,8 +164,15 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
148
164
149
165
let outerFieldId = ident ( outerFieldId.idText, outerFieldId.idRange.MakeSynthetic())
150
166
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
153
176
154
177
/// When the original expression in copy-and-update is more complex than `{ x with ... }`, like `{ f () with ... }`,
155
178
/// we bind it first, so that it's not evaluated multiple times during a nested update
0 commit comments