Skip to content

Commit 9fa2b3c

Browse files
authored
Merge pull request #5831 from cknitt/merge-from-10.1
Merge changes from 10.1
2 parents d81e6cc + 97718b8 commit 9fa2b3c

17 files changed

+1210
-835
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ These are only breaking changes for unformatted code.
4848
- Syntax: process uncurried function declarations explicitly in the parser/printer https://github.com/rescript-lang/rescript-compiler/pull/5794
4949
- PPX V4: allow uncurried `make` function and treat it like a curried one [#5802](https://github.com/rescript-lang/rescript-compiler/pull/5802) [#5808](https://github.com/rescript-lang/rescript-compiler/pull/5808) [#5812](https://github.com/rescript-lang/rescript-compiler/pull/5812)
5050

51+
# 10.1.0-rc.6
52+
53+
#### :bug: Bug Fix
54+
55+
- Fix issue where optional fields in inline records were not supported and would cause type errors https://github.com/rescript-lang/rescript-compiler/pull/5827
56+
5157
# 10.1.0-rc.5
5258

5359
#### :bug: Bug Fix

jscomp/core/js_dump.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,20 @@ and expression_desc cxt ~(level : int) f x : cxt =
757757
(if !Js_config.debug then [ (name_symbol, E.str p.name) ] else [])
758758
(fun i -> Js_op.Lit i)
759759
in
760+
let is_optional (pname: Js_op.property_name) =
761+
match pname with
762+
| Lit n -> Ext_list.mem_string p.optional_labels n
763+
| Symbol_name -> false
764+
in
765+
let tails =
766+
match p.optional_labels with
767+
| [] -> tails
768+
| _ ->
769+
Ext_list.filter_map tails (fun (f, x) ->
770+
match x.expression_desc with
771+
| Undefined when is_optional f -> None
772+
| _ -> Some (f, x))
773+
in
760774
if p.num_nonconst = 1 then tails
761775
else
762776
( Js_op.Lit L.tag,

jscomp/main/builtin_cmj_datasets.ml

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

jscomp/ml/datarepr.ml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ let constructor_descrs ty_path decl cstrs =
113113
if cd_args = Cstr_tuple [] then incr num_consts else incr num_nonconsts;
114114
if cd_res = None then incr num_normal)
115115
cstrs;
116+
let has_optional attrs = Ext_list.exists attrs (fun ({txt },_) -> txt = "ns.optional") in
116117
let rec describe_constructors idx_const idx_nonconst = function
117118
[] -> []
118119
| {cd_id; cd_args; cd_res; cd_loc; cd_attributes} :: rem ->
@@ -131,11 +132,17 @@ let constructor_descrs ty_path decl cstrs =
131132
| _ -> (Cstr_block idx_nonconst,
132133
describe_constructors idx_const (idx_nonconst+1) rem) in
133134
let cstr_name = Ident.name cd_id in
135+
let optional_labels = match cd_args with
136+
| Cstr_tuple _ -> []
137+
| Cstr_record lbls ->
138+
Ext_list.filter_map lbls (fun ({ld_id;ld_attributes; _}) ->
139+
if has_optional ld_attributes then Some ld_id.name else None)
140+
in
134141
let existentials, cstr_args, cstr_inlined =
135142
let representation =
136143
if decl.type_unboxed.unboxed
137144
then Record_unboxed true
138-
else Record_inlined {tag = idx_nonconst; name = cstr_name; num_nonconsts = !num_nonconsts}
145+
else Record_inlined {tag = idx_nonconst; name = cstr_name; num_nonconsts = !num_nonconsts; optional_labels}
139146
in
140147
constructor_args decl.type_private cd_args cd_res
141148
(Path.Pdot (ty_path, cstr_name, Path.nopos)) representation

jscomp/ml/lambda.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type record_repr =
4040

4141
type tag_info =
4242
| Blk_constructor of {name : string ; num_nonconst : int ; tag : int }
43-
| Blk_record_inlined of { name : string ; num_nonconst : int; tag : int; fields : string array; mutable_flag : Asttypes.mutable_flag }
43+
| Blk_record_inlined of { name : string ; num_nonconst : int; tag : int; optional_labels: string list; fields : string array; mutable_flag : Asttypes.mutable_flag }
4444
| Blk_tuple
4545
| Blk_poly_var of string
4646
| Blk_record of {fields : string array; mutable_flag : Asttypes.mutable_flag; record_repr : record_repr}
@@ -96,9 +96,9 @@ let blk_record_ext = ref (fun fields mutable_flag ->
9696
Blk_record_ext {fields = all_labels_info; mutable_flag }
9797
)
9898

99-
let blk_record_inlined = ref (fun fields name num_nonconst ~tag mutable_flag ->
99+
let blk_record_inlined = ref (fun fields name num_nonconst optional_labels ~tag mutable_flag ->
100100
let fields = fields |> Array.map (fun (x,_) -> x.Types.lbl_name) in
101-
Blk_record_inlined {fields; name; num_nonconst; tag; mutable_flag}
101+
Blk_record_inlined {fields; name; num_nonconst; tag; mutable_flag; optional_labels}
102102
)
103103

104104
let ref_tag_info : tag_info =

jscomp/ml/lambda.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type record_repr =
4040

4141
type tag_info =
4242
| Blk_constructor of {name : string ; num_nonconst : int; tag : int}
43-
| Blk_record_inlined of { name : string ; num_nonconst : int ; tag : int; fields : string array; mutable_flag : mutable_flag}
43+
| Blk_record_inlined of { name : string ; num_nonconst : int ; tag : int; optional_labels: string list; fields : string array; mutable_flag : mutable_flag }
4444
| Blk_tuple
4545
| Blk_poly_var of string
4646
| Blk_record of {fields : string array; mutable_flag : mutable_flag; record_repr : record_repr }
@@ -85,6 +85,7 @@ val blk_record_inlined :
8585
(Types.label_description* Typedtree.record_label_definition) array ->
8686
string ->
8787
int ->
88+
string list ->
8889
tag:int ->
8990
mutable_flag ->
9091
tag_info

jscomp/ml/translcore.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,10 +1138,10 @@ and transl_record loc env fields repres opt_init_expr =
11381138
| Record_optional_labels _ ->
11391139
Lconst
11401140
(Const_block (!Lambda.blk_record fields mut Record_optional, cl))
1141-
| Record_inlined { tag; name; num_nonconsts } ->
1141+
| Record_inlined { tag; name; num_nonconsts; optional_labels } ->
11421142
Lconst
11431143
(Const_block
1144-
( !Lambda.blk_record_inlined fields name num_nonconsts ~tag
1144+
( !Lambda.blk_record_inlined fields name num_nonconsts optional_labels ~tag
11451145
mut,
11461146
cl ))
11471147
| Record_unboxed _ ->
@@ -1160,10 +1160,10 @@ and transl_record loc env fields repres opt_init_expr =
11601160
ll,
11611161
loc )
11621162
| Record_float_unused -> assert false
1163-
| Record_inlined { tag; name; num_nonconsts } ->
1163+
| Record_inlined { tag; name; num_nonconsts; optional_labels } ->
11641164
Lprim
11651165
( Pmakeblock
1166-
(!Lambda.blk_record_inlined fields name num_nonconsts ~tag
1166+
(!Lambda.blk_record_inlined fields name num_nonconsts optional_labels ~tag
11671167
mut),
11681168
ll,
11691169
loc )

jscomp/ml/typecore.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
11531153
let label_is_optional ld =
11541154
match ld.lbl_repres with
11551155
| Record_optional_labels lbls -> Ext_list.mem_string lbls ld.lbl_name
1156+
| Record_inlined {optional_labels} -> Ext_list.mem_string optional_labels ld.lbl_name
11561157
| _ -> false in
11571158
let process_optional_label (ld, pat) =
11581159
let exp_optional_attr =
@@ -1879,6 +1880,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
18791880
let label_is_optional ld =
18801881
match ld.lbl_repres with
18811882
| Record_optional_labels lbls -> Ext_list.mem_string lbls ld.lbl_name
1883+
| Record_inlined {optional_labels} -> Ext_list.mem_string optional_labels ld.lbl_name
18821884
| _ -> false in
18831885
let process_optional_label (id, ld, e) =
18841886
let exp_optional_attr =

jscomp/ml/typedecl.ml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,20 @@ let transl_declaration env sdecl id =
358358
| (_,_,loc)::_ ->
359359
Location.prerr_warning loc Warnings.Constraint_on_gadt
360360
end;
361+
let has_optional attrs = Ext_list.exists attrs (fun ({txt },_) -> txt = "ns.optional") in
362+
let scstrs =
363+
Ext_list.map scstrs (fun ({pcd_args} as cstr) ->
364+
match pcd_args with
365+
| Pcstr_tuple _ -> cstr
366+
| Pcstr_record lds ->
367+
{cstr with pcd_args = Pcstr_record (Ext_list.map lds (fun ld ->
368+
if has_optional ld.pld_attributes then
369+
let typ = ld.pld_type in
370+
let typ = {typ with ptyp_desc = Ptyp_constr ({txt = Lident "option"; loc=typ.ptyp_loc}, [typ])} in
371+
{ld with pld_type = typ}
372+
else ld
373+
))}
374+
) in
361375
let all_constrs = ref StringSet.empty in
362376
List.iter
363377
(fun {pcd_name = {txt = name}} ->

jscomp/ml/types.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ and record_representation =
154154
| Record_float_unused (* Was: all fields are floats. Now: unused *)
155155
| Record_unboxed of bool (* Unboxed single-field record, inlined or not *)
156156
| Record_inlined of (* Inlined record *)
157-
{ tag : int ; name : string; num_nonconsts : int}
157+
{ tag : int ; name : string; num_nonconsts : int; optional_labels : string list}
158158
| Record_extension (* Inlined record under extension *)
159159
| Record_optional_labels of string list (* List of optional labels *)
160160

@@ -348,10 +348,10 @@ let same_record_representation x y =
348348
match y with
349349
| Record_optional_labels lbls2 -> lbls = lbls2
350350
| _ -> false)
351-
| Record_inlined {tag; name; num_nonconsts} -> (
351+
| Record_inlined {tag; name; num_nonconsts; optional_labels} -> (
352352
match y with
353353
| Record_inlined y ->
354-
tag = y.tag && name = y.name && num_nonconsts = y.num_nonconsts
354+
tag = y.tag && name = y.name && num_nonconsts = y.num_nonconsts && optional_labels = y.optional_labels
355355
| _ -> false)
356356
| Record_extension -> y = Record_extension
357357
| Record_unboxed x -> ( match y with Record_unboxed y -> x = y | _ -> false)

jscomp/ml/types.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ and record_representation =
301301
| Record_float_unused (* Was: all fields are floats. Now: unused *)
302302
| Record_unboxed of bool (* Unboxed single-field record, inlined or not *)
303303
| Record_inlined of (* Inlined record *)
304-
{ tag : int ; name : string; num_nonconsts : int}
304+
{ tag : int ; name : string; num_nonconsts : int; optional_labels : string list}
305305
| Record_extension (* Inlined record under extension *)
306306
| Record_optional_labels of string list (* List of optional labels *)
307307

jscomp/test/record_regression.js

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,183 @@ function setAA(ao) {
6060
};
6161
}
6262

63+
var ir0 = {
64+
TAG: /* V0 */0,
65+
x0: "v0",
66+
x3: 3
67+
};
68+
69+
var ir1 = {
70+
TAG: /* V0 */0,
71+
x0: "v0",
72+
x1: "v1",
73+
x3: 3
74+
};
75+
76+
var ir2 = {
77+
TAG: /* V0 */0,
78+
x0: "v0",
79+
x1: "v1",
80+
x2: 2,
81+
x3: 3
82+
};
83+
84+
var ir3 = {
85+
TAG: /* V1 */1,
86+
y0: "v0",
87+
y1: 1
88+
};
89+
90+
var pm0;
91+
92+
pm0 = ir0.TAG === /* V0 */0 ? [
93+
"v0",
94+
3
95+
] : [
96+
"v0",
97+
undefined
98+
];
99+
100+
var pm1;
101+
102+
if (ir1.TAG === /* V0 */0) {
103+
var x1 = "v1";
104+
var x0 = "v0";
105+
pm1 = x1 !== undefined ? [
106+
x0,
107+
x1,
108+
3
109+
] : [
110+
x0,
111+
"n/a",
112+
3
113+
];
114+
} else {
115+
pm1 = [
116+
"v0",
117+
"n/a",
118+
"v1"
119+
];
120+
}
121+
122+
var pm2;
123+
124+
if (ir2.TAG === /* V0 */0) {
125+
var x1$1 = "v1";
126+
var x0$1 = "v0";
127+
if (x1$1 !== undefined) {
128+
var x2 = 2;
129+
pm2 = x2 !== undefined ? [
130+
x0$1,
131+
x1$1,
132+
x2,
133+
3
134+
] : [
135+
x0$1,
136+
x1$1,
137+
0,
138+
3
139+
];
140+
} else {
141+
var x2$1 = 2;
142+
pm2 = x2$1 !== undefined ? [
143+
x0$1,
144+
"n/a",
145+
x2$1,
146+
3
147+
] : [
148+
x0$1,
149+
"n/a",
150+
0,
151+
3
152+
];
153+
}
154+
} else {
155+
pm2 = [
156+
"v0",
157+
"n/a",
158+
0,
159+
"v1"
160+
];
161+
}
162+
163+
function inlinedRecord(ir) {
164+
if (ir.TAG !== /* V0 */0) {
165+
return [
166+
ir.y0,
167+
"n/a",
168+
0,
169+
ir.y1
170+
];
171+
}
172+
var x1 = ir.x1;
173+
var x0 = ir.x0;
174+
if (x1 !== undefined) {
175+
switch (x1) {
176+
case "x1" :
177+
var x2 = ir.x2;
178+
if (x2 !== undefined) {
179+
return [
180+
x0,
181+
"x1",
182+
x2,
183+
ir.x3
184+
];
185+
}
186+
break;
187+
case "xx1" :
188+
var x2$1 = ir.x2;
189+
if (x2$1 !== undefined) {
190+
return [
191+
x0,
192+
"xx1",
193+
x2$1,
194+
ir.x3
195+
];
196+
}
197+
break;
198+
default:
199+
200+
}
201+
var x2$2 = ir.x2;
202+
if (x2$2 !== undefined) {
203+
return [
204+
x0,
205+
x1,
206+
x2$2,
207+
ir.x3
208+
];
209+
} else {
210+
return [
211+
x0,
212+
x1,
213+
0,
214+
ir.x3
215+
];
216+
}
217+
}
218+
var x2$3 = ir.x2;
219+
if (x2$3 !== undefined) {
220+
return [
221+
x0,
222+
"n/a",
223+
x2$3,
224+
ir.x3
225+
];
226+
} else {
227+
return [
228+
x0,
229+
"n/a",
230+
0,
231+
ir.x3
232+
];
233+
}
234+
}
235+
236+
var pm3 = inlinedRecord(ir2);
237+
238+
var pm4 = inlinedRecord(ir3);
239+
63240
var f2 = {
64241
x: 3,
65242
y: 3,
@@ -93,4 +270,14 @@ exports.h10 = h10;
93270
exports.h11 = h11;
94271
exports.po = po;
95272
exports.setAA = setAA;
273+
exports.ir0 = ir0;
274+
exports.ir1 = ir1;
275+
exports.ir2 = ir2;
276+
exports.ir3 = ir3;
277+
exports.pm0 = pm0;
278+
exports.pm1 = pm1;
279+
exports.pm2 = pm2;
280+
exports.inlinedRecord = inlinedRecord;
281+
exports.pm3 = pm3;
282+
exports.pm4 = pm4;
96283
/* Not a pure module */

0 commit comments

Comments
 (0)