]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_error_codes/src/error_codes/E0387.md
Rollup merge of #93556 - dtolnay:trailingcomma, r=cjgillot
[rust.git] / compiler / rustc_error_codes / src / error_codes / E0387.md
1 #### Note: this error code is no longer emitted by the compiler.
2
3 This error occurs when an attempt is made to mutate or mutably reference data
4 that a closure has captured immutably.
5
6 Erroneous code example:
7
8 ```compile_fail
9 // Accepts a function or a closure that captures its environment immutably.
10 // Closures passed to foo will not be able to mutate their closed-over state.
11 fn foo<F: Fn()>(f: F) { }
12
13 // Attempts to mutate closed-over data. Error message reads:
14 // `cannot assign to data in a captured outer variable...`
15 fn mutable() {
16     let mut x = 0u32;
17     foo(|| x = 2);
18 }
19
20 // Attempts to take a mutable reference to closed-over data.  Error message
21 // reads: `cannot borrow data mutably in a captured outer variable...`
22 fn mut_addr() {
23     let mut x = 0u32;
24     foo(|| { let y = &mut x; });
25 }
26 ```
27
28 The problem here is that foo is defined as accepting a parameter of type `Fn`.
29 Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
30 they capture their context immutably.
31
32 If the definition of `foo` is under your control, the simplest solution is to
33 capture the data mutably. This can be done by defining `foo` to take FnMut
34 rather than Fn:
35
36 ```
37 fn foo<F: FnMut()>(f: F) { }
38 ```
39
40 Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
41 interior mutability through a shared reference. Our example's `mutable`
42 function could be redefined as below:
43
44 ```
45 use std::cell::Cell;
46
47 fn foo<F: Fn()>(f: F) { }
48
49 fn mutable() {
50     let x = Cell::new(0u32);
51     foo(|| x.set(2));
52 }
53 ```
54
55 You can read more in the API documentation for [Cell][std-cell].
56
57 [std-cell]: https://doc.rust-lang.org/std/cell/