Skip to content

Commit e56e865

Browse files
committed
Pattern matching for @nullable records.
This gives pattern matching that mimics expression constructor, where the variable by default is not optional. The generated code seems fine, thought the checks for exhaustiveness are not kicking in. See #5452
1 parent 7e58a20 commit e56e865

File tree

6 files changed

+74
-0
lines changed

6 files changed

+74
-0
lines changed

jscomp/ml/typecore.ml

+14
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,19 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
11491149
Some (p0, p), expected_ty
11501150
with Not_found -> None, newvar ()
11511151
in
1152+
let label_is_optional ld =
1153+
match ld.lbl_repres with
1154+
| Record_optional_labels lbls -> Ext_list.mem_string lbls ld.lbl_name
1155+
| _ -> false in
1156+
let process_optional_label (id, ld, pat) =
1157+
let exp_optional_attr =
1158+
Ext_list.exists pat.ppat_attributes (fun ({txt },_) -> txt = "optional")
1159+
in
1160+
if label_is_optional ld && not exp_optional_attr then
1161+
let ppat_desc = Ppat_construct ({id with txt = Longident.Lident "Some"}, Some pat)
1162+
in {pat with ppat_desc}
1163+
else pat
1164+
in
11521165
let type_label_pat (label_lid, label, sarg) k =
11531166
begin_def ();
11541167
let (vars, ty_arg, ty_res) = instance_label false label in
@@ -1159,6 +1172,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
11591172
raise(Error(label_lid.loc, !env,
11601173
Label_mismatch(label_lid.txt, trace)))
11611174
end;
1175+
let sarg = process_optional_label (label_lid, label, sarg) in
11621176
type_pat sarg ty_arg (fun arg ->
11631177
if vars <> [] then begin
11641178
end_def ();

jscomp/test/res_debug.js

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ var newrecord = Caml_obj.obj_dup(v0);
1515

1616
newrecord.x = 3;
1717

18+
function testMatch(v) {
19+
var y = v.y;
20+
if (y !== undefined) {
21+
return y;
22+
} else {
23+
return 42;
24+
}
25+
}
26+
1827
var v2 = newrecord;
1928

2029
var v1 = {
@@ -30,6 +39,7 @@ exports.f = f;
3039
exports.v0 = v0;
3140
exports.v2 = v2;
3241
exports.v1 = v1;
42+
exports.testMatch = testMatch;
3343
exports.h = h;
3444
exports.hey = hey;
3545
/* Not a pure module */

jscomp/test/res_debug.res

+8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ let v1 : r = { x : 3
4444
, z : 3
4545
}
4646

47+
@@warning("-56") // Turn off match case unreachable
48+
49+
let testMatch = v =>
50+
switch v {
51+
| {y} => y
52+
| {y: @optional None} => 42
53+
}
54+
4755
let h = '😊'
4856
let hey = "hello, 世界"
4957
// failed to type check

lib/4.06.1/unstable/js_compiler.ml

+14
Original file line numberDiff line numberDiff line change
@@ -40052,6 +40052,19 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
4005240052
Some (p0, p), expected_ty
4005340053
with Not_found -> None, newvar ()
4005440054
in
40055+
let label_is_optional ld =
40056+
match ld.lbl_repres with
40057+
| Record_optional_labels lbls -> Ext_list.mem_string lbls ld.lbl_name
40058+
| _ -> false in
40059+
let process_optional_label (id, ld, pat) =
40060+
let exp_optional_attr =
40061+
Ext_list.exists pat.ppat_attributes (fun ({txt },_) -> txt = "optional")
40062+
in
40063+
if label_is_optional ld && not exp_optional_attr then
40064+
let ppat_desc = Ppat_construct ({id with txt = Longident.Lident "Some"}, Some pat)
40065+
in {pat with ppat_desc}
40066+
else pat
40067+
in
4005540068
let type_label_pat (label_lid, label, sarg) k =
4005640069
begin_def ();
4005740070
let (vars, ty_arg, ty_res) = instance_label false label in
@@ -40062,6 +40075,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
4006240075
raise(Error(label_lid.loc, !env,
4006340076
Label_mismatch(label_lid.txt, trace)))
4006440077
end;
40078+
let sarg = process_optional_label (label_lid, label, sarg) in
4006540079
type_pat sarg ty_arg (fun arg ->
4006640080
if vars <> [] then begin
4006740081
end_def ();

lib/4.06.1/unstable/js_playground_compiler.ml

+14
Original file line numberDiff line numberDiff line change
@@ -40052,6 +40052,19 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
4005240052
Some (p0, p), expected_ty
4005340053
with Not_found -> None, newvar ()
4005440054
in
40055+
let label_is_optional ld =
40056+
match ld.lbl_repres with
40057+
| Record_optional_labels lbls -> Ext_list.mem_string lbls ld.lbl_name
40058+
| _ -> false in
40059+
let process_optional_label (id, ld, pat) =
40060+
let exp_optional_attr =
40061+
Ext_list.exists pat.ppat_attributes (fun ({txt },_) -> txt = "optional")
40062+
in
40063+
if label_is_optional ld && not exp_optional_attr then
40064+
let ppat_desc = Ppat_construct ({id with txt = Longident.Lident "Some"}, Some pat)
40065+
in {pat with ppat_desc}
40066+
else pat
40067+
in
4005540068
let type_label_pat (label_lid, label, sarg) k =
4005640069
begin_def ();
4005740070
let (vars, ty_arg, ty_res) = instance_label false label in
@@ -40062,6 +40075,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
4006240075
raise(Error(label_lid.loc, !env,
4006340076
Label_mismatch(label_lid.txt, trace)))
4006440077
end;
40078+
let sarg = process_optional_label (label_lid, label, sarg) in
4006540079
type_pat sarg ty_arg (fun arg ->
4006640080
if vars <> [] then begin
4006740081
end_def ();

lib/4.06.1/whole_compiler.ml

+14
Original file line numberDiff line numberDiff line change
@@ -214583,6 +214583,19 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
214583214583
Some (p0, p), expected_ty
214584214584
with Not_found -> None, newvar ()
214585214585
in
214586+
let label_is_optional ld =
214587+
match ld.lbl_repres with
214588+
| Record_optional_labels lbls -> Ext_list.mem_string lbls ld.lbl_name
214589+
| _ -> false in
214590+
let process_optional_label (id, ld, pat) =
214591+
let exp_optional_attr =
214592+
Ext_list.exists pat.ppat_attributes (fun ({txt },_) -> txt = "optional")
214593+
in
214594+
if label_is_optional ld && not exp_optional_attr then
214595+
let ppat_desc = Ppat_construct ({id with txt = Longident.Lident "Some"}, Some pat)
214596+
in {pat with ppat_desc}
214597+
else pat
214598+
in
214586214599
let type_label_pat (label_lid, label, sarg) k =
214587214600
begin_def ();
214588214601
let (vars, ty_arg, ty_res) = instance_label false label in
@@ -214593,6 +214606,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
214593214606
raise(Error(label_lid.loc, !env,
214594214607
Label_mismatch(label_lid.txt, trace)))
214595214608
end;
214609+
let sarg = process_optional_label (label_lid, label, sarg) in
214596214610
type_pat sarg ty_arg (fun arg ->
214597214611
if vars <> [] then begin
214598214612
end_def ();

0 commit comments

Comments
 (0)