here is a simplified version of a Font object I'm currently building for inclusion in an embedded system. Inside the Font, I implement a cache of already rasterized glyphs through a HashMap. The retrieve() method must first check if a specific glyph is already in the cache through the find() method. If not found, it must then build the glyph, put it in the cache and then return it to the caller.
The issue is that the retrieve() method must first do an immutable borrow before modifying the cache if the required glyph was not found. Can't find a way to get it to work properly. Here is the code:
use std::collections::HashMap;
use std::collections::hash_map::RandomState;
type GlyphCharCode = u32;
type GlyphsCache = HashMap<GlyphCharCode, Glyph, RandomState>;
struct Glyph { a: u8 }
struct Font {
cache: GlyphsCache
}
impl Font {
fn new() -> Font {
Font { cache: GlyphsCache::new() }
}
fn find(&self, charcode: GlyphCharCode) -> Option<&Glyph> {
self.cache.get(&charcode)
}
fn retrieve(&mut self, charcode: GlyphCharCode) -> Option<&Glyph> {
let result = self.find(charcode);
match result {
Some(glyph) => Some(glyph),
None => { self.cache.insert(charcode, Glyph { a: 3u8 });
self.find(charcode) }
}
}
}
fn main() {
let charcode: GlyphCharCode = 3;
let mut font = Font::new();
if let Some(glyph) = font.retrieve(charcode) {
println!("Glyph value: {}", glyph.a);
}
}
and here are the error messages:
error[E0502]: cannot borrow `self.cache` as mutable because it is also borrowed as immutable
--> src/main.rs:26:17
|
22 | fn retrieve(&mut self, charcode: GlyphCharCode) -> Option<&Glyph> {
| - let's call the lifetime of this reference `'1`
23 | let result = self.find(charcode);
| ------------------- immutable borrow occurs here
24 | match result {
25 | Some(glyph) => Some(glyph),
| ----------- returning this value requires that `*self` is borrowed for `'1`
26 | None => { self.cache.insert(charcode, Glyph { a: 3u8 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here