Skip to content

Commit

Permalink
builtin: fix m.clear() having different observable behavior to `m = {…
Browse files Browse the repository at this point in the history
…}`, after multiple iterations of setting keys and clearing (fix #22145) (#22146)
  • Loading branch information
spytheman authored Sep 1, 2024
1 parent fc31b44 commit 33f74cf
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
12 changes: 7 additions & 5 deletions vlib/builtin/map.v
Original file line number Diff line number Diff line change
Expand Up @@ -314,18 +314,20 @@ pub fn (mut m map) move() map {
// It does it by setting the map length to `0`
// Example: a.clear() // `a.len` and `a.key_values.len` is now 0
pub fn (mut m map) clear() {
m.len = 0
m.even_index = init_even_index
m.key_values.len = 0
m.key_values.deletes = 0
unsafe {
if m.key_values.all_deleted != 0 {
free(m.key_values.all_deleted)
m.key_values.all_deleted = nil
}
vmemset(m.key_values.keys, 0, m.key_values.key_bytes * m.key_values.cap)
vmemset(m.metas, 0, sizeof(u32) * (m.even_index + 2 + m.extra_metas))
vmemset(m.metas, 0, 2 * (m.even_index + 2 + m.extra_metas))
}
m.key_values.len = 0
m.key_values.deletes = 0
m.even_index = init_even_index
m.cached_hashbits = max_cached_hashbits
m.shift = init_log_capicity
m.len = 0
}

@[inline]
Expand Down
22 changes: 22 additions & 0 deletions vlib/builtin/map_issue_22145_clear_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const t = [30, 38, 36, 31, 39, 37, 24, 32, 25, 33, 18, 26, 11, 18, 12, 4, 10, 17, 16, 11, 3, 9,
2, 23, 30, 24, 16, 22, 23, 17, 9, 15, 10, 2, 8, 3, 1, 0, 7, 14, 29, 21]

fn test_multiple_iterations_of_calling_clear_should_be_always_equivalent_to_assigning_a_new_map() {
println('array t len: ${t.len}, t: ${t}')
mut clr := map[int]int{}
for i in 0 .. 0xFFFF {
mut new := map[int]int{}
clr.clear()
for e in t {
new[e] = e
clr[e] = e
assert new.len == clr.len // , 'mismatch found after setting element: $e, on iteration ${i}'
}
if i & 0x3FFF == 0 {
println('index ${i}')
println('>> map new: ${new.len} | ${new.keys().sorted()}')
println('>> map cleared: ${clr.len} | ${clr.keys().sorted()}')
}
assert new == clr // , 'mismatch found for iteration: ${i}'
}
}

0 comments on commit 33f74cf

Please sign in to comment.