Skip to content

Commit 81b11ec

Browse files
committed
fixes
1 parent 9fa2193 commit 81b11ec

File tree

4 files changed

+15
-24
lines changed

4 files changed

+15
-24
lines changed

jscomp/ml/dict_type_helpers.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
66
### How are they implemented?
77
Dicts in ReScript are implemented as predefined record type, with a single (magic) field that holds
8-
the type of the dict's values. This field is called `dictValuesType`, and is just an implementation
9-
detail - it's never actually exposed to the user, just used internally.
8+
the type of the dict's values. This field is called `dictValuesType`, and it represent every possible
9+
key in the dict. It's just an implementation detail - it's never actually exposed to the user, just
10+
used internally.
1011
1112
The compiler will route any label lookup on the dict record type to the magic field, which creates a
1213
record with unknown keys, but of a single type.

jscomp/ml/typecore.ml

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ module NameChoice(Name : sig
790790
val get_type: t -> type_expr
791791
val get_descrs: Env.type_descriptions -> t list
792792

793-
val add_with_name: t -> string -> t
793+
val unsafe_do_not_use_add_with_name: t -> string -> t
794794
val unbound_name_error: Env.t -> Longident.t loc -> 'a
795795

796796
end) = struct
@@ -804,14 +804,8 @@ end) = struct
804804
let lookup_from_type env tpath (lid : Longident.t loc) : Name.t =
805805
let descrs = get_descrs (Env.find_type_descrs tpath env) in
806806
Env.mark_type_used env (Path.last tpath) (Env.find_type tpath env);
807-
let is_dict = Path.same tpath Predef.path_dict in
808-
if is_dict then (
809-
(* [dict] Dicts are implemented as a record with a single "magic" field. This magic field is
810-
used to track the dict value type, and any label lookup on the dict record type
811-
will give that single value type back. This is how we can piggy back on the record
812-
pattern matching mechanism.
813-
814-
The code below handles directing any label lookup to the magic field. *)
807+
if Path.same tpath Predef.path_dict then (
808+
(* [dict] Handle directing any label lookup to the magic dict field. *)
815809
match lid.txt with
816810
Longident.Lident s_ -> begin
817811
let s =
@@ -822,7 +816,7 @@ end) = struct
822816
try
823817
let x = List.find (fun nd -> get_name nd = s) descrs in
824818
if s = Dict_type_helpers.dict_magic_field_name
825-
then add_with_name x s_
819+
then unsafe_do_not_use_add_with_name x s_
826820
else x
827821
with Not_found ->
828822
let names = List.map get_name descrs in
@@ -914,7 +908,7 @@ module Label = NameChoice (struct
914908
let type_kind = "record"
915909
let get_name lbl = lbl.lbl_name
916910

917-
let add_with_name lbl name =
911+
let unsafe_do_not_use_add_with_name lbl name =
918912
(* [dict] This is used in dicts and shouldn't be used anywhere else.
919913
It adds a new field to an existing record type, to "fool" the pattern
920914
matching into thinking the label exists. *)
@@ -1084,7 +1078,7 @@ module Constructor = NameChoice (struct
10841078
let get_name cstr = cstr.cstr_name
10851079
let get_type cstr = cstr.cstr_res
10861080

1087-
let add_with_name _cstr _name = assert false
1081+
let unsafe_do_not_use_add_with_name _cstr _name = assert false
10881082
let get_descrs = fst
10891083
let unbound_name_error = Typetexp.unbound_constructor_error
10901084
end)
@@ -1396,10 +1390,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
13961390
let has_dict_pattern_attr = Dict_type_helpers.has_dict_pattern_attribute sp.ppat_attributes in
13971391
let opath, record_ty = (
13981392
if has_dict_pattern_attr then (
1399-
(* [dict] If this is a dict pattern match we know we should force the record type
1400-
as the dict record type with a fresh type variable. This fixes so that dicts
1401-
can still be inferred properly from just pattern usage. Without this little
1402-
tweak, the inference would not work properly. *)
1393+
(* [dict] Make sure dict patterns are inferred as actual dicts *)
14031394
(Some (Predef.path_dict, Predef.path_dict), newgenty (Tconstr (Predef.path_dict, [newvar ()], ref Mnil)))
14041395
) else
14051396
try
@@ -3040,9 +3031,9 @@ and type_label_access env srecord lid =
30403031
| (p0, _, {type_attributes})
30413032
when Path.same p0 Predef.path_dict && Dict_type_helpers.has_dict_attribute type_attributes ->
30423033
(* [dict] Cover the case when trying to direct field access on a dict, e.g. `someDict.name`.
3043-
We need to disallow this because the fact that a dict is represented as a single field
3044-
record internally is just an implementation detail, and not intended to be exposed to
3045-
the user. *)
3034+
We need to disallow this because the fact that a dict is represented as a single magic
3035+
field record internally is just an implementation detail, and not intended to be exposed
3036+
to the user. *)
30463037
raise(Error(lid.loc, env, Field_access_on_dict_type))
30473038
| (p0, p, {type_kind=Type_record _}) -> Some(p0, p)
30483039
| _ -> None

jscomp/ml/types.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ type label_description =
303303
lbl_arg: type_expr; (* Type of the argument *)
304304
lbl_mut: mutable_flag; (* Is this a mutable field? *)
305305
lbl_pos: int; (* Position in block *)
306-
mutable lbl_all: label_description array; (* All the labels in this type *)
306+
mutable lbl_all: label_description array; (* All the labels in this type. This is mutable only because of a specific feature related to dicts, and should not be mutated elsewhere. *)
307307
lbl_repres: record_representation; (* Representation for this record *)
308308
lbl_private: private_flag; (* Read-only field? *)
309309
lbl_loc: Location.t;

jscomp/ml/types.mli

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,7 @@ type label_description =
449449
lbl_arg: type_expr; (* Type of the argument *)
450450
lbl_mut: mutable_flag; (* Is this a mutable field? *)
451451
lbl_pos: int; (* Position in block *)
452-
mutable lbl_all: label_description array; (* All the labels in this type *)
453-
lbl_repres: record_representation; (* Representation for this record *)
452+
mutable lbl_all: label_description array; (* All the labels in this type. This is mutable only because of a specific feature related to dicts, and should not be mutated elsewhere. *) lbl_repres: record_representation; (* Representation for this record *)
454453
lbl_private: private_flag; (* Read-only field? *)
455454
lbl_loc: Location.t;
456455
lbl_attributes: Parsetree.attributes;

0 commit comments

Comments
 (0)