0

The check_vec() closure captures a mutable reference to the values vector. The compiler is not smart enough to understand that values.push(0xbeef) call is safe. I have tried compiling using NLL feature flag, but that didn't help either.

fn main() {
    let mut values = Vec::with_capacity(16);

    let mut check_vec = || {
        if values.len() < 16 {
            values.push(0xdead);
        }
    };

    for _ in 0..32 {
        check_vec();
        values.push(0xbeef);
    }

    check_vec();
}

(playground)

error[E0499]: cannot borrow `values` as mutable more than once at a time
  --> src/main.rs:12:9
   |
4  |     let mut check_vec = || {
   |                         -- first mutable borrow occurs here
5  |         if values.len() < 16 {
   |            ------ previous borrow occurs due to use of `values` in closure
...
12 |         values.push(0xbeef);
   |         ^^^^^^ second mutable borrow occurs here
...
16 | }
   | - first borrow ends here

Are there any ways to mitigate or workaround this limitation?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Araz Abishov
  • 1,661
  • 3
  • 15
  • 26
  • 1
    I believe your question is answered by the answers of [Can't borrow mutably within two different closures in the same scope](https://stackoverflow.com/q/49703990/155423) and/or [Problems with mutability in a closure](https://stackoverflow.com/q/41990175/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jul 28 '18 at 16:48
  • TL;DR the duplicates: pass an argument or switch to `RefCell`. – Shepmaster Jul 28 '18 at 16:50
  • `RefCell` introduces runtime overhead, which I would prefer to avoid. I was hoping for a solution which can make compiler "happy". Thanks anyways. – Araz Abishov Jul 28 '18 at 18:26
  • The solution to make the compiler happy is to pass `values` as an argument as @Shepmaster said. – mcarton Jul 28 '18 at 18:41
  • @mcarton that diminishes the value of capturing environment :shrug: – Araz Abishov Jul 28 '18 at 18:43
  • 1
    In your example, it is trivial to use a parameter. In a non-trivial example, how would you expect the borrow checker to verify that what you are doing is safe? Generally, capturing the environment is still very useful for immutable closures. – mcarton Jul 28 '18 at 19:20
  • @mcarton how do you feel about [my addition](https://stackoverflow.com/questions/49703990/cant-borrow-mutably-within-two-different-closures-in-the-same-scope) of "Unsafe programmer-brain-time borrow checking"? – Shepmaster Jul 28 '18 at 20:08
  • @Shepmaster Good! – mcarton Jul 28 '18 at 20:14
  • @ArazAbishov I've added an unsafe version to [Can't borrow mutably within two different closures in the same scope](https://stackoverflow.com/q/49703990/155423) to address your concern. – Shepmaster Jul 28 '18 at 20:52

0 Answers0