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
.