0

I'm very new to learning Rust. Here's a condensed and silly code sample which I'm trying to compile:

fn do_something(read: &Fn() -> i32, write: &mut FnMut(i32)) {
    if read() == 10 {
        write(11);
    }
}

fn print_11() {
    let mut val = 10;
    do_something(&|| val, &mut |n| val = n);
    println!("Got {}", val);
}

The write closure borrows val mutably, and the read closure borrows it immutably. The compiler blocks this for this reason:

error[E0502]: cannot borrow `val` as mutable because it is also borrowed as immutable
 --> src/main.rs:9:32
  |
9 |     do_something(&|| val, &mut |n| val = n);
  |                   -- ---       ^^^ ---    - immutable borrow ends here
  |                   |  |         |   |
  |                   |  |         |   borrow occurs due to use of `val` in closure
  |                   |  |         mutable borrow occurs here
  |                   |  previous borrow occurs due to use of `val` in closure
  |                   immutable borrow occurs here

error[E0502]: cannot borrow `val` as mutable because it is also borrowed as immutable
 --> src/main.rs:9:32
  |
9 |     do_something(&|| val, &mut |n| val = n);
  |                   -- ---       ^^^ ---    - immutable borrow ends here
  |                   |  |         |   |
  |                   |  |         |   borrow occurs due to use of `val` in closure
  |                   |  |         mutable borrow occurs here
  |                   |  previous borrow occurs due to use of `val` in closure
  |                   immutable borrow occurs here

Is there an idiomatic way to create two closures which can read/write to the same variable? Is this a case for using something like Rc?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Anthony Martin
  • 608
  • 6
  • 12
  • 1
    As-is, this definitely breaks Rust's rule of what references are allowed to exist at the same time. It might help to hear about the overall usecase? Seems like it'd be much easier to pass in a mutable reference to `val` itself in this case, but the exact solution would probably depend on why you're trying to use the closures in the first place. – loganfsmyth Dec 19 '17 at 17:50
  • Yes, this is a trimmed down example. The use case is - I'd like to have a module which when running, can read or write from a value whenever it likes. The caller needs to know when the value is read from or written to, and may need to perform custom logic and update its own state when this happens. I could push all of this logic into the module, but it then becomes less reusable, as I'd need to copy the module every time I need slightly different logic when the value is read/written to. – Anthony Martin Dec 19 '17 at 17:56
  • 1
    Not necessarily `Rc`, but `Cell` or `RefCell`. The duplicates [applied to your question](https://play.rust-lang.org/?gist=120b9e09baa7bef2c6fa874e953be0e2&version=stable). – Shepmaster Dec 19 '17 at 18:41

0 Answers0