Skip to content

Commit 54e6a2b

Browse files
committed
Test: support {} for empty records.
1 parent 7b1362b commit 54e6a2b

File tree

7 files changed

+115
-61
lines changed

7 files changed

+115
-61
lines changed

jscomp/core/js_dump.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ and expression_desc cxt ~(level : int) f x : cxt =
718718
Js_op.Lit (Ext_ident.convert x))))
719719
(*name convention of Record is slight different from modules*)
720720
| Caml_block (el, mutable_flag, _, Blk_record { fields; record_repr }) -> (
721-
if Ext_array.for_alli fields (fun i v -> string_of_int i = v) then
721+
if Array.length fields <> 0 && Ext_array.for_alli fields (fun i v -> string_of_int i = v) then
722722
expression_desc cxt ~level f (Array (el, mutable_flag))
723723
else
724724
match record_repr with

jscomp/ml/typecore.ml

+26-11
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type error =
7272
| Unknown_literal of string * char
7373
| Illegal_letrec_pat
7474
| Labels_omitted of string list
75+
| Empty_record_literal
7576
exception Error of Location.t * Env.t * error
7677
exception Error_forward of Location.error
7778

@@ -298,7 +299,7 @@ let extract_option_type env ty =
298299

299300
let extract_concrete_record env ty =
300301
match extract_concrete_typedecl env ty with
301-
(p0, p, {type_kind=Type_record (fields, _)}) -> (p0, p, fields)
302+
(p0, p, {type_kind=Type_record (fields, repr)}) -> (p0, p, fields, repr)
302303
| _ -> raise Not_found
303304

304305
let extract_concrete_variant env ty =
@@ -1145,7 +1146,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
11451146
assert (lid_sp_list <> []);
11461147
let opath, record_ty =
11471148
try
1148-
let (p0, p,_) = extract_concrete_record !env expected_ty in
1149+
let (p0, p, _, _) = extract_concrete_record !env expected_ty in
11491150
Some (p0, p), expected_ty
11501151
with Not_found -> None, newvar ()
11511152
in
@@ -2147,14 +2148,13 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
21472148
exp_env = env }
21482149
end
21492150
| Pexp_record(lid_sexp_list, None) ->
2150-
assert (lid_sexp_list <> []);
2151-
let ty_record, opath =
2151+
let ty_record, opath, fields, repr_opt =
21522152
match extract_concrete_record env ty_expected with
2153-
| (p0, p,_) ->
2153+
| (p0, p, fields, repr) ->
21542154
(* XXX level may be wrong *)
2155-
ty_expected, Some (p0, p)
2155+
ty_expected, Some (p0, p), fields, Some repr
21562156
| exception Not_found ->
2157-
newvar (), None
2157+
newvar (), None, [], None
21582158

21592159
in
21602160
let lbl_exp_list =
@@ -2166,7 +2166,20 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
21662166
in
21672167
unify_exp_types loc env ty_record (instance env ty_expected);
21682168
check_duplicates loc env lbl_exp_list;
2169-
let (_, { lbl_all = label_descriptions; lbl_repres = representation}, _) = List.hd lbl_exp_list in
2169+
let label_descriptions, representation = match lbl_exp_list, repr_opt with
2170+
| (_, { lbl_all = label_descriptions; lbl_repres = representation}, _) :: _, _ -> label_descriptions, representation
2171+
| [], Some (Record_optional_labels optional_labels as representation) when lid_sexp_list = [] ->
2172+
let filter_missing (ld : Types.label_declaration) =
2173+
let name = Ident.name ld.ld_id in
2174+
if List.mem name optional_labels then
2175+
None
2176+
else
2177+
Some name in
2178+
let labels_missing = fields |> List.filter_map filter_missing in
2179+
if labels_missing <> [] then
2180+
raise(Error(loc, env, Labels_missing labels_missing));
2181+
[||], representation
2182+
| [], _ -> raise(Error(loc, env, Empty_record_literal)) in
21702183
let labels_missing = ref [] in
21712184
let label_definitions =
21722185
let matching_label lbl =
@@ -2205,7 +2218,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
22052218
let ty_record, opath =
22062219
let get_path ty =
22072220
try
2208-
let (p0, p,_) = extract_concrete_record env ty in
2221+
let (p0, p, _, _) = extract_concrete_record env ty in
22092222
(* XXX level may be wrong *)
22102223
Some (p0, p)
22112224
with Not_found -> None
@@ -2803,7 +2816,7 @@ and type_label_access env srecord lid =
28032816
let ty_exp = record.exp_type in
28042817
let opath =
28052818
try
2806-
let (p0, p,_) = extract_concrete_record env ty_exp in
2819+
let (p0, p, _, _) = extract_concrete_record env ty_exp in
28072820
Some(p0, p)
28082821
with Not_found -> None
28092822
in
@@ -3805,9 +3818,11 @@ let report_error env ppf = function
38053818
| Illegal_letrec_pat ->
38063819
fprintf ppf
38073820
"Only variables are allowed as left-hand side of `let rec'"
3808-
| Labels_omitted labels ->
3821+
| Labels_omitted labels ->
38093822
fprintf ppf "For labeled funciton, labels %s were omitted in the application of this function."
38103823
(String.concat ", " labels)
3824+
| Empty_record_literal ->
3825+
fprintf ppf "Empty record literal {} should be type annotated or used in a record context."
38113826
38123827
let super_report_error_no_wrap_printing_env = report_error
38133828

