Hi there,
I'm writing some logic involving insert two value to a HashMap with two different keys, and return two immutable references to these inserted value stored in the HashMap.
However, the problem is that for each key, we performed two hashmap queries actually (1 for insert and 1 for get). Although an additional query is tolerable in my current work, I'm just wondering if it's possible to save this additional query. Using Entry API is obviously non-applicable, because HashMap::entry requires a mutable borrow to self, and return reference get via entry would extend the lifetime of the mutable self borrow, and the final result is that we are trying to create two mutable borrows to a HashMap at the same time which would be rejected by the borrow checker. Besides, runtime interior mutability like RefCell seems not work here.
I understand that Rust HashMap use quadratic probing instead of linked list buckets to handle hash conflicts and so insert a value might trigger rehashing, so even I hold an immutable reference to the first inserted value, the second insertion might invalidating the former reference, and that's why such operation is not allowed by borrow checker via single mutable reference rule. But if avoiding the additional query really matters, can we only write a HashMap by ourselves or if there is any crate implemented such functionality?
The Rust hash map uses hashbrown for its implementation. The hashbrown crate provides some additional functionality, though I'm not sure if it has what you're looking for.
Make your first insertion and take the resultant first & reference, convert it to a *const raw pointer, and store it in a variable.
Make your second insertion and store the resultant second & reference in a variable.
Somehow do some sort of run-time check that makes sure that the second insertion wouldn't have changed the memory location of the first value such as by re-hashing or whatever.
Use an unsafe block to convert your *const raw pointer back to a & reference.
This obviously relies on implementation details of HashMap and triggers UB if 3 goes wrong, but may be the easiest way to do the thing closest to what you're trying to do.
However, I would probably just use an IndexMap, or a custom structure, or perhaps even a fork of hashbrown instead.