From 682f0f584f0af96d79f27cfb191835eae7ece2ed Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 19 Dec 2024 19:31:01 -0600 Subject: [PATCH] freeze with mutable keys should be determinsic help address #1535 --- src/boot/boot.janet | 20 ++++++++++++-------- test/suite-boot.janet | 11 +++++++++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index dc16fec40..78c009f26 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -2224,14 +2224,18 @@ child values also immutable. Closures, fibers, and abstract types will not be recursively frozen, but all other types will.` [x] - (case (type x) - :array (tuple/slice (map freeze x)) - :tuple (tuple/slice (map freeze x)) - :table (if-let [p (table/getproto x)] - (freeze (merge (table/clone p) x)) - (struct ;(map freeze (kvs x)))) - :struct (struct ;(map freeze (kvs x))) - :buffer (string x) + (def tx (type x)) + (cond + (or (= tx :array) (= tx :tuple)) + (tuple/slice (map freeze x)) + + (or (= tx :table) (= tx :struct)) + (let [sorted-kvs (array/join @[] ;(sort (map freeze (pairs x))))] + (struct/with-proto (freeze (getproto x)) ;sorted-kvs)) + + (= tx :buffer) + (string x) + x)) (defn thaw diff --git a/test/suite-boot.janet b/test/suite-boot.janet index d77611a67..045f03688 100644 --- a/test/suite-boot.janet +++ b/test/suite-boot.janet @@ -896,11 +896,18 @@ (struct/with-proto {:a [1 2 3]} :c 22 :b [1 2 3 4] :d "test" :e "test2")) (table/setproto table-to-freeze @{:a @[1 2 3]}) -(assert (deep= {:a [1 2 3] :b [1 2 3 4] :c 22 :d "test" :e "test2"} - (freeze table-to-freeze))) +(assert (deep= struct-to-thaw (freeze table-to-freeze))) (assert (deep= table-to-freeze-with-inline-proto (thaw table-to-freeze))) (assert (deep= table-to-freeze-with-inline-proto (thaw struct-to-thaw))) +# Check that freezing mutable keys is deterministic +# for issue #1535 +(def hashes @{}) +(repeat 200 + (def x (freeze {@"" 1 @"" 2 @"" 3 @"" 4 @"" 5})) + (put hashes (hash x) true)) +(assert (= 1 (length hashes)) "freeze mutable keys is deterministic") + # Make sure Carriage Returns don't end up in doc strings # e528b86 (assert (not (string/find "\r"