I'm writing a function that works with a HashMap and at various points in the function I want to check if any of the values in the map meet a condition and if any does return the key for just one of the entries that meets the condition.
So far, I tried to first iterate over references to check my condition, and then use remove_entry to get an owned copy of the key rather than a borrow:
use std::{collections::HashMap, hash::Hash}; fn remove_first_odd<K: Hash + Eq>(map: &mut HashMap<K, u64>) -> Option<K> { let maybe_entry = map.iter().find(|(_, &value)| value & 1 == 1); match maybe_entry { Some((key_ref, _value_ref)) => { let (key_owned, _value_owned) = map.remove_entry(key_ref).unwrap(); Some(key_owned) } None => None, } } but this fails borrow checking, because I can't mutate the map while I am still holding a reference to one of the keys in it:
error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable --> src/lib.rs:8:45 | 4 | let maybe_entry = map.iter().find(|(_, &value)| value & 1 == 1); | --- immutable borrow occurs here ... 8 | let (key_owned, _value_owned) = map.remove_entry(key_ref).unwrap(); | ^^^^------------^^^^^^^^^ | | | | | immutable borrow later used by call | mutable borrow occurs here I believe that this is possible, because as long as remove_entry only dereferences my key before mutation and not after, this should be sound.
So is there a safe API to do this? If not, can one be created?
Note that:
- I can't clone my keys because they are generic without a clone bound
- I can't consume the
HashMapwith something like.into_iter() - I only need to remove a single entry, not all of the entries that match
retainto remove the pair that fits your criteria.