How can I mutate a hash_map
in the None
clause of match hash_map.get(...)
(and similarly for vec.get
)?
match hash_map.get(...) {
None => {
// How can I mutate hash_map here?
}
}
As a full example, the following does not compile:
use std::collections::HashMap;
fn map_question(map: &mut HashMap<String, String>) {
match map.get(&"foo".to_string()) {
Some(s) => {
// Do something with s
},
None => {
// I'd like to mutate `map` here, but I'm getting "cannot borrow map"
map.insert("bar".to_string(), "x".to_string());
}
}
}
The reason is that the Option<&String>
returned by map.get()
is still in scope, so map
is borrowed. Here's the full error message:
error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable
--> test.rs:10:13
|
4 | match map.get(&"foo".to_string()) {
| --- immutable borrow occurs here
...
10 | map.insert("bar".to_string(), "x".to_string());
| ^^^ mutable borrow occurs here
11 | }
12 | }
| - immutable borrow ends here
My solution has been to work around this problem by using if let
:
fn map_alternative(map: &mut HashMap<String, String>) {
if let Some(s) = map.get(&"foo".to_string()) {
// Do something with s
}
// Now we can mutate `map` because the `Option` return by `.get`
// is out of scope.
map.insert("bar".to_string(), "x".to_string());
}
(Note that we're not using an else
clause here, because the Option<&String>
returned by .get
would still be in scope in the else
clause for some reason.)
But this seems somewhat unsatisfactory. Can I tell Rust that when I'm matching None
, I'm done with the Option
object I got from .get
?