How can I modify self in a closure called from a member function?

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:21
   |
17 |     tester.traverse(|| {
   |     ------          ^^ second mutable borrow occurs here
   |     |
   |     first mutable borrow occurs here
18 |         tester.x += 1; //I want to be able to modify tester here
   |         ------ borrow occurs due to use of `tester` in closure
19 |     });
   |      - first borrow ends here

How can I satisfy the borrow checker so the code can compile?


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.

链接地址: http://www.djcxy.com/p/83748.html

上一篇: 使用Angularjs将Excel转换为JSON

下一篇: 如何修改从成员函数调用的闭包中的self?