jscomp/ml/typecore.mli

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ type error =
108108
| Unknown_literal of string * char
109109
| Illegal_letrec_pat
110110
| Labels_omitted of string list
111+
| Empty_record_literal
111112
exception Error of Location.t * Env.t * error
112113
exception Error_forward of Location.error
113114

lib/4.06.1/unstable/js_compiler.ml

+28-12
Original file line numberDiff line numberDiff line change
@@ -38915,6 +38915,7 @@ type error =
3891538915
| Unknown_literal of string * char
3891638916
| Illegal_letrec_pat
3891738917
| Labels_omitted of string list
38918+
| Empty_record_literal
3891838919
exception Error of Location.t * Env.t * error
3891938920
exception Error_forward of Location.error
3892038921

@@ -39021,6 +39022,7 @@ type error =
3902139022
| Unknown_literal of string * char
3902239023
| Illegal_letrec_pat
3902339024
| Labels_omitted of string list
39025+
| Empty_record_literal
3902439026
exception Error of Location.t * Env.t * error
3902539027
exception Error_forward of Location.error
3902639028

@@ -39247,7 +39249,7 @@ let extract_option_type env ty =
3924739249

3924839250
let extract_concrete_record env ty =
3924939251
match extract_concrete_typedecl env ty with
39250-
(p0, p, {type_kind=Type_record (fields, _)}) -> (p0, p, fields)
39252+
(p0, p, {type_kind=Type_record (fields, repr)}) -> (p0, p, fields, repr)
3925139253
| _ -> raise Not_found
3925239254

3925339255
let extract_concrete_variant env ty =
@@ -40094,7 +40096,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
4009440096
assert (lid_sp_list <> []);
4009540097
let opath, record_ty =
4009640098
try
40097-
let (p0, p,_) = extract_concrete_record !env expected_ty in
40099+
let (p0, p, _, _) = extract_concrete_record !env expected_ty in
4009840100
Some (p0, p), expected_ty
4009940101
with Not_found -> None, newvar ()
4010040102
in
@@ -41096,14 +41098,13 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
4109641098
exp_env = env }
4109741099
end
4109841100
| Pexp_record(lid_sexp_list, None) ->
41099-
assert (lid_sexp_list <> []);
41100-
let ty_record, opath =
41101+
let ty_record, opath, fields, repr_opt =
4110141102
match extract_concrete_record env ty_expected with
41102-
| (p0, p,_) ->
41103+
| (p0, p, fields, repr) ->
4110341104
(* XXX level may be wrong *)
41104-
ty_expected, Some (p0, p)
41105+
ty_expected, Some (p0, p), fields, Some repr
4110541106
| exception Not_found ->
41106-
newvar (), None
41107+
newvar (), None, [], None
4110741108

