How can I modify self in a closure called from a member function?
borrow-checker, closures, mutability, rust
Solution
The simplest change you can make is to pass the reference to the closure:
struct Tester {
x: i8,
}
impl Tester {
fn traverse<F>(&mut self, mut f: F)
where
F: FnMut(&mut Tester),
{
f(self);
}
}
fn main() {
let mut tester = Tester { x: 8 };
tester.traverse(|z| z.x += 1);
println!("{}", tester.x);
}
This prevents having multiple mutable references (also known as aliasing), which are disallowed in Rust.
Problem
I am trying to calculate legal chess moves and am having problems satisfying the borrow checker. I have a struct `Chess` that implements these methods (non-important code replaced by `...`): ``` // internal iterator over (possibly not legal) moves fn get_moves<F>(&self, func: F) where F: Fn(/* ... */), { func(/* ... */); // move 1 func(/* ... */); // move 2 func(/* ... */); // etc... } fn is_legal_move(&mut self) -> bool { // notice this takes a mutable self. For performance // reasons, the move is made, legality is checked, then I // undo the move, so it must be mutable to be able to move pieces make_move(/* ... */); // check if legal undo_move(/* ... */); //return true if legal } fn get_legal_moves(&self) /* -> ... */ { self.get_moves(|/* ... */| { if self.is_legal_move(/* ... */) { // <-- error here // do something with legal move } }) } ``` I get a compilation error in `get_legal_moves` because I am modifying `self` inside the closure while `get_moves` is still borrowing `self`. I created a simplified example showing the problem I am trying to solve: ``` struct Tester { x: i8, } impl Tester { fn traverse<Func>(&mut self, mut f: Func) where Func: FnMut(), { //in real-world, this would probably iterate over something f(); } } fn main() { let mut tester = Tester { x: 8 }; tester.traverse(|| { tester.x += 1; //I want to be able to modify tester here }); println!("{}", tester.x); } ``` Playground The error: ``` error[E0499]: cannot borrow `tester` as mutable more than once at a time --> src/main.rs:17:5 | 17 | tester.traverse(|| { | ^ -------- -- first mutable borrow occurs here | | | | _____| first borrow later used by call | | 18 | | tester.x += 1; //I want to be able to modify tester here | | ------ first borrow occurs due to use of `tester` in closure 19 | | }); | |______^ second mutable borrow occurs here error[E0499]: cannot borrow `tester` as mutable more than once at a time --> src/main.rs:17:21 | 17 | tester.traverse(|| { | ------ -------- ^^ second mutable borrow occurs here | | | | | first borrow later used by call | first mutable borrow occurs here 18 | tester.x += 1; //I want to be able to modify tester here | ------ second borrow occurs due to use of `tester` in closure ``` How can I satisfy the borrow checker so the code can compile?