The following code snippet does the same things in 3 ways.
use std::collections::HashMap;
struct Foo {
cache: HashMap<String, String>,
}
impl Foo {
fn get_cached(&mut self, key: &String) -> &String {
if !self.cache.contains_key(key) {
self.cache.insert(key.clone(), String::from("default"));
}
self.cache.get(key).unwrap()
}
fn show_impl(&self, what: &String) {
println!("{}", what);
}
pub fn show1(&mut self, key: &String) {
println!("{}", self.get_cached(key));
}
pub fn show2(&mut self, key: &String) {
if !self.cache.contains_key(key) {
self.cache.insert(key.clone(), String::from("default"));
}
self.show_impl(self.cache.get(key).unwrap());
}
// This does not compile
pub fn show3(&mut self, key: &String) {
self.show_impl(self.get_cached(key));
}
}
fn main() {}
show3 doesn't compile, giving the following error:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:28:24
|
28 | self.show_impl(self.get_cached(key));
| ---- ^^^^ - immutable borrow ends here
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
As far as I tell, the issue with show3 is not about mutability, but rather a double borrow: the borrow of self is given away to get_cached which doesn't end because get_cached returns a reference to something contained in self. Is this even correct?
How can I accomplish my intended goal of looking up a value in a mutable cache in self and pass the reference to another method of self?