4110841109
in
4110941110
let lbl_exp_list =
@@ -41115,7 +41116,20 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
4111541116
in
4111641117
unify_exp_types loc env ty_record (instance env ty_expected);
4111741118
check_duplicates loc env lbl_exp_list;
41118-
let (_, { lbl_all = label_descriptions; lbl_repres = representation}, _) = List.hd lbl_exp_list in
41119+
let label_descriptions, representation = match lbl_exp_list, repr_opt with
41120+
| (_, { lbl_all = label_descriptions; lbl_repres = representation}, _) :: _, _ -> label_descriptions, representation
41121+
| [], Some (Record_optional_labels optional_labels as representation) when lid_sexp_list = [] ->
41122+
let filter_missing (ld : Types.label_declaration) =
41123+
let name = Ident.name ld.ld_id in
41124+
if List.mem name optional_labels then
41125+
None
41126+
else
41127+
Some name in
41128+
let labels_missing = fields |> List.filter_map filter_missing in
41129+
if labels_missing <> [] then
41130+
raise(Error(loc, env, Labels_missing labels_missing));
41131+
[||], representation
41132+
| [], _ -> raise(Error(loc, env, Empty_record_literal)) in
4111941133
let labels_missing = ref [] in
4112041134
let label_definitions =
4112141135
let matching_label lbl =
@@ -41154,7 +41168,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
4115441168
let ty_record, opath =
4115541169
let get_path ty =
4115641170
try
41157-
let (p0, p,_) = extract_concrete_record env ty in
41171+
let (p0, p, _, _) = extract_concrete_record env ty in
4115841172
(* XXX level may be wrong *)
4115941173
Some (p0, p)
4116041174
with Not_found -> None
@@ -41752,7 +41766,7 @@ and type_label_access env srecord lid =
4175241766
let ty_exp = record.exp_type in
4175341767
let opath =
4175441768
try
41755-
let (p0, p,_) = extract_concrete_record env ty_exp in
41769+
let (p0, p, _, _) = extract_concrete_record env ty_exp in
4175641770
Some(p0, p)
4175741771
with Not_found -> None
4175841772
in
@@ -42754,9 +42768,11 @@ let report_error env ppf = function
4275442768
| Illegal_letrec_pat ->
4275542769
fprintf ppf
4275642770
"Only variables are allowed as left-hand side of `let rec'"
42757-
| Labels_omitted labels ->
42771+
| Labels_omitted labels ->
4275842772
fprintf ppf "For labeled funciton, labels %s were omitted in the application of this function."
4275942773
(String.concat ", " labels)
42774+
| Empty_record_literal ->
42775+
fprintf ppf "Empty record literal {} should be type annotated or used in a record context."
4276042776

4276142777
let super_report_error_no_wrap_printing_env = report_error
4276242778

@@ -79689,7 +79705,7 @@ and expression_desc cxt ~(level : int) f x : cxt =
7968979705
Js_op.Lit (Ext_ident.convert x))))
7969079706
(*name convention of Record is slight different from modules*)
7969179707
| Caml_block (el, mutable_flag, _, Blk_record { fields; record_repr }) -> (
79692-
if Ext_array.for_alli fields (fun i v -> string_of_int i = v) then
79708+
if Array.length fields <> 0 && Ext_array.for_alli fields (fun i v -> string_of_int i = v) then
7969379709
expression_desc cxt ~level f (Array (el, mutable_flag))
7969479710
else
7969579711
match record_repr with

lib/4.06.1/unstable/js_playground_compiler.ml

+29-18
Original file line numberDiff line numberDiff line change
@@ -38915,6 +38915,7 @@ type error =
3891538915
| Unknown_literal of string * char
3891638916
| Illegal_letrec_pat
3891738917
| Labels_omitted of string list
38918+
| Empty_record_literal
3891838919
exception Error of Location.t * Env.t * error
3891938920
exception Error_forward of Location.error
3892038921

@@ -39021,6 +39022,7 @@ type error =
3902139022
| Unknown_literal of string * char
3902239023
| Illegal_letrec_pat
3902339024
| Labels_omitted of string list
39025+
| Empty_record_literal
3902439026
exception Error of Location.t * Env.t * error
3902539027
exception Error_forward of Location.error
3902639028

@@ -39247,7 +39249,7 @@ let extract_option_type env ty =
3924739249

3924839250
let extract_concrete_record env ty =
3924939251
match extract_concrete_typedecl env ty with
39250-
(p0, p, {type_kind=Type_record (fields, _)}) -> (p0, p, fields)
39252+
(p0, p, {type_kind=Type_record (fields, repr)}) -> (p0, p, fields, repr)
3925139253
| _ -> raise Not_found
3925239254

3925339255
let extract_concrete_variant env ty =
@@ -40094,7 +40096,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
4009440096
assert (lid_sp_list <> []);
4009540097
let opath, record_ty =
4009640098
try
40097-
let (p0, p,_) = extract_concrete_record !env expected_ty in
40099+
let (p0, p, _, _) = extract_concrete_record !env expected_ty in
4009840100
Some (p0, p), expected_ty
4009940101
with Not_found -> None, newvar ()
4010040102
in
@@ -41096,14 +41098,13 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
4109641098
exp_env = env }
4109741099
end
4109841100
| Pexp_record(lid_sexp_list, None) ->
41099-
assert (lid_sexp_list <> []);
41100-
let ty_record, opath =
41101+
let ty_record, opath, fields, repr_opt =
4110141102
match extract_concrete_record env ty_expected with
41102-
| (p0, p,_) ->
41103+
| (p0, p, fields, repr) ->
4110341104
(* XXX level may be wrong *)
41104-
ty_expected, Some (p0, p)
41105+
ty_expected, Some (p0, p), fields, Some repr
4110541106
| exception Not_found ->
41106-
newvar (), None
41107+
newvar (), None, [], None
4110741108

