Skip to content

Commit 13c4257

Browse files
Record spreads
1 parent 984837b commit 13c4257

File tree

114 files changed

+30308
-282
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+30308
-282
lines changed

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 214 additions & 6 deletions
Large diffs are not rendered by default.

src/Compiler/Checking/CheckPatterns.fs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,14 @@ and TcPatArrayOrList warnOnUpper cenv env vFlags patEnv ty isArray args m =
457457
phase2, acc
458458

459459
and TcRecordPat warnOnUpper (cenv: cenv) env vFlags patEnv ty fieldPats m =
460-
let fieldPats =
460+
let fieldPats =
461+
// This will obviously need to change if we support spreads in record patterns.
462+
let isFromSpread = false
461463
fieldPats
462464
|> List.map (fun (NamePatPairField(fieldName = fieldLid; pat = pat)) ->
463465
match fieldLid.LongIdent with
464-
| [id] -> ([], id), pat
465-
| lid -> List.frontAndBack lid, pat)
466+
| [id] -> isFromSpread, ([], id), pat
467+
| lid -> isFromSpread, List.frontAndBack lid, pat)
466468

467469
match BuildFieldMap cenv env false ty fieldPats m with
468470
| None -> (fun _ -> TPat_error m), patEnv

src/Compiler/Checking/CheckRecordSyntaxHelpers.fs

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ open FSharp.Compiler.Text.Range
1313
open FSharp.Compiler.TypedTree
1414
open FSharp.Compiler.Xml
1515
open 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

src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,26 @@ open FSharp.Compiler.Syntax
77
open FSharp.Compiler.Text
88
open FSharp.Compiler.TypedTree
99

10+
[<RequireQualifiedAccess; NoEquality; NoComparison>]
11+
type SynExprOrSpreadValue =
12+
/// A syntactic expression being assigned to a record field.
13+
| SynExpr of SynExpr
14+
15+
/// A typechecked record field `get` from a spread expression.
16+
| SpreadValue of TType * Expr
17+
1018
val GroupUpdatesToNestedFields:
11-
fields: ((Ident list * Ident) * SynExpr option) list -> ((Ident list * Ident) * SynExpr option) list
19+
fields: ((Ident list * Ident) * SynExprOrSpreadValue option) list ->
20+
((Ident list * Ident) * SynExprOrSpreadValue option) list
1221

1322
val TransformAstForNestedUpdates:
1423
cenv: TcFileState ->
1524
env: TcEnv ->
1625
overallTy: TType ->
1726
lid: LongIdent ->
18-
exprBeingAssigned: SynExpr ->
27+
exprBeingAssigned: SynExprOrSpreadValue ->
1928
withExpr: SynExpr * BlockSeparator ->
20-
(Ident list * Ident) * SynExpr option
29+
(Ident list * Ident) * SynExprOrSpreadValue option
2130

2231
val BindOriginalRecdExpr:
2332
withExpr: SynExpr * BlockSeparator -> mkRecdExpr: ((SynExpr * BlockSeparator) option -> SynExpr) -> SynExpr

0 commit comments

Comments
 (0)