One approach to solving item 1 is to think about the default as not being a separate key to the HashMap, but being a part of the value for that key, which allows you to model this a little more explicitly:
struct WithDefault<T> {
value: Option<T>,
default: Option<T>,
}
struct DefaultMap<K, V> {
map: HashMap<K, WithDefault<V>>,
}
impl<K: Eq + Hash, V> DefaultMap<K, V> {
fn get_mut(&mut self, key: &K) -> Option<&mut V> {
let item = self.map.get_mut(key)?;
item.value.as_mut().or_else(|| item.default.as_mut())
}
}
Obviously this isn't a generic solution to splitting borrows though (which is covered in https://doc.rust-lang.org/nomicon/borrow-splitting.html)