Working with arenas

Hello,

I am having trouble designing my application in a way that avoids problems with the borrow checker.
Specifically, I am using an Arena to access structs. The situation is best explained in pseudo-code:

// Foo contains an index to an element in the arena
struct Foo {
    element_id: Index,
    ...
}

struct Master {
    foos: Vec<Foo>,
    arena: Arena<Bar>
}

impl Foo {
    fn do_something(&self, arena: &mut Arena<Bar>) {
        // Does something with the arena
    }
}

impl Master {
    fn get_current_foo(&self) -> &Foo {
        // Returns some Foo
        self.foos[0]
    }
}


fn main() {
    let m = Master {...};
    
    // How is it possible to do a call like this?
    m.get_current_foo().do_something(&mut m.arena);
}

The call m.get_current_foo().do_something(&mut m.arena) will obviously fail because it creates simultaniously an immutable and a mutable borrow of m.
I see that the way I have implemented this is generally bad design, but unfortunately I do not know how to make it better. Is this just a hard problem, or ist there a simple idiomatic way to solve this?

One thing you might try is this:

struct Master {
    foos: Vec<Foo>,
    arena: Arena<Bar>
}

struct FooRefWithArena<'a> {
    foo: &'a Foo,
    arena: &'a mut Arena<Bar>,
}

impl Foo {
    fn do_something(&self, arena: &mut Arena<Bar>) {
        // Does something with the arena
    }
}

impl<'a> FooRefWithArena<'a> {
    fn do_something(&self) {
        self.foo.do_something(self.arena)
    }
}

impl Master {
    fn get_current_foo(&mut self) -> FooRefWithArena {
        FooRefWithArena {
            foo: &self.foos[0],
            arena: &mut self.arena,
        }
    }
}

I have no idea if this compiles, as the example you provided is not complete and fails to compile.

1 Like

Thank you very much for your quick response!
This solves my borrowing problem. I don't like to have to create a special struct just to handle this function, but I think I'll just go with it.

You can also return a tuple (&Foo, &mut Arena)