Skip to content

Commit c1b9701

Browse files
zthcristianoc
andauthored
Experiment with allowing empty inline records (#6494)
* experiment with allowing empty inline records * remove check for empty record pattern match * syntax tests * Update inline_record_test.res * add extra test for top level empty record match * changelog * Remove some dead code. --------- Co-authored-by: Cristiano Calcagno <[email protected]>
1 parent e709f3c commit c1b9701

File tree

14 files changed

+55
-90
lines changed

14 files changed

+55
-90
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
1313
# 11.0.0-rc.7 (Unreleased)
1414

15+
#### :rocket: New Feature
16+
17+
- Allow empty inline records in variants. https://github.com/rescript-lang/rescript-compiler/pull/6494
18+
- Allow empty record patterns in pattern matching. https://github.com/rescript-lang/rescript-compiler/pull/6494
19+
1520
# 11.0.0-rc.6
1621

1722
#### :rocket: New Feature

jscomp/frontend/bs_ast_invariant.ml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,6 @@ let emit_external_warnings : iterator =
166166
(fun self (pat : Parsetree.pattern) ->
167167
match pat.ppat_desc with
168168
| Ppat_constant constant -> check_constant pat.ppat_loc constant
169-
| Ppat_record ([], _) ->
170-
Location.raise_errorf ~loc:pat.ppat_loc
171-
"Empty record pattern is not supported"
172169
| _ -> super.pat self pat);
173170
}
174171

jscomp/gentype/GenTypeCommon.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type labelJS =
2626
| IntLabel of string
2727
| StringLabel of string
2828

29-
type case = {label: string; labelJS: labelJS}
29+
type case = {labelJS: labelJS}
3030

3131
let isJSSafePropertyName name =
3232
name = ""

jscomp/gentype/Runtime.ml

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,6 @@
1-
type recordGen = {mutable unboxed: int; mutable boxed: int}
2-
type recordValue = int
31
type moduleItem = string
42
type moduleAccessPath = Root of string | Dot of moduleAccessPath * moduleItem
53

6-
let recordValueToString recordValue = recordValue |> string_of_int
7-
let recordGen () = {unboxed = 0; boxed = 0}
8-
9-
let newRecordValue ~unboxed recordGen =
10-
if unboxed then (
11-
let v = recordGen.unboxed in
12-
recordGen.unboxed <- recordGen.unboxed + 1;
13-
v)
14-
else
15-
let v = recordGen.boxed in
16-
recordGen.boxed <- recordGen.boxed + 1;
17-
v
18-
194
let newModuleItem ~name = name
205

216
let rec emitModuleAccessPath ~config moduleAccessPath =

jscomp/gentype/Runtime.mli

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
open GenTypeCommon
22

3-
type recordGen
4-
type recordValue
53
type moduleItem
64
type moduleAccessPath = Root of string | Dot of moduleAccessPath * moduleItem
75

@@ -11,9 +9,6 @@ val emitModuleAccessPath : config:Config.t -> moduleAccessPath -> string
119

1210
val isMutableObjectField : string -> bool
1311
val newModuleItem : name:string -> moduleItem
14-
val newRecordValue : unboxed:bool -> recordGen -> recordValue
15-
val recordGen : unit -> recordGen
16-
val recordValueToString : recordValue -> string
1712
val jsVariantTag : polymorphic:bool -> tag:string option -> string
1813
val jsVariantPayloadTag : n:int -> string
1914
val jsVariantValue : polymorphic:bool -> string

