From 6199af21afac5d62b31e52b88b2b9634ea420358 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Sat, 10 Oct 2026 18:50:18 +0000 Subject: [PATCH 1/3] Use the stdlib Hashtbl for the compiler's hash sets Hash sets are unit Hashtbl.Make tables; adds keep the first key. Sort hard dependencies by a total order so ties no longer depend on hash order. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Christoph Knittel --- CHANGELOG.md | 1 + compiler/core/js_fold_basic.ml | 2 +- compiler/core/js_fold_basic.mli | 2 +- compiler/core/lam_check.ml | 2 +- compiler/core/lam_coercion.ml | 3 +- compiler/core/lam_compile_env.ml | 9 +- compiler/core/lam_compile_env.mli | 2 +- compiler/core/lam_compile_main.ml | 19 ++- compiler/core/lam_dce.ml | 2 +- compiler/core/lam_module_ident.ml | 14 +- compiler/core/lam_module_ident.mli | 9 +- compiler/ext/hash_set.ml | 80 ---------- compiler/ext/hash_set.mli | 32 ---- compiler/ext/hash_set_gen.ml | 167 -------------------- compiler/ext/hash_set_ident.ml | 2 +- compiler/ext/hash_set_ident.mli | 2 +- compiler/ext/hash_set_string.ml | 2 +- compiler/ext/hash_set_string.mli | 2 +- compiler/ml/used_attributes.ml | 4 +- tests/ounit_tests/ounit_hash_set_tests.ml | 178 ---------------------- tests/ounit_tests/ounit_tests_main.ml | 1 - tests/tests/src/key_word_property.mjs | 8 +- 22 files changed, 57 insertions(+), 486 deletions(-) delete mode 100644 compiler/ext/hash_set.ml delete mode 100644 compiler/ext/hash_set.mli delete mode 100644 compiler/ext/hash_set_gen.ml delete mode 100644 tests/ounit_tests/ounit_hash_set_tests.ml diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e074708a5b..1a04d2bd130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ - Speed up dead code elimination of toplevel bindings in large modules. https://github.com/rescript-lang/rescript/pull/8773 - Make .cmt and .cmti files smaller by no longer embedding a copy of the .cmi. https://github.com/rescript-lang/rescript/pull/8774 - Use the OCaml standard library's hash tables in the compiler. https://github.com/rescript-lang/rescript/pull/8786 +- Use the OCaml standard library's hash tables for the compiler's hash sets, and always order the imports of a module used both with and without `default` the same way. https://github.com/rescript-lang/rescript/pull/PRNUM - Represent explicit expression braces as `Pexp_braces` in parsetree v1 and format `else` branches consistently with `if` branches. https://github.com/rescript-lang/rescript/pull/8678 - Omit redundant braces around multi-statement switch case bodies when formatting. https://github.com/rescript-lang/rescript/pull/8677 - Avoid running `rescript-schema-ppx` and `sury-ppx` on source files without an `@schema` annotation. https://github.com/rescript-lang/rescript/pull/8662 diff --git a/compiler/core/js_fold_basic.ml b/compiler/core/js_fold_basic.ml index 45e64dc4d0b..64a46621440 100644 --- a/compiler/core/js_fold_basic.ml +++ b/compiler/core/js_fold_basic.ml @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -let add_lam_module_ident = Lam_module_ident.Hash_set.add +let add_lam_module_ident = Lam_module_ident.set_add let create = Lam_module_ident.Hash_set.create diff --git a/compiler/core/js_fold_basic.mli b/compiler/core/js_fold_basic.mli index 5474c925b85..9606167a102 100644 --- a/compiler/core/js_fold_basic.mli +++ b/compiler/core/js_fold_basic.mli @@ -24,4 +24,4 @@ (** A module to calculate hard dependency based on JS IR in module [J] *) -val calculate_hard_dependencies : J.block -> Lam_module_ident.Hash_set.t +val calculate_hard_dependencies : J.block -> unit Lam_module_ident.Hash_set.t diff --git a/compiler/core/lam_check.ml b/compiler/core/lam_check.ml index f57f7a2312b..c78daddbb1a 100644 --- a/compiler/core/lam_check.ml +++ b/compiler/core/lam_check.ml @@ -43,7 +43,7 @@ let check ~file ~pass lam = "\n[SANITY after %s]:%s/%d bound twice in %s@." pass id.name id.stamp file; success := false) - else Hash_set_ident.add defined_variables id + else Hash_set_ident.add defined_variables id () in let rec check_list xs (cxt : Set_int.t) = Ext_list.iter xs (fun x -> check_staticfails x cxt) diff --git a/compiler/core/lam_coercion.ml b/compiler/core/lam_coercion.ml index 4b11e845ca2..f56a23f83db 100644 --- a/compiler/core/lam_coercion.ml +++ b/compiler/core/lam_coercion.ml @@ -94,8 +94,9 @@ let handle_exports (meta : Lam_stats.t) (lambda_exports : Lambda.t list) groups = []; } (fun (original_export_id : Ident.t) (lam : Lambda.t) (acc : t) -> let original_name = original_export_id.name in - if not @@ Hash_set_string.check_add tbl original_name then + if Hash_set_string.mem tbl original_name then Bs_exception.error (Bs_duplicate_exports original_name); + Hash_set_string.add tbl original_name (); match lam with | Lvar id -> if Ident.name id = original_name then diff --git a/compiler/core/lam_compile_env.ml b/compiler/core/lam_compile_env.ml index 86674956639..f4114cf7a13 100644 --- a/compiler/core/lam_compile_env.ml +++ b/compiler/core/lam_compile_env.ml @@ -128,7 +128,7 @@ let get_package_path_from_cmj (id : Lam_module_ident.t) : let cmj_table = cmj_load_info.cmj_table in (cmj_load_info.package_path, cmj_table.package_spec, cmj_table.case) -let add = Lam_module_ident.Hash_set.add +let add = Lam_module_ident.set_add (* Conservative interface *) let is_pure_module (oid : Lam_module_ident.t) = @@ -147,9 +147,10 @@ let is_pure_module (oid : Lam_module_ident.t) = | Some (External _) -> false) let populate_required_modules extras - (hard_dependencies : Lam_module_ident.Hash_set.t) = + (hard_dependencies : unit Lam_module_ident.Hash_set.t) = Lam_module_ident.Hash.iter (fun id _ -> if not (is_pure_module id) then add hard_dependencies id) cached_tbl; - Lam_module_ident.Hash_set.iter extras (fun id : unit -> - if not (is_pure_module id) then add hard_dependencies id) + Lam_module_ident.Hash_set.iter + (fun id () -> if not (is_pure_module id) then add hard_dependencies id) + extras diff --git a/compiler/core/lam_compile_env.mli b/compiler/core/lam_compile_env.mli index 3968e88133b..5fd7558b0d9 100644 --- a/compiler/core/lam_compile_env.mli +++ b/compiler/core/lam_compile_env.mli @@ -89,4 +89,4 @@ val get_package_path_from_cmj : [extra] maybe removed if it is pure and not in [hard_dependencies] *) val populate_required_modules : - Lam_module_ident.Hash_set.t -> Lam_module_ident.Hash_set.t -> unit + unit Lam_module_ident.Hash_set.t -> unit Lam_module_ident.Hash_set.t -> unit diff --git a/compiler/core/lam_compile_main.ml b/compiler/core/lam_compile_main.ml index 004f175f412..663e4b639dc 100644 --- a/compiler/core/lam_compile_main.ml +++ b/compiler/core/lam_compile_main.ml @@ -242,12 +242,12 @@ let js_hoisted_aliases (export_ids : Ident.t list) (** Actually simplify_lets is kind of global optimization since it requires you to know whether it's used or not *) -let required_modules (lam : Lambda.t) : Lam_module_ident.Hash_set.t = +let required_modules (lam : Lambda.t) : unit Lam_module_ident.Hash_set.t = let required = Lam_module_ident.Hash_set.create 0 in let rec collect (lam : Lambda.t) = (match lam with | Lglobal_module id -> - Lam_module_ident.Hash_set.add required (Lam_module_ident.of_ml id) + Lam_module_ident.set_add required (Lam_module_ident.of_ml id) | _ -> ()); Lambda_traverse.iter collect lam in @@ -407,11 +407,18 @@ let compile (output_prefix : string) export_idents hoisted (lam : Lambda.t) = else let hard_deps = Js_fold_basic.calculate_hard_dependencies program.block in Lam_compile_env.populate_required_modules may_required_modules hard_deps; - Ext_list.sort_via_array (Lam_module_ident.Hash_set.to_list hard_deps) + Ext_list.sort_via_array + (Lam_module_ident.Hash_set.fold + (fun id () acc -> id :: acc) + hard_deps []) (fun id1 id2 -> - Ext_string.compare - (Lam_module_ident.name id1) - (Lam_module_ident.name id2)) + match + Ext_string.compare + (Lam_module_ident.name id1) + (Lam_module_ident.name id2) + with + | 0 -> Lam_module_ident.compare_same_name id1 id2 + | c -> c) in Warnings.check_fatal (); let effect_ = diff --git a/compiler/core/lam_dce.ml b/compiler/core/lam_dce.ml index 47ecd47f722..d5f36bb9dc0 100644 --- a/compiler/core/lam_dce.ml +++ b/compiler/core/lam_dce.ml @@ -27,7 +27,7 @@ let transitive_closure (initial_idents : Ident.t list) let visited = Hash_set_ident.create 31 in let rec dfs (id : Ident.t) : unit = if not (Hash_set_ident.mem visited id || Ext_ident.is_js_or_global id) then ( - Hash_set_ident.add visited id; + Hash_set_ident.add visited id (); match Hash_ident.find_opt ident_freevars id with | None -> Ext_fmt.failwithf ~loc:__LOC__ "%s/%d not found" (Ident.name id) diff --git a/compiler/core/lam_module_ident.ml b/compiler/core/lam_module_ident.ml index 9da485441ef..f7cddb4385f 100644 --- a/compiler/core/lam_module_ident.ml +++ b/compiler/core/lam_module_ident.ml @@ -70,4 +70,16 @@ end module Hash = Hashtbl.Make (Cmp) -module Hash_set = Hash_set.Make (Cmp) +module Hash_set = Hash + +let set_add set id = if not (Hash_set.mem set id) then Hash_set.add set id () + +let compare_same_name (x : t) (y : t) = + let rank (x : t) = + match x.kind with + | Ml -> 0 + | Runtime -> 1 + | External {default = false} -> 2 + | External {default = true} -> 3 + in + compare (rank x) (rank y) diff --git a/compiler/core/lam_module_ident.mli b/compiler/core/lam_module_ident.mli index 79053421823..81dd13a81e2 100644 --- a/compiler/core/lam_module_ident.mli +++ b/compiler/core/lam_module_ident.mli @@ -38,4 +38,11 @@ val of_ml : ?dynamic_import:bool -> Ident.t -> t val of_runtime : Ident.t -> t module Hash : Hashtbl.S with type key = t -module Hash_set : Hash_set_gen.S with type key = t +module Hash_set = Hash + +val set_add : unit Hash_set.t -> t -> unit +(** Adds a module unless an equal one is present. The first key is kept since + it carries the id the module is bound to. *) + +val compare_same_name : t -> t -> int +(** Orders modules with the same [name]: by kind, then by [default] *) diff --git a/compiler/ext/hash_set.ml b/compiler/ext/hash_set.ml deleted file mode 100644 index 6947f58ed21..00000000000 --- a/compiler/ext/hash_set.ml +++ /dev/null @@ -1,80 +0,0 @@ -(* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -module Make (H : Hashtbl.HashedType) : Hash_set_gen.S with type key = H.t = -struct - type key = H.t - let eq_key = H.equal - let key_index (h : _ Hash_set_gen.t) key = - H.hash key land (Array.length h.data - 1) - type t = key Hash_set_gen.t - - let create = Hash_set_gen.create - let clear = Hash_set_gen.clear - let reset = Hash_set_gen.reset - - let iter = Hash_set_gen.iter - let fold = Hash_set_gen.fold - let length = Hash_set_gen.length - - let to_list = Hash_set_gen.to_list - - let remove (h : _ Hash_set_gen.t) key = - let i = key_index h key in - let h_data = h.data in - Hash_set_gen.remove_bucket h i key ~prec:Empty - (Array.unsafe_get h_data i) - eq_key - - let add (h : _ Hash_set_gen.t) key = - let i = key_index h key in - let h_data = h.data in - let old_bucket = Array.unsafe_get h_data i in - if not (Hash_set_gen.small_bucket_mem eq_key key old_bucket) then ( - Array.unsafe_set h_data i (Cons {key; next = old_bucket}); - h.size <- h.size + 1; - if h.size > Array.length h_data lsl 1 then Hash_set_gen.resize key_index h) - - let of_array arr = - let len = Array.length arr in - let tbl = create len in - for i = 0 to len - 1 do - add tbl (Array.unsafe_get arr i) - done; - tbl - - let check_add (h : _ Hash_set_gen.t) key : bool = - let i = key_index h key in - let h_data = h.data in - let old_bucket = Array.unsafe_get h_data i in - if not (Hash_set_gen.small_bucket_mem eq_key key old_bucket) then ( - Array.unsafe_set h_data i (Cons {key; next = old_bucket}); - h.size <- h.size + 1; - if h.size > Array.length h_data lsl 1 then Hash_set_gen.resize key_index h; - true) - else false - - let mem (h : _ Hash_set_gen.t) key = - Hash_set_gen.small_bucket_mem eq_key key - (Array.unsafe_get h.data (key_index h key)) -end diff --git a/compiler/ext/hash_set.mli b/compiler/ext/hash_set.mli deleted file mode 100644 index bd825433759..00000000000 --- a/compiler/ext/hash_set.mli +++ /dev/null @@ -1,32 +0,0 @@ -(* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -(** Ideas are based on {!Hash}, - however, {!Hash.add} does not really optimize and has a bad semantics for {!Hash_set}, - This module fixes the semantics of [add]. - [remove] is not optimized since it is not used too much -*) - -(** A naive t implementation on top of [hashtbl], the value is [unit]*) -module Make (H : Hashtbl.HashedType) : Hash_set_gen.S with type key = H.t diff --git a/compiler/ext/hash_set_gen.ml b/compiler/ext/hash_set_gen.ml deleted file mode 100644 index db892caf467..00000000000 --- a/compiler/ext/hash_set_gen.ml +++ /dev/null @@ -1,167 +0,0 @@ -(* Copyright (C) 2015-2016 Bloomberg Finance L.P. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * In addition to the permissions granted to you by the LGPL, you may combine - * or link a "work that uses the Library" with a publicly distributed version - * of this file to produce a combined library or application, then distribute - * that combined work under the terms of your choosing, with no requirement - * to comply with the obligations normally placed on you by section 4 of the - * LGPL version 3 (or the corresponding section of a later version of the LGPL - * should you choose to use a later version). - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) - -(* We do dynamic hashing, and resize the table and rehash the elements - when buckets become too long. *) - -type 'a bucket = Empty | Cons of {mutable key: 'a; mutable next: 'a bucket} - -type 'a t = { - mutable size: int; - (* number of entries *) - mutable data: 'a bucket array; - (* the buckets *) - initial_size: int; (* initial array size *) -} - -let create initial_size = - let s = Ext_util.power_2_above 16 initial_size in - {initial_size = s; size = 0; data = Array.make s Empty} - -let clear h = - h.size <- 0; - let len = Array.length h.data in - for i = 0 to len - 1 do - Array.unsafe_set h.data i Empty - done - -let reset h = - h.size <- 0; - h.data <- Array.make h.initial_size Empty - -let length h = h.size - -let resize indexfun h = - let odata = h.data in - let osize = Array.length odata in - let nsize = osize * 2 in - if nsize < Sys.max_array_length then ( - let ndata = Array.make nsize Empty in - let ndata_tail = Array.make nsize Empty in - h.data <- ndata; - (* so that indexfun sees the new bucket count *) - let rec insert_bucket = function - | Empty -> () - | Cons {key; next} as cell -> - let nidx = indexfun h key in - (match Array.unsafe_get ndata_tail nidx with - | Empty -> Array.unsafe_set ndata nidx cell - | Cons tail -> tail.next <- cell); - Array.unsafe_set ndata_tail nidx cell; - insert_bucket next - in - for i = 0 to osize - 1 do - insert_bucket (Array.unsafe_get odata i) - done; - for i = 0 to nsize - 1 do - match Array.unsafe_get ndata_tail i with - | Empty -> () - | Cons tail -> tail.next <- Empty - done) - -let iter h f = - let rec do_bucket = function - | Empty -> () - | Cons l -> - f l.key; - do_bucket l.next - in - let d = h.data in - for i = 0 to Array.length d - 1 do - do_bucket (Array.unsafe_get d i) - done - -let fold h init f = - let rec do_bucket b accu = - match b with - | Empty -> accu - | Cons l -> do_bucket l.next (f l.key accu) - in - let d = h.data in - let accu = ref init in - for i = 0 to Array.length d - 1 do - accu := do_bucket (Array.unsafe_get d i) !accu - done; - !accu - -let to_list set = fold set [] List.cons - -let rec small_bucket_mem eq key lst = - match lst with - | Empty -> false - | Cons lst -> ( - eq key lst.key - || - match lst.next with - | Empty -> false - | Cons lst -> ( - eq key lst.key - || - match lst.next with - | Empty -> false - | Cons lst -> eq key lst.key || small_bucket_mem eq key lst.next)) - -let rec remove_bucket (h : _ t) (i : int) key ~(prec : _ bucket) - (buck : _ bucket) eq_key = - match buck with - | Empty -> () - | Cons {key = k; next} -> - if eq_key k key then ( - h.size <- h.size - 1; - match prec with - | Empty -> Array.unsafe_set h.data i next - | Cons c -> c.next <- next) - else remove_bucket h i key ~prec:buck next eq_key - -module type S = sig - type key - - type t - - val create : int -> t - - val clear : t -> unit - - val reset : t -> unit - - (* val copy: t -> t *) - val remove : t -> key -> unit - - val add : t -> key -> unit - - val of_array : key array -> t - - val check_add : t -> key -> bool - - val mem : t -> key -> bool - - val iter : t -> (key -> unit) -> unit - - val fold : t -> 'b -> (key -> 'b -> 'b) -> 'b - - val length : t -> int - - (* val stats: t -> Hashtbl.statistics *) - val to_list : t -> key list -end diff --git a/compiler/ext/hash_set_ident.ml b/compiler/ext/hash_set_ident.ml index 20b87a084c0..da3e15e2301 100644 --- a/compiler/ext/hash_set_ident.ml +++ b/compiler/ext/hash_set_ident.ml @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -include Hash_set.Make (struct +include Hashtbl.Make (struct type t = Ident.t let equal = Ext_ident.equal diff --git a/compiler/ext/hash_set_ident.mli b/compiler/ext/hash_set_ident.mli index b32ba8aec4e..f30278fbcbd 100644 --- a/compiler/ext/hash_set_ident.mli +++ b/compiler/ext/hash_set_ident.mli @@ -22,4 +22,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -include Hash_set_gen.S with type key = Ident.t +include Hashtbl.S with type key = Ident.t diff --git a/compiler/ext/hash_set_string.ml b/compiler/ext/hash_set_string.ml index 71df8f0499d..47faa868af0 100644 --- a/compiler/ext/hash_set_string.ml +++ b/compiler/ext/hash_set_string.ml @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -include Hash_set.Make (struct +include Hashtbl.Make (struct type t = string let equal = Ext_string.equal diff --git a/compiler/ext/hash_set_string.mli b/compiler/ext/hash_set_string.mli index 0050b66dc19..882e5dfa95a 100644 --- a/compiler/ext/hash_set_string.mli +++ b/compiler/ext/hash_set_string.mli @@ -22,4 +22,4 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *) -include Hash_set_gen.S with type key = string +include Hashtbl.S with type key = string diff --git a/compiler/ml/used_attributes.ml b/compiler/ml/used_attributes.ml index 5fa4bfba80e..9c159cbce0e 100644 --- a/compiler/ml/used_attributes.ml +++ b/compiler/ml/used_attributes.ml @@ -1,4 +1,4 @@ -module Attribute_name_set = Hash_set.Make (struct +module Attribute_name_set = Hashtbl.Make (struct type t = string Asttypes.loc let equal = ( = ) @@ -9,7 +9,7 @@ let used_attributes = Attribute_name_set.create 16 (* only mark non-ghost used bs attribute *) let mark_used_attribute ((x, _) : Parsetree.attribute) = - if not x.loc.loc_ghost then Attribute_name_set.add used_attributes x + if not x.loc.loc_ghost then Attribute_name_set.replace used_attributes x () let is_used_attribute (sloc : string Asttypes.loc) = Attribute_name_set.mem used_attributes sloc diff --git a/tests/ounit_tests/ounit_hash_set_tests.ml b/tests/ounit_tests/ounit_hash_set_tests.ml deleted file mode 100644 index a91e5508054..00000000000 --- a/tests/ounit_tests/ounit_hash_set_tests.ml +++ /dev/null @@ -1,178 +0,0 @@ -let ( >:: ), ( >::: ) = OUnit.(( >:: ), ( >::: )) - -let ( =~ ) = OUnit.assert_equal - -type id = {name: string; stamp: int} - -module Id_hash_set = Hash_set.Make (struct - type t = id - let equal x y = x.stamp = y.stamp && x.name = y.name - let hash x = Hashtbl.hash x.stamp -end) - -let const_tbl = - [| - "0"; - "1"; - "2"; - "3"; - "4"; - "5"; - "6"; - "7"; - "8"; - "9"; - "10"; - "100"; - "99"; - "98"; - "97"; - "96"; - "95"; - "94"; - "93"; - "92"; - "91"; - "90"; - "89"; - "88"; - "87"; - "86"; - "85"; - "84"; - "83"; - "82"; - "81"; - "80"; - "79"; - "78"; - "77"; - "76"; - "75"; - "74"; - "73"; - "72"; - "71"; - "70"; - "69"; - "68"; - "67"; - "66"; - "65"; - "64"; - "63"; - "62"; - "61"; - "60"; - "59"; - "58"; - "57"; - "56"; - "55"; - "54"; - "53"; - "52"; - "51"; - "50"; - "49"; - "48"; - "47"; - "46"; - "45"; - "44"; - "43"; - "42"; - "41"; - "40"; - "39"; - "38"; - "37"; - "36"; - "35"; - "34"; - "33"; - "32"; - "31"; - "30"; - "29"; - "28"; - "27"; - "26"; - "25"; - "24"; - "23"; - "22"; - "21"; - "20"; - "19"; - "18"; - "17"; - "16"; - "15"; - "14"; - "13"; - "12"; - "11"; - |] -let suites = - __FILE__ - >::: [ - ( __LOC__ >:: fun _ -> - let v = Id_hash_set.create 30 in - for i = 0 to 2_000 do - Id_hash_set.add v {name = "x"; stamp = i} - done; - for i = 0 to 2_000 do - Id_hash_set.add v {name = "x"; stamp = i} - done; - for i = 0 to 2_000 do - assert (Id_hash_set.mem v {name = "x"; stamp = i}) - done; - OUnit.assert_equal (Id_hash_set.length v) 2_001; - for i = 1990 to 3_000 do - Id_hash_set.remove v {name = "x"; stamp = i} - done; - OUnit.assert_equal (Id_hash_set.length v) 1990; - for i = 1000 to 3990 do - Id_hash_set.remove v {name = "x"; stamp = i} - done; - OUnit.assert_equal (Id_hash_set.length v) 1000; - for i = 1000 to 1100 do - Id_hash_set.add v {name = "x"; stamp = i} - done; - OUnit.assert_equal (Id_hash_set.length v) 1101; - for i = 0 to 1100 do - OUnit.assert_bool "exist" - (Id_hash_set.mem v {name = "x"; stamp = i}) - done ); - ( __LOC__ >:: fun _ -> - let duplicate arr = - let len = Array.length arr in - let rec aux tbl off = - if off >= len then None - else - let curr = Array.unsafe_get arr off in - if Hash_set_string.check_add tbl curr then aux tbl (off + 1) - else Some curr - in - aux (Hash_set_string.create len) 0 - in - let v = [|"if"; "a"; "b"; "c"|] in - OUnit.assert_equal (duplicate v) None; - OUnit.assert_equal - (duplicate [|"if"; "a"; "b"; "b"; "c"|]) - (Some "b") ); - ( __LOC__ >:: fun _ -> - let of_array lst = - let len = Array.length lst in - let tbl = Hash_set_string.create len in - lst |> Array.iter (Hash_set_string.add tbl); - tbl - in - let hash = of_array const_tbl in - let len = Hash_set_string.length hash in - Hash_set_string.remove hash "x"; - OUnit.assert_equal len (Hash_set_string.length hash); - Hash_set_string.remove hash "0"; - OUnit.assert_equal (len - 1) (Hash_set_string.length hash) ); - ] diff --git a/tests/ounit_tests/ounit_tests_main.ml b/tests/ounit_tests/ounit_tests_main.ml index 084313bd55d..c8881d80d39 100644 --- a/tests/ounit_tests/ounit_tests_main.ml +++ b/tests/ounit_tests/ounit_tests_main.ml @@ -5,7 +5,6 @@ let suites = Ounit_json_tests.suites; Ounit_scc_tests.suites; Ounit_list_test.suites; - Ounit_hash_set_tests.suites; Ounit_bal_tree_tests.suites; Ounit_hash_stubs_test.suites; Ounit_map_tests.suites; diff --git a/tests/tests/src/key_word_property.mjs b/tests/tests/src/key_word_property.mjs index 26e224057d8..73af9a88313 100644 --- a/tests/tests/src/key_word_property.mjs +++ b/tests/tests/src/key_word_property.mjs @@ -3,16 +3,16 @@ import * as Vscode from "vscode"; import * as SomeEs6Module from "some-es6-module"; import SomeEs6Module$1 from "some-es6-module"; -import OmeEs6Module from "./ome-es6-module"; -import * as OmeEs6Module$1 from "./ome-es6-module"; +import * as OmeEs6Module from "./ome-es6-module"; +import OmeEs6Module$1 from "./ome-es6-module"; let $$default = SomeEs6Module$1; let default2 = SomeEs6Module.default2; -let oefault = OmeEs6Module; +let oefault = OmeEs6Module$1; -let oefault2 = OmeEs6Module$1.default2; +let oefault2 = OmeEs6Module.default2; let window = Vscode.window; From 92a1e0cf2f4b0882ab42ea60896b3a2b0c4ae5d7 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Sat, 10 Oct 2026 18:50:40 +0000 Subject: [PATCH 2/3] Add PR link to CHANGELOG Co-Authored-By: Claude Opus 5.5 Signed-off-by: Christoph Knittel --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a04d2bd130..f5625ad66a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ - Speed up dead code elimination of toplevel bindings in large modules. https://github.com/rescript-lang/rescript/pull/8773 - Make .cmt and .cmti files smaller by no longer embedding a copy of the .cmi. https://github.com/rescript-lang/rescript/pull/8774 - Use the OCaml standard library's hash tables in the compiler. https://github.com/rescript-lang/rescript/pull/8786 -- Use the OCaml standard library's hash tables for the compiler's hash sets, and always order the imports of a module used both with and without `default` the same way. https://github.com/rescript-lang/rescript/pull/PRNUM +- Use the OCaml standard library's hash tables for the compiler's hash sets, and always order the imports of a module used both with and without `default` the same way. https://github.com/rescript-lang/rescript/pull/8787 - Represent explicit expression braces as `Pexp_braces` in parsetree v1 and format `else` branches consistently with `if` branches. https://github.com/rescript-lang/rescript/pull/8678 - Omit redundant braces around multi-statement switch case bodies when formatting. https://github.com/rescript-lang/rescript/pull/8677 - Avoid running `rescript-schema-ppx` and `sury-ppx` on source files without an `@schema` annotation. https://github.com/rescript-lang/rescript/pull/8662 From 9b8ce57768d3cf4ee1a26e190c20738eccb154d4 Mon Sep 17 00:00:00 2001 From: Christoph Knittel Date: Sat, 10 Oct 2026 19:13:36 +0000 Subject: [PATCH 3/3] Update gentype example outputs for the new import order Co-Authored-By: Claude Opus 5.5 Signed-off-by: Christoph Knittel --- .../src/ImportHookDefault.res.js | 8 ++--- .../src/ImportJsValue.res.js | 32 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js b/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js index 8b5cb1e4641..d3b91414d77 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js +++ b/tests/gentype_tests/typescript-react-example/src/ImportHookDefault.res.js @@ -1,11 +1,11 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import ImportHookDefaultGen from "./ImportHookDefault.gen"; -import * as ImportHookDefaultGen$1 from "./ImportHookDefault.gen"; +import * as ImportHookDefaultGen from "./ImportHookDefault.gen"; +import ImportHookDefaultGen$1 from "./ImportHookDefault.gen"; -let make = ImportHookDefaultGen$1.make; +let make = ImportHookDefaultGen.make; -let make2 = ImportHookDefaultGen; +let make2 = ImportHookDefaultGen$1; let MM = { make2: make2 diff --git a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js index 8a66e36eb2c..c31daa8a0c4 100644 --- a/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js +++ b/tests/gentype_tests/typescript-react-example/src/ImportJsValue.res.js @@ -1,27 +1,27 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import ImportJsValueGen from "./ImportJsValue.gen"; -import * as ImportJsValueGen$1 from "./ImportJsValue.gen"; +import * as ImportJsValueGen from "./ImportJsValue.gen"; +import ImportJsValueGen$1 from "./ImportJsValue.gen"; function round(prim) { - return ImportJsValueGen$1.round(prim); + return ImportJsValueGen.round(prim); } function round2(prim) { - return ImportJsValueGen$1.round2(prim); + return ImportJsValueGen.round2(prim); } function area(prim) { - return ImportJsValueGen$1.area(prim); + return ImportJsValueGen.area(prim); } function returnMixedArray(prim) { - return ImportJsValueGen$1.returnMixedArray(); + return ImportJsValueGen.returnMixedArray(); } -let roundedNumber = ImportJsValueGen$1.round(1.8); +let roundedNumber = ImportJsValueGen.round(1.8); -let areaValue = ImportJsValueGen$1.area({ +let areaValue = ImportJsValueGen.area({ x: 3, y: undefined }); @@ -44,11 +44,11 @@ function useGetAbs(x) { } function useColor(prim) { - return ImportJsValueGen$1.useColor(prim); + return ImportJsValueGen.useColor(prim); } function useEscapedInlineVariant(prim) { - return ImportJsValueGen$1.useEscapedInlineVariant((() => { + return ImportJsValueGen.useEscapedInlineVariant((() => { switch (prim) { case "illegalName" : return "Illegal\"Name"; @@ -57,7 +57,7 @@ function useEscapedInlineVariant(prim) { } function useUtf8InlineVariant(prim) { - return ImportJsValueGen$1.useUtf8InlineVariant((() => { + return ImportJsValueGen.useUtf8InlineVariant((() => { switch (prim) { case "utf8" : return "café\npath\\name"; @@ -66,20 +66,20 @@ function useUtf8InlineVariant(prim) { } function higherOrder(prim) { - return ImportJsValueGen$1.higherOrder(prim); + return ImportJsValueGen.higherOrder(prim); } -let returnedFromHigherOrder = ImportJsValueGen$1.higherOrder((prim0, prim1) => prim0 + prim1 | 0); +let returnedFromHigherOrder = ImportJsValueGen.higherOrder((prim0, prim1) => prim0 + prim1 | 0); function convertVariant(prim) { - return ImportJsValueGen$1.convertVariant(prim); + return ImportJsValueGen.convertVariant(prim); } function polymorphic(prim) { - return ImportJsValueGen$1.polymorphic(prim); + return ImportJsValueGen.polymorphic(prim); } -let $$default = ImportJsValueGen; +let $$default = ImportJsValueGen$1; export { round,