HashMap: why can't get multiple mut borrows to different values?

Hi everybody!

The question is: why can’t you get multiple mutable references to DIFFERENT values ​​from a HashMap (code is below)?

Do I understand correctly that in this way the compiler prevents us from the phenomenon of mutable aliasing? Because it cannot statically guarantee that the resulting borrows point to different values?

Or simply protects us from multiple calls (with the same key) to methods that return mut borrow?

Or how, if we retrieve values using different keys, can we get the SAME value? How is it possible?

use std::collections::HashMap;
type PlayerID = i32;
#[derive(Debug, Default)]
struct Player {
    score: i32,
}
fn main() {
    let mut serv = HashMap::new();
    serv.insert(2, Player::default());
    let player_a = serv.get_mut(&32);
    let player_b = serv.get_mut(&32);
    dbg!(player_a, player_b);
}

On nightly there is get_many_mut to solve this problem.

3 Likes

In general, the compiler works on type-based logic.

Thus, if you ask for &mut a[1] and &mut a[4], all it sees is "oh, you asked for something with a usize", and it can't prove separability from that.

To get the compiler to understand it, you need to use something like different fields, which it does understand.

There are APIs in nightly being explored to allow this, though: https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.get_many_mut.

3 Likes

I also recommend reading this: Splitting Borrows - The Rustonomicon

It's even more basic than that for non-built-in indexing operations: IndexMut::index_mut requires an exclusive borrow of the entire collection.

2 Likes

Many thanks to everyone who responded! =)

I marked as a solution an answer that provides a link to a page that answers the question “why” the problem I described exists at all. This interested me more than possible ways to solve it.

Thank you!)

Aren't these two the same?

Yes, it's the same. This is what I wanted to find out. That these are all reflections of the same problem/limitation.