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
}
}