0

I have a function that gets a mutable reference from a HashMap using two possible keys, using the second only only if the first is not present. This is most concisely expressed as:

fn get_a<T>(map: &mut HashMap<usize, T>) -> Option<&mut T> {
  map.get_mut(&1).or_else(|| map.get_mut(&2))
}

This fails with closure requires unique access to *map but it is already borrowed. Understandable, as lifetimes and closures can get fiddly.

But expressed very verbosely without combinators this still fails.

fn get_b<T>(map: &mut HashMap<usize, T>) -> Option<&mut T> {
  let one = map.get_mut(&1);
  if let Some(one) = one {
    return Some(one);
  }
  drop(one);

  if let Some(two) = map.get_mut(&2) {
    Some(two)
  }
  else {
    None
  }
}
error[E0499]: cannot borrow `*map` as mutable more than once at a time
    |
94  | fn get_b<T>(map: &mut HashMap<usize, T>) -> Option<&mut T> {
    |                - let's call the lifetime of this reference `'1`
95  |   let one = map.get_mut(&1);
    |             --------------- first mutable borrow occurs here
96  |   if let Some(one) = one {
97  |     return Some(one);
    |            --------- returning this value requires that `*map` is borrowed for `'1`
...
101 |   if let Some(two) = map.get_mut(&2) {
    |                      ^^^^^^^^^^^^^^^ second mutable borrow occurs here

It seems the mutable lifetime of by the initial get_mut is required to live for the length of the function as its returned. But this means map is still mutably borrowed when attempting the second get_mut.

How can I avoid this? The only way I've found possible is by calling contains_key before the first get_mut, but that is not ideal for performance.

fn get_c<T>(map: &mut HashMap<usize, T>) -> Option<&mut T> {
  if map.contains_key(&1) { // works, but isn't optimal for performance
    return Some(map.get_mut(&1).unwrap());
  }
  else if let Some(two) = map.get_mut(&2) {
    Some(two)
  }
  else {
    None
  }
}
Oliver Cooper
  • 849
  • 7
  • 20

0 Answers0