I am implementing a cache which tries a lookup in a table, if that fails it tries a simple method to get the value, and if that fails, it goes and computes multiple new entries in the cache. The Entry
system seems specifically designed for the first half of this, but I cannot get the borrow checker to allow me to complete the last half.
use std::collections::HashMap;
fn main() {
let mut cache = Cache { cache: HashMap::new() };
println!("{}", cache.get_from_cache(10));
}
struct Cache {
cache: HashMap<u32, String>
}
impl Cache {
fn get_from_cache<'a>(&'a mut self, i: u32) -> &'a String {
match self.cache.entry(i) {
std::collections::hash_map::Entry::Occupied(entry) => return entry.into_mut(),
std::collections::hash_map::Entry::Vacant(entry) => {
// Some values have an easy way to be computed...
if i == 5 {
return entry.insert("my string".to_string())
}
}
}
// Neither look-up method succeeded, so we 'compute' values one-by-one
for j in 1..=i {
self.cache.insert(j, "another string".to_string()); // Borrow checker fails here
}
self.cache.get(&i).unwrap()
}
}
The problem is that the Entry
from self.cache.entry(i)
borrows self.cache
for the entire lifetime 'a
even though I no longer need it at the point that I attempt to do self.cache.insert
.
One solution to this (I think) would be if there were a way to turn my reference to the Entry
into a reference to its HashMap
and then insert through that reference. However, I see no way to do this with the entry
interface. Is there some way to achieve this? Or to otherwise satisfy the borrow checker?