Fix dict equality: structural eq for plain dicts, Integer/Number in equal?
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 44s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 44s
Two related kernel bugs were causing the HS conformance test
"arrays containing objects work" to fail with the misleading message
"Expected ({:a 1} {:b 2}) but got ({:a 1} {:b 2})".
1. sx_primitives.ml safe_eq: Dict/Dict only returned true for DOM-wrapped
dicts (those carrying __host_handle); all other dict pairs returned
false unconditionally. Plain dict literals can never have been =
to each other. Add the structural-equality fallback: when neither
side has a host handle, compare lengths and walk keys.
2. sx_browser.ml deep_equal (the kernel binding for equal?): had a
Number/Number branch but no Integer/Integer or cross-Integer/Number
branches, so since the numeric tower change Integer 1 vs Integer 1
was falling through to the catch-all and returning false. Mirror the
cases from run_tests.ml deep_equal which already had them.
Verified via direct kernel probe:
(= {:a 1} {:a 1}) => true (was false)
(= {:a 1 :b 2} {:b 2 :a 1}) => true (was false)
(equal? 1 1) => true (was false)
(equal? {:a 1} {:a 1}) => true (was false)
(equal? (list {:a 1}) (list {:a 1})) => true (was false)
HS suite arrayLiteral: 7/8 → 8/8.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -665,7 +665,11 @@ let () =
|
|||||||
let rec deep_equal a b =
|
let rec deep_equal a b =
|
||||||
match a, b with
|
match a, b with
|
||||||
| Nil, Nil -> true | Bool a, Bool b -> a = b
|
| Nil, Nil -> true | Bool a, Bool b -> a = b
|
||||||
| Number a, Number b -> a = b | String a, String b -> a = b
|
| Integer a, Integer b -> a = b
|
||||||
|
| Number a, Number b -> a = b
|
||||||
|
| Integer a, Number b -> float_of_int a = b
|
||||||
|
| Number a, Integer b -> a = float_of_int b
|
||||||
|
| String a, String b -> a = b
|
||||||
| Symbol a, Symbol b -> a = b | Keyword a, Keyword b -> a = b
|
| Symbol a, Symbol b -> a = b | Keyword a, Keyword b -> a = b
|
||||||
| (List a | ListRef { contents = a }), (List b | ListRef { contents = b }) ->
|
| (List a | ListRef { contents = a }), (List b | ListRef { contents = b }) ->
|
||||||
List.length a = List.length b && List.for_all2 deep_equal a b
|
List.length a = List.length b && List.for_all2 deep_equal a b
|
||||||
|
|||||||
@@ -582,11 +582,22 @@ let () =
|
|||||||
(List lb | ListRef { contents = lb }) ->
|
(List lb | ListRef { contents = lb }) ->
|
||||||
List.length la = List.length lb &&
|
List.length la = List.length lb &&
|
||||||
List.for_all2 safe_eq la lb
|
List.for_all2 safe_eq la lb
|
||||||
(* Dict: check __host_handle for DOM node identity *)
|
(* Dict: __host_handle identity for DOM-wrapped dicts; otherwise
|
||||||
|
structural equality over keys + values. *)
|
||||||
| Dict a, Dict b ->
|
| Dict a, Dict b ->
|
||||||
(match Hashtbl.find_opt a "__host_handle", Hashtbl.find_opt b "__host_handle" with
|
(match Hashtbl.find_opt a "__host_handle", Hashtbl.find_opt b "__host_handle" with
|
||||||
| Some (Number ha), Some (Number hb) -> ha = hb
|
| Some (Number ha), Some (Number hb) -> ha = hb
|
||||||
| _ -> false)
|
| Some _, _ | _, Some _ -> false
|
||||||
|
| None, None ->
|
||||||
|
Hashtbl.length a = Hashtbl.length b &&
|
||||||
|
(let eq = ref true in
|
||||||
|
Hashtbl.iter (fun k v ->
|
||||||
|
if !eq then
|
||||||
|
match Hashtbl.find_opt b k with
|
||||||
|
| Some v' -> if not (safe_eq v v') then eq := false
|
||||||
|
| None -> eq := false
|
||||||
|
) a;
|
||||||
|
!eq))
|
||||||
(* Records: same type + structurally equal fields *)
|
(* Records: same type + structurally equal fields *)
|
||||||
| Record a, Record b ->
|
| Record a, Record b ->
|
||||||
a.r_type.rt_uid = b.r_type.rt_uid &&
|
a.r_type.rt_uid = b.r_type.rt_uid &&
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user