How can I convince the check check to allow me to cache the values?
The minter hammered me:
use std::collections::HashMap;
struct Cache {
cache: Vec<HashMap<String, String>>,
}
impl Cache {
fn get(&mut self, index: usize, key: String) -> String {
let mut cache = &mut self.cache[index];
match cache.get(&key) {
Some(r) => {
return r.clone();
}
None => {
let r = "foo".to_string(); // something smart here
cache.insert(key, r.clone());
return r;
}
}
}
}
What I get:
error[E0502]: cannot borrow `*cache` as mutable because it is also borrowed as immutable --> src/main.rs:16:17 | 10 | match cache.get(&key) { | ----- immutable borrow occurs here ... 16 | cache.insert(key, r.clone()); | ^^^^^ mutable borrow occurs here ... 19 | } | - immutable borrow ends here
How can I rewrite my code so that it compiles?
source to share
Another approach is to use an interface entry
. The only downside to this approach is that it (currently) doesn't use the infrastructure BorrowFrom
that the method uses get
, which makes it less flexible. In your case, this is not a problem, since it get
accepts a key belonging to it. The advantage entry
is that it only does one hash lookup, whereas using get
makes you do two lookups.
use std::collections::HashMap;
struct Cache {
cache: Vec<HashMap<String, String>>,
}
impl Cache {
fn get(&mut self, index: usize, key: String) -> String {
self.cache[index]
.entry(key)
.or_insert_with(|| "foo".to_string())
.clone()
}
}
source to share
The borrowing controller sees it cache.get
as an unchanged loan, even though it returns None
. The easiest way to change the code is to move the insert out of the match, for example:
use std::collections::HashMap;
struct Cache {
cache: Vec<HashMap<String, String>>,
}
impl Cache {
fn get(&mut self, index: usize, key: String) -> String {
let mut cache = &mut self.cache[index];
match cache.get(&key) {
Some(r) => {
return r.clone();
}
None => (),
}
let r = "foo".to_string(); // something smart here
cache.insert(key, r.clone());
return r;
}
}
source to share