Skip to content

Commit f835e3f

Browse files
committed
support rest of inline record
1 parent d634e1e commit f835e3f

File tree

3 files changed

+271
-61
lines changed

3 files changed

+271
-61
lines changed

compiler/ml/typecore.ml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,22 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env sp
16021602
if opt then Some label.lbl_name else None)
16031603
lbl_pat_list
16041604
in
1605+
let runtime_excluded_fields =
1606+
match lbl_pat_list with
1607+
| (_, label1, _, _) :: _ -> (
1608+
match label1.lbl_repres with
1609+
| Record_inlined {attrs; _}
1610+
when not (Ast_untagged_variants.process_untagged attrs) ->
1611+
let tag_name =
1612+
match Ast_untagged_variants.process_tag_name attrs with
1613+
| Some s -> s
1614+
| None -> "TAG"
1615+
in
1616+
if List.mem tag_name explicit_fields then explicit_fields
1617+
else tag_name :: explicit_fields
1618+
| _ -> explicit_fields)
1619+
| [] -> explicit_fields
1620+
in
16051621
(* Get rest field names *)
16061622
let rest_field_names =
16071623
List.map
@@ -1708,7 +1724,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env sp
17081724
rest_type = rest_type_expr;
17091725
rest_path;
17101726
rest_labels;
1711-
excluded_labels = explicit_fields;
1727+
excluded_labels = runtime_excluded_fields;
17121728
}
17131729
in
17141730
rp k
Lines changed: 145 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
// Generated by ReScript, PLEASE EDIT WITH CARE
22

3+
import * as Mocha from "mocha";
4+
import * as Test_utils from "./test_utils.mjs";
35

