Error code E0387
Note: this error code is no longer emitted by the compiler.
This error occurs when an attempt is made to mutate or mutably reference data that a closure has captured immutably.
Erroneous code example:
#![allow(unused)] fn main() { // Accepts a function or a closure that captures its environment immutably. // Closures passed to foo will not be able to mutate their closed-over state. fn foo<F: Fn()>(f: F) { } // Attempts to mutate closed-over data. Error message reads: // `cannot assign to data in a captured outer variable...` fn mutable() { let mut x = 0u32; foo(|| x = 2); } // Attempts to take a mutable reference to closed-over data. Error message // reads: `cannot borrow data mutably in a captured outer variable...` fn mut_addr() { let mut x = 0u32; foo(|| { let y = &mut x; }); } }
The problem here is that foo is defined as accepting a parameter of type Fn
.
Closures passed into foo will thus be inferred to be of type Fn
, meaning that
they capture their context immutably.
If the definition of foo
is under your control, the simplest solution is to
capture the data mutably. This can be done by defining foo
to take FnMut
rather than Fn:
#![allow(unused)] fn main() { fn foo<F: FnMut()>(f: F) { } }
Alternatively, we can consider using the Cell
and RefCell
types to achieve
interior mutability through a shared reference. Our example's mutable
function could be redefined as below:
#![allow(unused)] fn main() { use std::cell::Cell; fn foo<F: Fn()>(f: F) { } fn mutable() { let x = Cell::new(0u32); foo(|| x.set(2)); } }
You can read more in the API documentation for Cell.