4110841109
in
4110941110
let lbl_exp_list =
@@ -41115,7 +41116,20 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
4111541116
in
4111641117
unify_exp_types loc env ty_record (instance env ty_expected);
4111741118
check_duplicates loc env lbl_exp_list;
41118-
let (_, { lbl_all = label_descriptions; lbl_repres = representation}, _) = List.hd lbl_exp_list in
41119+
let label_descriptions, representation = match lbl_exp_list, repr_opt with
41120+
| (_, { lbl_all = label_descriptions; lbl_repres = representation}, _) :: _, _ -> label_descriptions, representation
41121+
| [], Some (Record_optional_labels optional_labels as representation) when lid_sexp_list = [] ->
41122+
let filter_missing (ld : Types.label_declaration) =
41123+
let name = Ident.name ld.ld_id in
41124+
if List.mem name optional_labels then
41125+
None
41126+
else
41127+
Some name in
41128+
let labels_missing = fields |> List.filter_map filter_missing in
41129+
if labels_missing <> [] then
41130+
raise(Error(loc, env, Labels_missing labels_missing));
41131+
[||], representation
41132+
| [], _ -> raise(Error(loc, env, Empty_record_literal)) in
4111941133
let labels_missing = ref [] in
4112041134
let label_definitions =
4112141135
let matching_label lbl =
@@ -41154,7 +41168,7 @@ and type_expect_ ?in_function ?(recarg=Rejected) env sexp ty_expected =
4115441168
let ty_record, opath =
4115541169
let get_path ty =
4115641170
try
41157-
let (p0, p,_) = extract_concrete_record env ty in
41171+
let (p0, p, _, _) = extract_concrete_record env ty in
4115841172
(* XXX level may be wrong *)
4115941173
Some (p0, p)
4116041174
with Not_found -> None
@@ -41752,7 +41766,7 @@ and type_label_access env srecord lid =
4175241766
let ty_exp = record.exp_type in
4175341767
let opath =
4175441768
try
41755-
let (p0, p,_) = extract_concrete_record env ty_exp in
41769+
let (p0, p, _, _) = extract_concrete_record env ty_exp in
4175641770
Some(p0, p)
4175741771
with Not_found -> None
4175841772
in
@@ -42754,9 +42768,11 @@ let report_error env ppf = function
4275442768
| Illegal_letrec_pat ->
4275542769
fprintf ppf
4275642770
"Only variables are allowed as left-hand side of `let rec'"
42757-
| Labels_omitted labels ->
42771+
| Labels_omitted labels ->
4275842772
fprintf ppf "For labeled funciton, labels %s were omitted in the application of this function."
4275942773
(String.concat ", " labels)
42774+
| Empty_record_literal ->
42775+
fprintf ppf "Empty record literal {} should be type annotated or used in a record context."
4276042776

4276142777
let super_report_error_no_wrap_printing_env = report_error
4276242778

@@ -79689,7 +79705,7 @@ and expression_desc cxt ~(level : int) f x : cxt =
7968979705
Js_op.Lit (Ext_ident.convert x))))
7969079706
(*name convention of Record is slight different from modules*)
7969179707
| Caml_block (el, mutable_flag, _, Blk_record { fields; record_repr }) -> (
79692-
if Ext_array.for_alli fields (fun i v -> string_of_int i = v) then
79708+
if Array.length fields <> 0 && Ext_array.for_alli fields (fun i v -> string_of_int i = v) then
7969379709
expression_desc cxt ~level f (Array (el, mutable_flag))
7969479710
else
7969579711
match record_repr with
@@ -285488,13 +285504,9 @@ and parseBracedOrRecordExpr p =
285488285504
Parser.expect Lbrace p;
285489285505
match p.Parser.token with
285490285506
| Rbrace ->
285491-
Parser.err p (Diagnostics.unexpected Rbrace p.breadcrumbs);
285492285507
Parser.next p;
285493285508
let loc = mkLoc startPos p.prevEndPos in
285494-
let braces = makeBracesAttr loc in
285495-
Ast_helper.Exp.construct ~attrs:[braces] ~loc
285496-
(Location.mkloc (Longident.Lident "()") loc)
285497-
None
285509+
Ast_helper.Exp.record ~loc [] None
285498285510
| DotDotDot ->
285499285511
(* beginning of record spread, parse record *)
285500285512
Parser.next p;
@@ -287107,7 +287119,6 @@ and parseFieldDeclarationRegion p =
287107287119
| Lident _ ->
287108287120
let lident, loc = parseLident p in
287109287121
let name = Location.mkloc lident loc in
287110-
(* XXX *)
287111287122
let optional = parseOptionalLabel p in
287112287123
let typ =
287113287124
match p.Parser.token with

0 commit comments

Comments
 (0)