@@ -158,6 +158,60 @@ fn main(){
158
158
x = 5;
159
159
}
160
160
```
161
+ "## ,
162
+
163
+ E0387 : r##"
164
+ This error occurs when an attempt is made to mutate or mutably reference data
165
+ that a closure has captured immutably. Examples of this error are shown below:
166
+
167
+ ```
168
+ // Accepts a function or a closure that captures its environment immutably.
169
+ // Closures passed to foo will not be able to mutate their closed-over state.
170
+ fn foo<F: Fn()>(f: F) { }
171
+
172
+ // Attempts to mutate closed-over data. Error message reads:
173
+ // `cannot assign to data in a captured outer variable...`
174
+ fn mutable() {
175
+ let mut x = 0u32;
176
+ foo(|| x = 2);
177
+ }
178
+
179
+ // Attempts to take a mutable reference to closed-over data. Error message
180
+ // reads: `cannot borrow data mutably in a captured outer variable...`
181
+ fn mut_addr() {
182
+ let mut x = 0u32;
183
+ foo(|| { let y = &mut x; });
184
+ }
185
+ ```
186
+
187
+ The problem here is that foo is defined as accepting a parameter of type `Fn`.
188
+ Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
189
+ they capture their context immutably.
190
+
191
+ If the definition of `foo` is under your control, the simplest solution is to
192
+ capture the data mutably. This can be done by defining `foo` to take FnMut
193
+ rather than Fn:
194
+
195
+ ```
196
+ fn foo<F: FnMut()>(f: F) { }
197
+ ```
198
+
199
+ Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
200
+ interior mutability through a shared reference. Our example's `mutable` function
201
+ could be redefined as below:
202
+
203
+ ```
204
+ use std::cell::Cell;
205
+
206
+ fn mutable() {
207
+ let x = Cell::new(0u32);
208
+ foo(|| x.set(2));
209
+ }
210
+ ```
211
+
212
+ You can read more about cell types in the API documentation:
213
+
214
+ https://doc.rust-lang.org/std/cell/
161
215
"##
162
216
163
217
}
@@ -166,7 +220,6 @@ register_diagnostics! {
166
220
E0383 , // partial reinitialization of uninitialized structure
167
221
E0385 , // {} in an aliasable location
168
222
E0386 , // {} in an immutable container
169
- E0387 , // {} in a captured outer variable in an `Fn` closure
170
223
E0388 , // {} in a static location
171
224
E0389 // {} in a `&` reference
172
225
}
0 commit comments