I want to add memoization to a function which can be kind of costly. I tried to make a minimum example below which demonstrates the error.
use std::collections::{HashMap};
struct Foo {
data: i64,
memo: HashMap<i64, String>
}
impl Foo {
fn new(data: i64) -> Foo {
let memo = HashMap::new();
Foo {data, memo}
}
fn f(&self, x: i64) -> String {
(self.data + x).to_string()
}
fn f_cached(&mut self, x: i64) -> String {
match self.memo.get(&x) {
Some(result) => result.clone(),
None => {
let result = self.f(x);
self.memo.insert(x, result.clone());
result
}
}
}
}
I remove the f_cached
function below then everything compiles, but the cached version refuses to compile; the error I get is:
error[E0502]: cannot borrow `self.memo` as mutable because it is also borrowed as immutable
--> src/main.rs:173:17
|
169 | match self.memo.get(&x) {
| --------- immutable borrow occurs here
...
173 | self.memo.insert(x, result.clone());
| ^^^^^^^^^ mutable borrow occurs here
...
176 | }
| - immutable borrow ends here
I've tried various reworkings of the basic logic, such as assigning self.memo.get(&x)
to a variable, using if let
, etc etc, but everything produces the same or a different kind of error. Certainly it doesn't look like there's anything unsafe going on in the code.