summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_error_codes/src/error_codes/E0387.md
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_error_codes/src/error_codes/E0387.md')
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0387.md57
1 files changed, 57 insertions, 0 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0387.md b/compiler/rustc_error_codes/src/error_codes/E0387.md
new file mode 100644
index 000000000..38ad19bd6
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0387.md
@@ -0,0 +1,57 @@
+#### 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:
+
+```compile_fail
+// 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:
+
+```
+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:
+
+```
+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][std-cell].
+
+[std-cell]: https://doc.rust-lang.org/std/cell/