Borrow two mutable values from the same HashMap

If you can change your datatypes and your function signature, you can use a RefCell to create interior mutability:

use std::cell::RefCell;
use std::collections::{HashMap, HashSet};

fn populate_connections(
    start: i32,
    num: i32,
    conns: &HashMap<i32, RefCell<HashSet<i32>>>,
    ancs: &mut HashSet<i32>,
) {
    let mut orig_conns = conns.get(&start).unwrap().borrow_mut();
    let pipes = conns.get(&num).unwrap().borrow();

    for pipe in pipes.iter() {
        if !ancs.contains(pipe) && !orig_conns.contains(pipe) {
            ancs.insert(*pipe);
            orig_conns.insert(*pipe);
            populate_connections(start, num, conns, ancs);
        }
    }
}

fn main() {}

Note that if start == num, the thread will panic because this is an attempt to have both mutable and immutable access to the same HashSet.

Safe alternatives to RefCell

Depending on your exact data and code needs, you can also use types like Cell or one of the atomics. These have lower memory overhead than a RefCell and only a small effect on codegen.

In multithreaded cases, you may wish to use a Mutex or RwLock.

Leave a Comment