diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index c60cd8f35..8284f021e 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -700,7 +700,7 @@ macro uint hash_array(array_ptr) @local *> macro uint hash_vec(vec) @local { - var $len = $sizeof(vec.len * $typeof(vec).inner.sizeof); + var $len = $sizeof(vec); $if $len > 16: return (uint)komi::hash(((char*)&&vec)[:$len]); diff --git a/releasenotes.md b/releasenotes.md index 979dc9237..e7da7d712 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -58,6 +58,7 @@ - Creating recursive debug info for functions could cause assertions. - bitorder::read and bitorder::write may fail because of unaligned access #2734. - Fix `LinkedList.to_format` to properly iterate linked list for printing. +- Hashing a vector would not use the entire vector in some cases. ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/test/unit/stdlib/core/builtintests.c3 b/test/unit/stdlib/core/builtintests.c3 index 601843aaa..56546ed63 100644 --- a/test/unit/stdlib/core/builtintests.c3 +++ b/test/unit/stdlib/core/builtintests.c3 @@ -174,6 +174,63 @@ fn void test_hash_repeat() assert(int.typeid.hash() == int.typeid.hash()); } +macro test_hash_vector_macro(...) +{ + int[] $lens = {1, 2, 4, 7, 8, 13, 16, 23, 32, 43, 64, 103}; + $for var $i = 0; $i < $vacount ; $i++: + { + $foreach $vec_len : $lens: + { + $if $vec_len * $vatype[$i].sizeof * 8 <= $$MAX_VECTOR_SIZE: + { + $vatype[$i][<$vec_len>] vec1, vec2; + for (int val = 0; val < $vec_len; val++) + { + $vatype[$i] tval = ($vatype[$i])val; + vec1[val] = (tval | (tval << (($vatype[$i].sizeof - 1) * 8))); + } + vec2 = vec1; + assert(vec1.hash() == vec2.hash(), "hashes don't match for %s and %s", vec1, vec2); + for (int val = 0; val < $vec_len; val++) + { + vec2[val] ^= (($vatype[$i])0b0010_0000 << (($vatype[$i].sizeof - 1) * 8)); + assert(vec1.hash() != vec2.hash(), "hashes match for %s and %s", vec1, vec2); + vec2[val] ^= (($vatype[$i])0b0010_0000 << (($vatype[$i].sizeof - 1) * 8)); + } + } + $endif + } + $endforeach + } + $endfor +} +macro test_hash_vector_macro_bool() +{ + int[] $lens = {1, 2, 4, 7, 8, 13, 16, 23, 32, 43, 64, 103}; + $foreach $vec_len : $lens: + { + bool[<$vec_len>] vec1, vec2; + for (int val = 0; val < $vec_len; val++) + { + vec1[val] = ((val & 0x3) == 0); + } + vec2 = vec1; + assert(vec1.hash() == vec2.hash(), "hashes don't match for %s and %s", vec1, vec2); + for (int val = 0; val < $vec_len; val++) + { + vec2[val] = !vec2[val]; + assert(vec1.hash() != vec2.hash(), "hashes match for %s and %s", vec1, vec2); + vec2[val] = !vec2[val]; + } + } + $endforeach +} +fn void test_hash_vector() +{ + test_hash_vector_macro(char, ichar, short, ushort, int, uint, long, ulong, int128, uint128); + test_hash_vector_macro_bool(); +} + fn void test_builtin_string_hashing() => @pool() { var $x = "";