Hi everyone!
I am trying to implement a Python-style dict in Rust. More information about the idea can be found here: https://softwaremaniacs.org/blog/2020/02/05/dicts-ordered/en/
I thought of using hashbrown's RawTable to store indices into a Vec
of (Key, Value)
tuples. While writing the insert function I ran into an ownership problem that I need help with. The code looks like this:
pub struct OrderedHashMap<K, V, S = DefaultHashBuilder> {
hash_builder: S,
table: RawTable<usize>,
entries: Vec<(K, V)>,
}
pub fn insert(&mut self, k: K, v: V) -> Option<V> {
unsafe {
let hash = make_hash(&self.hash_builder, &k);
if let Some(item) = self.table.find(hash, |x| k.eq(&self.entries[*x].0)) {
Some(std::mem::replace(&mut self.entries[item.read()].1, v))
} else {
// Insert (k,v) into dense entries vec.
self.entries.push((k, v));
let index = self.entries.len() - 1;
// Insert index into hash map.
let hash_builder = &self.hash_builder;
let hasher = |x: &usize| make_hash(hash_builder, &self.entries[*x].0);
self.table.insert(hash, index, hasher);
None
}
}
This does not compile with the following error message:
let hasher = |x: &usize| make_hash(hash_builder, &self.entries[*x].0);
----------- ---- first borrow occurs due to use of `self` in closure
|
immutable borrow occurs here
self.table.insert(hash, index, hasher);
^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^
| |
| immutable borrow later used by call
mutable borrow occurs here
The table
needs to be able to index into entries
in order to rehash all the keys when it sees fit. How can I work around the Rust ownership system to accomplish that?