Mutable borrow in mutable closure

I would like to modify the variable via a closure.
Then I get the error.

error[E0499]: cannot borrow `tr` as mutable more than once at a time
 --> src\main.rs:34:17
  |
31 |     let mut c = Changers::new(&mut tr);
  |                               ------- first mutable borrow occurs here
...
34 |     let mut f = || {
  |                 ^^ second mutable borrow occurs here
35 |         let base = c.call_index();
  |                    - first borrow later captured here by closure
36 |         tr.set_index(base + index);
  |         -- second borrow occurs due to use of `tr` in closure

error: aborting due to previous error

How can I resolve this problem?

Code is as the following:

#[derive(Default)]
pub struct ProgressTracker {
    index: u64,
}

impl ProgressTracker {
    fn get_index(&self) -> u64 {
        self.index
    }
    pub fn set_index(&mut self, index: u64) {
        self.index = index
    }
}

pub struct Changers<'a> {
    tracker: &'a ProgressTracker,
}

impl Changers<'_> {
    pub fn new(tracker: &ProgressTracker) -> Changers {
        Changers { tracker }
    }

    pub fn call_index(&mut self) -> u64 {
        self.tracker.get_index()
    }
}

fn main() {
    let mut tr = ProgressTracker::default();
    let mut c = Changers::new(&mut tr);
    let mut index = 0;

    let mut f = || {
        let base = c.call_index();
        tr.set_index(base + index);
        index += 1;
    };

    for _ in 0..5 {
        f();
    }
}

I expect that tr.set_index(base + index); will effect to c.

You can expose set_index through changer interface. The problem here is that there can only be one mutable borrow of value at a time, furthermore - no immutable borrow can happen, while mutable borrow is alive. So you may reconsider your program design, either access mutably borrowed progress tracker only through Changer, or give changer an ownership of ProgressTracker. There may be better possibilities if you explain what you want to accomplish in final.

Also it helps to keep in mind, that there is an aliasing restriction in Rust (immutable reference expects value to stay immutable).

1 Like

Since your write tr.set_index(base + index) in the closure f, it will borrow a mutable reference of tr while c still holds a mutable reference of tr at the same time. This violates the borrow rules in rust.
You may need runtime borrow checks: std::cell - Rust

1 Like

What I would like to do is,

  1. create Struct ProgressTracker
  2. create Struct Changers by &ProgressTracker (avoiding Clone or Copy, because I think it might be costly)
  3. Call function in Changers(which get the current state of ProgressTracker), and Update ProgressTracker with the return values. Also the updated ProgressTracker can be used by creating another Changers. Repeatedly.

Everything is fine until I need to do these in a mutable function.

I find this gets rid of CE.

#[derive(Default)]
pub struct ProgressTracker {
    index: u64,
}

impl ProgressTracker {
    fn get_index(&self) -> u64 {
        self.index
    }
    pub fn set_index(&mut self, index: u64) {
        self.index = index
    }
}

pub struct Changers<'a> {
    tracker: &'a ProgressTracker,
}

impl Changers<'_> {
    pub fn new(tracker: &ProgressTracker) -> Changers {
        Changers { tracker }
    }

    pub fn call_index(&mut self) -> u64 {
        self.tracker.get_index()
    }
}

fn main() {
    let mut tr = ProgressTracker::default();
    // let mut c = Changers::new(&mut tr);
    let mut index = 0;

    let mut f = || {
        let base = Changers::new(&mut tr).call_index();
        tr.set_index(base + index);
        index += 1;
    };

    for _ in 0..5 {
        f();
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.