Skip to content

Commit b632d73

Browse files
committed
WIP: disambiguate optional labels
When disambiguating record types, there's a check that all the labels are supplied when constructing a record. While not supplying all the labels is supported in case of optional labels, the order of disambiguation is affected by the presence of optional labels. Example: ```res type t1 = {x:int, y:int} type t2 = {x:int, y:int, z?:int} let v = {x:3, y:4} ``` Currently `v` has type `t1`, while it's perfectly fine for it to have type `t2`. In particular, the normal shadowing behaviour that applies without optional labels, does not happen. (If you remove `z` from the second type definition, then the normal shadowing happens, and `v` gets type `t2`. This wip changes the disambiguation so that supplying at least all the mandatory labels is enough in disambiguation. The change also addresses the issue #6752 of spurious warning of unused open.
1 parent 8403cdb commit b632d73

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

jscomp/ml/env.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,8 @@ let open_signature
20482048
);
20492049
let shadowed = ref [] in
20502050
let slot s b =
2051+
let () = Printf.eprintf "XXX slot %s\n" s in
2052+
(* let _ = assert false in *)
20512053
begin match check_shadowing env b with
20522054
| Some kind when not (List.mem (kind, s) !shadowed) ->
20532055
shadowed := (kind, s) :: !shadowed;

jscomp/ml/typecore.ml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,14 +840,23 @@ module Label = NameChoice (struct
840840
end)
841841

842842
let disambiguate_label_by_ids keep closed ids labels =
843+
Printf.eprintf "XXX disambiguate_label_by_ids labels:%d\n" (List.length labels);
843844
let check_ids (lbl, _) =
844845
let lbls = Hashtbl.create 8 in
845846
Array.iter (fun lbl -> Hashtbl.add lbls lbl.lbl_name ()) lbl.lbl_all;
846847
List.for_all (Hashtbl.mem lbls) ids
847848
and check_closed (lbl, _) =
848-
(not closed || List.length ids = Array.length lbl.lbl_all)
849+
let all_lbls = ref (Array.length lbl.lbl_all) in
850+
all_lbls := 0;
851+
for i = 0 to Array.length lbl.lbl_all - 1 do
852+
let lbl = lbl.lbl_all.(i) in
853+
if not (label_is_optional lbl) then incr all_lbls
854+
done;
855+
Printf.eprintf "XXX check_closed %s %d %d\n" lbl.lbl_name (List.length ids) !all_lbls;
856+
(not closed || List.length ids >= !all_lbls)
849857
in
850858
let labels' = Ext_list.filter labels check_ids in
859+
Printf.eprintf "XXX labels':%d\n" (List.length labels);
851860
if keep && labels' = [] then (false, labels) else
852861
let labels'' = Ext_list.filter labels' check_closed in
853862
if keep && labels'' = [] then (false, labels') else (true, labels'')
@@ -864,6 +873,7 @@ let disambiguate_lid_a_list loc closed env opath lid_a_list =
864873
| _ -> Location.prerr_warning loc msg
865874
in
866875
let process_label lid =
876+
let () = Printf.eprintf "XXX process_label %s\n" (Longident.last lid.txt) in
867877
(* Strategy for each field:
868878
* collect all the labels in scope for that name
869879
* if the type is known and principal, just eventually warn
@@ -882,6 +892,7 @@ let disambiguate_lid_a_list loc closed env opath lid_a_list =
882892
Some (_, _) -> (true, scope) (* disambiguate only checks scope *)
883893
| _ -> disambiguate_label_by_ids (opath=None) closed ids scope
884894
in
895+
Printf.eprintf "ok: %b\n" ok;
885896
if ok then Label.disambiguate lid env opath labels ~warn ~scope
886897
else fst (List.hd labels) (* will fail later *)
887898
in

0 commit comments

Comments
 (0)