I want to get the following code working (it needs to be a static method, no self
, and good judgement prevents me from using multiple get_mut
calls or some other hack -- the map is large; using entry API unconditionally is a no-go due to unconditional clone):
fn get<'slf>(
map: &'slf mut HashMap<String, usize>,
key: &str,
) -> &'slf mut usize {
if let Some(data) = map.get_mut(key) {
data
} else {
let data = 42usize;
map
.entry(key.to_string())
.or_insert(data)
}
}
Here is the full playground.
error[E0499]: cannot borrow
*map
as mutable more than once at a time
It's not clear to me why Rust complains about multiple mutable borrows, when they should apply to different branches. As per my reading of rust 🚀 - &mut self borrow conflicting with itself. | bleepcoder.com this should have been fixed with non-lexical lifetimes (i.e., a couple years back...). Alas, it's still not working.
I am currently using a bunch of ugly unsafe to work around the problem and Miri does not complain. But that gets me back to the good judgement above...
Are there suggestions for a non-unsafe solution?
Here are two more variations of what I believe to be similar problems. with
is like with2
but without the explicit lifetime (which I can elide there, but I cannot elide it in the get
example which is really what I need). with
compiles and works fine, suggesting to me that the named lifetimes is tripping Rust over. But I am unsure how that finding helps me, as I cannot craft anything like this for the original get
code. I'd still be curious as to why exactly that makes such a difference -- named or not, the reference has to outlive the function call and must not exceed the lifetime of self
.