Skip to content

Commit 12465f3

Browse files
MozirDmitriyTomAFrenchjfecher
authored
fix: Sync len after map rebuilds in iter_mut/iter_keys_mut for HashMap and UHashMap (#9491)
Co-authored-by: Tom French <[email protected]> Co-authored-by: Jake Fecher <[email protected]>
1 parent 4c65b51 commit 12465f3

16 files changed

+96
-39
lines changed

noir_stdlib/src/collections/map.nr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ impl<K, V, let N: u32, B> HashMap<K, V, N, B> {
319319
}
320320

321321
self._table = new_map._table;
322+
self._len = new_map._len;
322323
}
323324

324325
/// Iterates through the HashMap, mutating each key to the result returned from
@@ -356,6 +357,7 @@ impl<K, V, let N: u32, B> HashMap<K, V, N, B> {
356357
}
357358

358359
self._table = new_map._table;
360+
self._len = new_map._len;
359361
}
360362

361363
/// Iterates through the HashMap, applying the given function to each value and mutating the

noir_stdlib/src/collections/umap.nr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ impl<K, V, B> UHashMap<K, V, B> {
210210
}
211211

212212
self._table = new_map._table;
213+
self._len = new_map._len;
213214
}
214215

215216
// For each key applies mutator function.
@@ -229,6 +230,7 @@ impl<K, V, B> UHashMap<K, V, B> {
229230
}
230231

231232
self._table = new_map._table;
233+
self._len = new_map._len;
232234
}
233235

234236
// For each value applies mutator function.

test_programs/execution_success/hashmap/src/main.nr

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fn main(input: [Entry; HASHMAP_LEN]) {
3636
test_retain();
3737
test_iterators();
3838
test_mut_iterators();
39+
test_iter_len_shrink_on_key_collision();
3940

4041
doc_tests();
4142
}
@@ -199,6 +200,29 @@ fn test_mut_iterators() {
199200
assert(entries == [(12, 30), (30, 70), (66, 130)], "Got incorrect iteration of entries.");
200201
}
201202

203+
// Ensure that mutating keys to collide shrinks the length and keeps iterator invariants intact.
204+
fn test_iter_len_shrink_on_key_collision() {
205+
let mut hashmap = ALLOCATE_HASHMAP();
206+
207+
hashmap.insert(1, 10);
208+
hashmap.insert(2, 20);
209+
hashmap.insert(3, 30);
210+
211+
// Mutate all keys to the same value to force collisions.
212+
hashmap.iter_keys_mut(|_k: K| -> K { 0 });
213+
214+
assert_eq(
215+
hashmap.len(),
216+
1,
217+
"HashMap length should shrink to 1 after key collisions during iter_keys_mut.",
218+
);
219+
220+
// These calls will assert internally if _len is not synchronized with the table.
221+
let _ = hashmap.entries();
222+
let _ = hashmap.keys();
223+
let _ = hashmap.values();
224+
}
225+
202226
// docs:start:type_alias
203227
type MyMap = HashMap<u8, u32, 10, BuildHasherDefault<Poseidon2Hasher>>;
204228
// docs:end:type_alias

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__expanded.snap

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__force_brillig_false_inliner_-9223372036854775808.snap

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__force_brillig_false_inliner_0.snap

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__force_brillig_false_inliner_9223372036854775807.snap

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__force_brillig_true_inliner_-9223372036854775808.snap

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__force_brillig_true_inliner_0.snap

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tooling/nargo_cli/tests/snapshots/execution_success/hashmap/execute__tests__force_brillig_true_inliner_9223372036854775807.snap

Lines changed: 8 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)