How to fix ".. was mutably borrowed here in the previous iteration of the loop" in Rust?

You can't do caching with exclusive access. You can't treat Rust references like general-purpose pointers (BTW: &String and &Box<T> are double indirection, and very unidiomatic in Rust. Use &str or &T for temporary borrows).

&mut self means not just mutable, but exclusive and mutable, so your cache supports returning only one item, because the reference it returns has to keep self "locked" for as long as it exists.

You need to convince the borrow checker that the thing that find returns won't suddenly disappear next time you call it. Currently there's no such guarantee, because the interface doesn't stop you from calling e.g. items.clear() (borrow checker checks what function's interface allows, not what function actually does).

You can do that either by using Rc, or using a crate that implements a memory pool/arena.

struct Struct {
   items: HashMap<String, Rc<Calculation>>,
}

fn find(&mut self, key: &str) -> Rc<Calculation> 

This way if you clone the Rc, it will live for as long as it needs, independently of the cache.

You can also make it nicer with interior mutability.

struct Struct {
   items: RefCell<HashMap<…
}

This will allow your memoizing find method to use a shared borrow instead of an exclusive one:

fn find(&self, key: &str) -> …

which is much easier to work with for the callers of the method.


Probably not the cleanest way to do that, but it compiles. The idea is not to store the value found in a temporary result, to avoid aliasing: if you store the result, self is kept borrowed.

impl Struct {

    fn find(&mut self, key: &String) -> Option<&Box<Calculation>> {
        None
    }

    fn it(&mut self) -> Option<&Box<Calculation>> {
        for key in vec!["1","2","3"] {
            if self.find(&key.to_owned()).is_some() {
                return self.find(&key.to_owned());
            }
        }
        None
    }
}

Tags:

Ownership

Rust