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
32 Another situation where this might be encountered is when spawning threads:
39 let thr = std::thread::spawn(|| {
45 Since our new thread runs in parallel, the stack frame containing `x` and `y`
46 may well have disappeared by the time we try to use them. Even if we call
47 `thr.join()` within foo (which blocks until `thr` has completed, ensuring the
48 stack frame won't disappear), we will not succeed: the compiler cannot prove
49 that this behaviour is safe, and so won't let us do it.
51 The solution to this problem is usually to switch to using a `move` closure.
52 This approach moves (or copies, where possible) data into the closure, rather
53 than taking references to it. For example:
56 fn foo() -> Box<Fn(u32) -> u32> {
58 Box::new(move |y| x + y)
62 Now that the closure has its own copy of the data, there's no need to worry
67 This error occurs when an attempt is made to use a variable after its contents
68 have been moved elsewhere. For example:
71 struct MyStruct { s: u32 }
74 let mut x = MyStruct{ s: 5u32 };
81 Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
82 of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
83 of workarounds like `Rc`, a value cannot be owned by more than one variable.
85 If we own the type, the easiest way to address this problem is to implement
86 `Copy` and `Clone` on it, as shown below. This allows `y` to copy the
87 information in `x`, while leaving the original version owned by `x`. Subsequent
88 changes to `x` will not be reflected when accessing `y`.
91 #[derive(Copy, Clone)]
92 struct MyStruct { s: u32 }
95 let mut x = MyStruct{ s: 5u32 };
102 Alternatively, if we don't control the struct's definition, or mutable shared
103 ownership is truly required, we can use `Rc` and `RefCell`:
106 use std::cell::RefCell;
109 struct MyStruct { s: u32 }
112 let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
114 x.borrow_mut().s = 6;
115 println!("{}", x.borrow().s);
119 With this approach, x and y share ownership of the data via the `Rc` (reference
120 count type). `RefCell` essentially performs runtime borrow checking: ensuring
121 that at most one writer or multiple readers can access the data at any one time.
123 If you wish to learn more about ownership in Rust, start with the chapter in the
126 https://doc.rust-lang.org/book/first-edition/ownership.html
130 This error occurs when an attempt is made to partially reinitialize a
131 structure that is currently uninitialized.
133 For example, this can happen when a drop has taken place:
135 ```compile_fail,E0383
140 fn drop(&mut self) { /* ... */ }
143 let mut x = Foo { a: 1 };
144 drop(x); // `x` is now uninitialized
145 x.a = 2; // error, partial reinitialization of uninitialized structure `t`
148 This error can be fixed by fully reinitializing the structure in question:
155 fn drop(&mut self) { /* ... */ }
158 let mut x = Foo { a: 1 };
165 This error occurs when an attempt is made to mutate the target of a mutable
166 reference stored inside an immutable container.
168 For example, this can happen when storing a `&mut` inside an immutable `Box`:
170 ```compile_fail,E0386
172 let y: Box<_> = Box::new(&mut x);
173 **y = 2; // error, cannot assign to data in an immutable container
176 This error can be fixed by making the container mutable:
180 let mut y: Box<_> = Box::new(&mut x);
184 It can also be fixed by using a type with interior mutability, such as `Cell`
191 let y: Box<Cell<_>> = Box::new(Cell::new(x));
197 This error occurs when an attempt is made to mutate or mutably reference data
198 that a closure has captured immutably. Examples of this error are shown below:
200 ```compile_fail,E0387
201 // Accepts a function or a closure that captures its environment immutably.
202 // Closures passed to foo will not be able to mutate their closed-over state.
203 fn foo<F: Fn()>(f: F) { }
205 // Attempts to mutate closed-over data. Error message reads:
206 // `cannot assign to data in a captured outer variable...`
212 // Attempts to take a mutable reference to closed-over data. Error message
213 // reads: `cannot borrow data mutably in a captured outer variable...`
216 foo(|| { let y = &mut x; });
220 The problem here is that foo is defined as accepting a parameter of type `Fn`.
221 Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
222 they capture their context immutably.
224 If the definition of `foo` is under your control, the simplest solution is to
225 capture the data mutably. This can be done by defining `foo` to take FnMut
229 fn foo<F: FnMut()>(f: F) { }
232 Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
233 interior mutability through a shared reference. Our example's `mutable`
234 function could be redefined as below:
239 fn foo<F: Fn()>(f: F) { }
242 let x = Cell::new(0u32);
247 You can read more about cell types in the API documentation:
249 https://doc.rust-lang.org/std/cell/
253 E0388 was removed and is no longer issued.
257 An attempt was made to mutate data using a non-mutable reference. This
258 commonly occurs when attempting to assign to a non-mutable reference of a
259 mutable reference (`&(&mut T)`).
261 Example of erroneous code:
263 ```compile_fail,E0389
269 let mut fancy = FancyNum{ num: 5 };
270 let fancy_ref = &(&mut fancy);
271 fancy_ref.num = 6; // error: cannot assign to data in a `&` reference
272 println!("{}", fancy_ref.num);
276 Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an
277 immutable reference to a value borrows it immutably. There can be multiple
278 references of type `&(&mut T)` that point to the same value, so they must be
279 immutable to prevent multiple mutable references to the same value.
281 To fix this, either remove the outer reference:
289 let mut fancy = FancyNum{ num: 5 };
291 let fancy_ref = &mut fancy;
292 // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum)
294 fancy_ref.num = 6; // No error!
296 println!("{}", fancy_ref.num);
300 Or make the outer reference mutable:
308 let mut fancy = FancyNum{ num: 5 };
310 let fancy_ref = &mut (&mut fancy);
311 // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum)
313 fancy_ref.num = 6; // No error!
315 println!("{}", fancy_ref.num);
321 You tried to move out of a value which was borrowed. Erroneous code example:
323 ```compile_fail,E0507
324 use std::cell::RefCell;
326 struct TheDarkKnight;
329 fn nothing_is_true(self) {}
333 let x = RefCell::new(TheDarkKnight);
335 x.borrow().nothing_is_true(); // error: cannot move out of borrowed content
339 Here, the `nothing_is_true` method takes the ownership of `self`. However,
340 `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`,
341 which is a borrow of the content owned by the `RefCell`. To fix this error,
342 you have three choices:
344 * Try to avoid moving the variable.
345 * Somehow reclaim the ownership.
346 * Implement the `Copy` trait on the type.
351 use std::cell::RefCell;
353 struct TheDarkKnight;
356 fn nothing_is_true(&self) {} // First case, we don't take ownership
360 let x = RefCell::new(TheDarkKnight);
362 x.borrow().nothing_is_true(); // ok!
369 use std::cell::RefCell;
371 struct TheDarkKnight;
374 fn nothing_is_true(self) {}
378 let x = RefCell::new(TheDarkKnight);
379 let x = x.into_inner(); // we get back ownership
381 x.nothing_is_true(); // ok!
388 use std::cell::RefCell;
390 #[derive(Clone, Copy)] // we implement the Copy trait
391 struct TheDarkKnight;
394 fn nothing_is_true(self) {}
398 let x = RefCell::new(TheDarkKnight);
400 x.borrow().nothing_is_true(); // ok!
404 Moving a member out of a mutably borrowed struct will also cause E0507 error:
406 ```compile_fail,E0507
407 struct TheDarkKnight;
410 fn nothing_is_true(self) {}
414 knight: TheDarkKnight
418 let mut cave = Batcave {
419 knight: TheDarkKnight
421 let borrowed = &mut cave;
423 borrowed.knight.nothing_is_true(); // E0507
427 It is fine only if you put something back. `mem::replace` can be used for that:
430 # struct TheDarkKnight;
431 # impl TheDarkKnight { fn nothing_is_true(self) {} }
432 # struct Batcave { knight: TheDarkKnight }
435 let mut cave = Batcave {
436 knight: TheDarkKnight
438 let borrowed = &mut cave;
440 mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok!
443 You can find more information about borrowing in the rust-book:
444 http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html
448 A value was moved out of a non-copy fixed-size array.
450 Example of erroneous code:
452 ```compile_fail,E0508
456 let array = [NonCopy; 1];
457 let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`,
458 // a non-copy fixed-size array
462 The first element was moved out of the array, but this is not
463 possible because `NonCopy` does not implement the `Copy` trait.
465 Consider borrowing the element instead of moving it:
471 let array = [NonCopy; 1];
472 let _value = &array[0]; // Borrowing is allowed, unlike moving.
476 Alternatively, if your type implements `Clone` and you need to own the value,
477 consider borrowing and then cloning:
484 let array = [NonCopy; 1];
485 // Now you can clone the array element.
486 let _value = array[0].clone();
492 This error occurs when an attempt is made to move out of a value whose type
493 implements the `Drop` trait.
495 Example of erroneous code:
497 ```compile_fail,E0509
506 impl Drop for DropStruct {
508 // Destruct DropStruct, possibly using FancyNum
513 let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
514 let fancy_field = drop_struct.fancy; // Error E0509
515 println!("Fancy: {}", fancy_field.num);
516 // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
520 Here, we tried to move a field out of a struct of type `DropStruct` which
521 implements the `Drop` trait. However, a struct cannot be dropped if one or
522 more of its fields have been moved.
524 Structs implementing the `Drop` trait have an implicit destructor that gets
525 called when they go out of scope. This destructor may use the fields of the
526 struct, so moving out of the struct could make it impossible to run the
527 destructor. Therefore, we must think of all values whose type implements the
528 `Drop` trait as single units whose fields cannot be moved.
530 This error can be fixed by creating a reference to the fields of a struct,
531 enum, or tuple using the `ref` keyword:
542 impl Drop for DropStruct {
544 // Destruct DropStruct, possibly using FancyNum
549 let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
550 let ref fancy_field = drop_struct.fancy; // No more errors!
551 println!("Fancy: {}", fancy_field.num);
552 // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
556 Note that this technique can also be used in the arms of a match expression:
567 impl Drop for DropEnum {
569 // Destruct DropEnum, possibly using FancyNum
574 // Creates and enum of type `DropEnum`, which implements `Drop`
575 let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
577 // Creates a reference to the inside of `DropEnum::Fancy`
578 DropEnum::Fancy(ref fancy_field) => // No error!
579 println!("It was fancy-- {}!", fancy_field.num),
581 // implicit call to `drop_enum.drop()` as drop_enum goes out of scope
587 Closures cannot mutate immutable captured variables.
589 Erroneous code example:
591 ```compile_fail,E0595
592 let x = 3; // error: closure cannot assign to immutable local variable `x`
593 let mut c = || { x += 1 };
596 Make the variable binding mutable:
599 let mut x = 3; // ok!
600 let mut c = || { x += 1 };
605 This error occurs because you tried to mutably borrow a non-mutable variable.
607 Example of erroneous code:
609 ```compile_fail,E0596
611 let y = &mut x; // error: cannot borrow mutably
614 In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
615 fails. To fix this error, you need to make `x` mutable:
619 let y = &mut x; // ok!
624 This error occurs because a borrow was made inside a variable which has a
625 greater lifetime than the borrowed one.
627 Example of erroneous code:
629 ```compile_fail,E0597
634 let mut x = Foo { x: None };
636 x.x = Some(&y); // error: `y` does not live long enough
639 In here, `x` is created before `y` and therefore has a greater lifetime. Always
640 keep in mind that values in a scope are dropped in the opposite order they are
641 created. So to fix the previous example, just make the `y` lifetime greater than
650 let mut x = Foo { x: None };
657 register_diagnostics! {
658 // E0385, // {} in an aliasable location
659 E0594, // cannot assign to {}
660 E0598, // lifetime of {} is too short to guarantee its contents can be...