1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #![allow(non_snake_case)]
13 register_long_diagnostics! {
16 This error occurs when an attempt is made to use data captured by a closure,
17 when that data may no longer exist. It's most commonly seen when attempting to
21 fn foo() -> Box<Fn(u32) -> u32> {
27 Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
28 closed-over data by reference. This means that once `foo()` returns, `x` no
29 longer exists. An attempt to access `x` within the closure would thus be unsafe.
31 Another situation where this might be encountered is when spawning threads:
38 let thr = std::thread::spawn(|| {
44 Since our new thread runs in parallel, the stack frame containing `x` and `y`
45 may well have disappeared by the time we try to use them. Even if we call
46 `thr.join()` within foo (which blocks until `thr` has completed, ensuring the
47 stack frame won't disappear), we will not succeed: the compiler cannot prove
48 that this behaviour is safe, and so won't let us do it.
50 The solution to this problem is usually to switch to using a `move` closure.
51 This approach moves (or copies, where possible) data into the closure, rather
52 than taking references to it. For example:
55 fn foo() -> Box<Fn(u32) -> u32> {
57 Box::new(move |y| x + y)
61 Now that the closure has its own copy of the data, there's no need to worry
66 It is not allowed to use or capture an uninitialized variable. For example:
71 let y = x; // error, use of possibly uninitialized variable
74 To fix this, ensure that any declared variables are initialized before being
79 This error occurs when an attempt is made to use a variable after its contents
80 have been moved elsewhere. For example:
83 struct MyStruct { s: u32 }
86 let mut x = MyStruct{ s: 5u32 };
93 Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
94 of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
95 of workarounds like `Rc`, a value cannot be owned by more than one variable.
97 If we own the type, the easiest way to address this problem is to implement
98 `Copy` and `Clone` on it, as shown below. This allows `y` to copy the
99 information in `x`, while leaving the original version owned by `x`. Subsequent
100 changes to `x` will not be reflected when accessing `y`.
103 #[derive(Copy, Clone)]
104 struct MyStruct { s: u32 }
107 let mut x = MyStruct{ s: 5u32 };
114 Alternatively, if we don't control the struct's definition, or mutable shared
115 ownership is truly required, we can use `Rc` and `RefCell`:
118 use std::cell::RefCell;
121 struct MyStruct { s: u32 }
124 let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
126 x.borrow_mut().s = 6;
127 println!("{}", x.borrow.s);
131 With this approach, x and y share ownership of the data via the `Rc` (reference
132 count type). `RefCell` essentially performs runtime borrow checking: ensuring
133 that at most one writer or multiple readers can access the data at any one time.
135 If you wish to learn more about ownership in Rust, start with the chapter in the
138 https://doc.rust-lang.org/book/ownership.html
142 This error occurs when an attempt is made to partially reinitialize a
143 structure that is currently uninitialized.
145 For example, this can happen when a drop has taken place:
148 let mut x = Foo { a: 1 };
149 drop(x); // `x` is now uninitialized
150 x.a = 2; // error, partial reinitialization of uninitialized structure `t`
153 This error can be fixed by fully reinitializing the structure in question:
156 let mut x = Foo { a: 1 };
163 This error occurs when an attempt is made to reassign an immutable variable.
169 x = 5; // error, reassignment of immutable variable
173 By default, variables in Rust are immutable. To fix this error, add the keyword
174 `mut` after the keyword `let` when declaring the variable. For example:
185 This error occurs when an attempt is made to mutate the target of a mutable
186 reference stored inside an immutable container.
188 For example, this can happen when storing a `&mut` inside an immutable `Box`:
192 let y: Box<_> = Box::new(&mut x);
193 **y = 2; // error, cannot assign to data in an immutable container
196 This error can be fixed by making the container mutable:
200 let mut y: Box<_> = Box::new(&mut x);
204 It can also be fixed by using a type with interior mutability, such as `Cell` or
209 let y: Box<Cell<_>> = Box::new(Cell::new(x));
215 This error occurs when an attempt is made to mutate or mutably reference data
216 that a closure has captured immutably. Examples of this error are shown below:
219 // Accepts a function or a closure that captures its environment immutably.
220 // Closures passed to foo will not be able to mutate their closed-over state.
221 fn foo<F: Fn()>(f: F) { }
223 // Attempts to mutate closed-over data. Error message reads:
224 // `cannot assign to data in a captured outer variable...`
230 // Attempts to take a mutable reference to closed-over data. Error message
231 // reads: `cannot borrow data mutably in a captured outer variable...`
234 foo(|| { let y = &mut x; });
238 The problem here is that foo is defined as accepting a parameter of type `Fn`.
239 Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
240 they capture their context immutably.
242 If the definition of `foo` is under your control, the simplest solution is to
243 capture the data mutably. This can be done by defining `foo` to take FnMut
247 fn foo<F: FnMut()>(f: F) { }
250 Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
251 interior mutability through a shared reference. Our example's `mutable` function
252 could be redefined as below:
258 let x = Cell::new(0u32);
263 You can read more about cell types in the API documentation:
265 https://doc.rust-lang.org/std/cell/
269 A variable was borrowed as mutable more than once. Erroneous code example:
275 // error: cannot borrow `i` as mutable more than once at a time
278 Please note that in rust, you can either have many immutable references, or one
279 mutable reference. Take a look at
280 https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
281 information. Example:
286 let mut x = &mut i; // ok!
291 let b = &i; // still ok!
292 let c = &i; // still ok!
297 You tried to move out of a value which was borrowed. Erroneous code example:
300 use std::cell::RefCell;
302 struct TheDarkKnight;
305 fn nothing_is_true(self) {}
309 let x = RefCell::new(TheDarkKnight);
311 x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
315 Here, the `nothing_is_true` method takes the ownership of `self`. However,
316 `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
317 which is a borrow of the content owned by the `RefCell`. To fix this error,
318 you have three choices:
320 * Try to avoid moving the variable.
321 * Somehow reclaim the ownership.
322 * Implement the `Copy` trait on the type.
327 use std::cell::RefCell;
329 struct TheDarkKnight;
332 fn nothing_is_true(&self) {} // First case, we don't take ownership
336 let x = RefCell::new(TheDarkKnight);
338 x.borrow().nothing_is_true(); // ok!
345 use std::cell::RefCell;
347 struct TheDarkKnight;
350 fn nothing_is_true(self) {}
354 let x = RefCell::new(TheDarkKnight);
355 let x = x.into_inner(); // we get back ownership
357 x.nothing_is_true(); // ok!
364 use std::cell::RefCell;
366 #[derive(Clone, Copy)] // we implement the Copy trait
367 struct TheDarkKnight;
370 fn nothing_is_true(self) {}
374 let x = RefCell::new(TheDarkKnight);
376 x.borrow().nothing_is_true(); // ok!
380 You can find more information about borrowing in the rust-book:
381 http://doc.rust-lang.org/stable/book/references-and-borrowing.html
386 register_diagnostics! {
387 E0385, // {} in an aliasable location
388 E0388, // {} in a static location
389 E0389, // {} in a `&` reference
390 E0500, // closure requires unique access to `..` but .. is already borrowed
391 E0501, // cannot borrow `..`.. as .. because previous closure requires unique access
392 E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
393 E0503, // cannot use `..` because it was mutably borrowed
394 E0504, // cannot move `..` into closure because it is borrowed
395 E0505, // cannot move out of `..` because it is borrowed
396 E0506, // cannot assign to `..` because it is borrowed
397 E0508, // cannot move out of type `..`, a non-copy fixed-size array
398 E0509, // cannot move out of type `..`, which defines the `Drop` trait