4-
let rest = ((({name, ...__rest}) => __rest))({
5-
name: "test",
6-
version: "1.0",
7-
debug: true
8-
});
9-
10-
function describe(c) {
6+
function describeConfig(c) {
117
let rest = ((({name, ...__rest}) => __rest))(c);
128
return [
139
c.name,
@@ -23,11 +19,6 @@ function extractClassName(param) {
2319
return ((({className, ...__rest}) => __rest))(param);
2420
}
2521

26-
let intRest = ((({id, ...__rest}) => __rest))({
27-
id: "1",
28-
value: 42
29-
});
30-
3122
function getValue(param) {
3223
return ((({id, ...__rest}) => __rest))(param);
3324
}
@@ -36,44 +27,160 @@ function getTupleRest(param) {
3627
return ((({name, ...__rest}) => __rest))(param[0]);
3728
}
3829

39-
let tupleRest = getTupleRest([
40-
{
41-
name: "tuple",
42-
version: "2.0",
43-
debug: false
44-
},
45-
1
46-
]);
47-
4830
function getWrappedRest(wrapped) {
4931
return ((({name, ...__rest}) => __rest))(wrapped._0);
5032
}
5133

52-
let wrappedRest = getWrappedRest({
53-
TAG: "Wrap",
54-
_0: {
55-
name: "wrapped",
34+
function getInlineWrappedRest(wrapped) {
35+
return ((({TAG, name, ...__rest}) => __rest))(wrapped);
36+
}
37+
38+
function getCustomTaggedInlineWrappedRest(wrapped) {
39+
return ((({kind, name, ...__rest}) => __rest))(wrapped);
40+
}
41+
42+
Mocha.describe("Record_rest_test", () => {
43+
Mocha.test("let binding captures record rest value", () => {
44+
let rest = ((({name, ...__rest}) => __rest))({
45+
name: "test",
46+
version: "1.0",
47+
debug: true
48+
});
49+
Test_utils.eq("File \"record_rest_test.res\", line 83, characters 7-14", "test", "test");
50+
Test_utils.eq("File \"record_rest_test.res\", line 84, characters 7-14", rest, {
51+
version: "1.0",
52+
debug: true
53+
});
54+
});
55+
Mocha.test("match arm returns the named field and the rest record", () => Test_utils.eq("File \"record_rest_test.res\", line 89, characters 6-13", describeConfig({
56+
name: "match",
57+
version: "2.0",
58+
debug: false
59+
}), [
60+
"match",
61+
{
62+
version: "2.0",
63+
debug: false
64+
}
65+
]));
66+
Mocha.test("function parameter destructuring keeps the named field", () => Test_utils.eq("File \"record_rest_test.res\", line 96, characters 7-14", getName({
67+
name: "param",
5668
version: "3.0",
5769
debug: true
58-
}
70+
}), "param"));
71+
Mocha.test("optional overlap keeps the remaining fields in the rest object", () => {
72+
let onClick = () => {};
73+
let rest = extractClassName({
74+
className: "btn",
75+
style: "bold",
76+
onClick: onClick
77+
});
78+
Test_utils.eq("File \"record_rest_test.res\", line 102, characters 7-14", rest, {
79+
style: "bold",
80+
onClick: onClick
81+
});
82+
});
83+
Mocha.test("polymorphic rest captures the value field", () => {
84+
let intRest = ((({id, ...__rest}) => __rest))({
85+
id: "1",
86+
value: 42
87+
});
88+
Test_utils.eq("File \"record_rest_test.res\", line 107, characters 7-14", "1", "1");
89+
Test_utils.eq("File \"record_rest_test.res\", line 108, characters 7-14", intRest, {
90+
value: 42
91+
});
92+
Test_utils.eq("File \"record_rest_test.res\", line 109, characters 7-14", ((({id, ...__rest}) => __rest))({
93+
id: "2",
94+
value: "hello"
95+
}), {
96+
value: "hello"
97+
});
98+
});
99+
Mocha.test("tuple nested record rest is initialized", () => Test_utils.eq("File \"record_rest_test.res\", line 114, characters 6-13", getTupleRest([
100+
{
101+
name: "tuple",
102+
version: "4.0",
103+
debug: false
104+
},
105+
1
106+
]), {
107+
version: "4.0",
108+
debug: false
109+
}));
110+
Mocha.test("variant payload rest works through the or-pattern path", () => {
111+
Test_utils.eq("File \"record_rest_test.res\", line 122, characters 6-13", getWrappedRest({
112+
TAG: "Wrap",
113+
_0: {
114+
name: "wrapped",
115+
version: "5.0",
116+
debug: true
117+
}
118+
}), {
119+
version: "5.0",
120+
debug: true
121+
});
122+
Test_utils.eq("File \"record_rest_test.res\", line 127, characters 6-13", getWrappedRest({
123+
TAG: "Mirror",
124+
_0: {
125+
name: "mirror",
126+
version: "6.0",
127+
debug: false
128+
}
129+
}), {
130+
version: "6.0",
131+
debug: false
132+
});
133+
});
134+
Mocha.test("inline record variant rest removes the runtime tag field", () => {
135+
Test_utils.eq("File \"record_rest_test.res\", line 135, characters 6-13", getInlineWrappedRest({
136+
TAG: "InlineWrap",
137+
name: "inline",
138+
version: "7.0",
139+
debug: true
140+
}), {
141+
version: "7.0",
142+
debug: true
143+
});
144+
Test_utils.eq("File \"record_rest_test.res\", line 140, characters 6-13", getInlineWrappedRest({
145+
TAG: "InlineMirror",
146+
name: "inlineMirror",
147+
version: "8.0",
148+
debug: false
149+
}), {
150+
version: "8.0",
151+
debug: false
152+
});
153+
});
154+
Mocha.test("inline record variant rest removes a custom runtime tag field", () => {
155+
Test_utils.eq("File \"record_rest_test.res\", line 148, characters 6-13", getCustomTaggedInlineWrappedRest({
156+
kind: "CustomInlineWrap",
157+
name: "customInline",
158+
version: "9.0",
159+
debug: true
160+
}), {
161+
version: "9.0",
162+
debug: true
163+
});
164+
Test_utils.eq("File \"record_rest_test.res\", line 155, characters 6-13", getCustomTaggedInlineWrappedRest({
165+
kind: "CustomInlineMirror",
166+
name: "customInlineMirror",
167+
version: "10.0",
168+
debug: false
169+
}), {
170+
version: "10.0",
171+
debug: false
172+
});
173+
});
59174
});
60175

61-
let name = "test";
62-
63-
let id = "1";
64-
65176
export {
66-
rest,
67-
name,
68-
describe,
177+
describeConfig,
69178
getName,
70179
extractClassName,
71-
intRest,
72-
id,
73180
getValue,
74181
getTupleRest,
75-
tupleRest,
76182
getWrappedRest,
77-
wrappedRest,
183+
getInlineWrappedRest,
184+
getCustomTaggedInlineWrappedRest,
78185
}
79-
/* tupleRest Not a pure module */
186+
/* Not a pure module */

0 commit comments

Comments
 (0)