jscomp/gentype/TranslateCoreType.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ and translateCoreType_ ~config ~typeVarsGen
192192
else if isNumber label then IntLabel label
193193
else StringLabel label
194194
in
195-
{label; labelJS})
195+
{labelJS})
196196
in
197197
let payloadsTranslations =
198198
payloads
@@ -207,7 +207,6 @@ and translateCoreType_ ~config ~typeVarsGen
207207
{
208208
case =
209209
{
210-
label;
211210
labelJS =
212211
(if isNumber label then IntLabel label
213212
else StringLabel label);

jscomp/gentype/TranslateTypeDeclarations.ml

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ let createExportTypeFromTypeDeclaration ~annotation ~loc ~nameAs ~opaque ~type_
2323

2424
let createCase (label, attributes) ~poly =
2525
{
26-
label;
2726
labelJS =
2827
(match
2928
attributes |> Annotation.getAttributePayload Annotation.tagIsAs
@@ -230,7 +229,6 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
230229
}
231230
|> returnTypeDeclaration
232231
| VariantDeclarationFromTypes constructorDeclarations, None ->
233-
let recordGen = Runtime.recordGen () in
234232
let variants =
235233
constructorDeclarations
236234
|> List.map (fun constructorDeclaration ->
@@ -262,46 +260,25 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
262260
|> Translation.translateDependencies ~config ~outputFileRelative
263261
~resolver
264262
in
265-
let recordValue =
266-
recordGen
267-
|> Runtime.newRecordValue
268-
~unboxed:(constructorArgs = Cstr_tuple [])
269-
in
270-
( name,
271-
attributes,
272-
argTypes,
273-
importTypes,
274-
recordValue |> Runtime.recordValueToString ))
263+
(name, attributes, argTypes, importTypes))
275264
in
276265
let variantsNoPayload, variantsWithPayload =
277-
variants |> List.partition (fun (_, _, argTypes, _, _) -> argTypes = [])
266+
variants |> List.partition (fun (_, _, argTypes, _) -> argTypes = [])
278267
in
279268
let noPayloads =
280269
variantsNoPayload
281-
|> List.map
282-
(fun (name, attributes, _argTypes, _importTypes, recordValue) ->
283-
{
284-
((name, attributes) |> createCase ~poly:false) with
285-
label = recordValue;
286-
})
270+
|> List.map (fun (name, attributes, _argTypes, _importTypes) ->
271+
(name, attributes) |> createCase ~poly:false)
287272
in
288273
let payloads =
289274
variantsWithPayload
290-
|> List.map
291-
(fun (name, attributes, argTypes, _importTypes, recordValue) ->
275+
|> List.map (fun (name, attributes, argTypes, _importTypes) ->
292276
let type_ =
293277
match argTypes with
294278
| [type_] -> type_
295279
| _ -> Tuple argTypes
296280
in
297-
{
298-
case =
299-
{
300-
((name, attributes) |> createCase ~poly:false) with
301-
label = recordValue;
302-
};
303-
t = type_;
304-
})
281+
{case = (name, attributes) |> createCase ~poly:false; t = type_})
305282
in
306283
let variantTyp =
307284
createVariant ~inherits:[] ~noPayloads ~payloads ~polymorphic:false
@@ -325,7 +302,7 @@ let traslateDeclarationKind ~config ~loc ~outputFileRelative ~resolver
325302
in
326303
let importTypes =
327304
variants
328-
|> List.map (fun (_, _, _, importTypes, _) -> importTypes)
305+
|> List.map (fun (_, _, _, importTypes) -> importTypes)
329306
|> List.concat
330307
in
331308
{CodeItem.exportFromTypeDeclaration; importTypes} |> returnTypeDeclaration

jscomp/gentype/TranslateTypeExprFromTypes.ml

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,13 @@ let translateConstr ~config ~paramsTranslation ~(path : Path.t) ~typeEnv =
137137
}
138138
| ( (["Pervasives"; "result"] | ["Belt"; "Result"; "t"] | ["result"]),
139139
[paramTranslation1; paramTranslation2] ) ->
140-
let case n name type_ =
141-
{case = {label = string_of_int n; labelJS = StringLabel name}; t = type_}
142-
in
140+
let case name type_ = {case = {labelJS = StringLabel name}; t = type_} in
143141
let variant =
144142
createVariant ~inherits:[] ~noPayloads:[]
145143
~payloads:
146144
[
147-
case 0 "Ok" paramTranslation1.type_;
148-
case 1 "Error" paramTranslation2.type_;
145+
case "Ok" paramTranslation1.type_;
146+
case "Error" paramTranslation2.type_;
149147
]
150148
~polymorphic:false ~tag:None ~unboxed:false
151149
in
@@ -384,7 +382,6 @@ and translateTypeExprFromTypes_ ~config ~typeVarsGen ~typeEnv
384382
noPayloads
385383
|> List.map (fun label ->
386384
{
387-
label;
388385
labelJS =
389386
(if isNumber label then IntLabel label
390387
else StringLabel label);
@@ -401,8 +398,7 @@ and translateTypeExprFromTypes_ ~config ~typeVarsGen ~typeEnv
401398
t |> translateTypeExprFromTypes_ ~config ~typeVarsGen ~typeEnv
402399
| {noPayloads; payloads; unknowns = []} ->
403400
let noPayloads =
404-
noPayloads
405-
|> List.map (fun label -> {label; labelJS = StringLabel label})
401+
noPayloads |> List.map (fun label -> {labelJS = StringLabel label})
406402
in
407403
let payloadTranslations =
408404
payloads
@@ -414,10 +410,7 @@ and translateTypeExprFromTypes_ ~config ~typeVarsGen ~typeEnv
414410
let payloads =
415411
payloadTranslations
416412
|> List.map (fun (label, translation) ->
417-
{
418-
case = {label; labelJS = StringLabel label};
419-
t = translation.type_;
420-
})
413+
{case = {labelJS = StringLabel label}; t = translation.type_})
421414
in
422415
let type_ =
423416
createVariant ~inherits:[] ~noPayloads ~payloads ~polymorphic:true

jscomp/gentype_tests/typescript-react-example/package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/ml/typecore.ml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,6 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
12731273
| _ -> k None
12741274
end
12751275
| Ppat_record(lid_sp_list, closed) ->
1276-
assert (lid_sp_list <> []);
12771276
let opath, record_ty =
12781277
try
12791278
let (p0, p, _, _) = extract_concrete_record !env expected_ty in

jscomp/syntax/src/res_core.ml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4544,7 +4544,6 @@ and parseConstrDeclArgs p =
45444544
(* TODO: this could use some cleanup/stratification *)
45454545
match p.Parser.token with
45464546
| Lbrace -> (
4547-
let lbrace = p.startPos in
45484547
Parser.next p;
45494548
let startPos = p.Parser.startPos in
45504549
match p.Parser.token with
@@ -4683,14 +4682,6 @@ and parseConstrDeclArgs p =
46834682
:: parseCommaDelimitedRegion ~grammar:Grammar.FieldDeclarations
46844683
~closing:Rbrace ~f:parseFieldDeclarationRegion p
46854684
in
4686-
let () =
4687-
match fields with
4688-
| [] ->
4689-
Parser.err ~startPos:lbrace p
4690-
(Diagnostics.message
4691-
"An inline record declaration needs at least one field")
4692-
| _ -> ()
4693-
in
46944685
Parser.expect Rbrace p;
46954686
Parser.optional p Comma |> ignore;
46964687
Parser.expect Rparen p;

jscomp/syntax/tests/parsing/errors/typeDef/expected/emptyInlineRecord.res.txt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
2-
Syntax error!
3-
tests/parsing/errors/typeDef/emptyInlineRecord.res:3:10-11
4-
5-
1 │ type node<'a> =
6-
2 │ | Nil
7-
3 │ | Node({})
8-
4 │
9-
10-
An inline record declaration needs at least one field
11-
121
type nonrec 'a node =
132
| Nil
143
| Node of {

jscomp/test/inline_record_test.js

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jscomp/test/inline_record_test.res

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,20 @@ let ff1 = (x: t1): t1 =>
117117
}
118118

119119
let () = Mt.from_pair_suites(__MODULE__, suites.contents)
120+
121+
type emptyRecord = A | B({})
122+
123+
let b = B({})
124+
125+
let () = switch b {
126+
| A => Js.log("A!")
127+
| B({}) => Js.log("B")
128+
}
129+
130+
type r = {y: int}
131+
let r = {y: 10}
132+
133+
switch r {
134+
| {y: 10} => Js.log("10!")
135+
| {} => Js.log("Catch all?")
136+
}

0 commit comments

Comments
 (0)