```
"##,
+ E0504: r##"
+ This error occurs when an attempt is made to move a borrowed variable into a
+ closure.
+
+ Example of erroneous code:
+
+ ```compile_fail
+ struct FancyNum {
+ num: u8
+ }
+
+ fn main() {
+ let fancy_num = FancyNum { num: 5 };
+ let fancy_ref = &fancy_num;
+
+ let x = move || {
+ println!("child function: {}", fancy_num.num);
+ // error: cannot move `fancy_num` into closure because it is borrowed
+ };
+
+ x();
+ println!("main function: {}", fancy_ref.num);
+ }
+ ```
+
+ Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into
+ the closure `x`. There is no way to move a value into a closure while it is
+ borrowed, as that would invalidate the borrow.
+
+ If the closure can't outlive the value being moved, try using a reference
+ rather than moving:
+
+ ```
+ struct FancyNum {
+ num: u8
+ }
+
+ fn main() {
+ let fancy_num = FancyNum { num: 5 };
+ let fancy_ref = &fancy_num;
+
+ let x = move || {
+ // fancy_ref is usable here because it doesn't move `fancy_num`
+ println!("child function: {}", fancy_ref.num);
+ };
+
+ x();
+
+ println!("main function: {}", fancy_num.num);
+ }
+ ```
+
+ If the value has to be borrowed and then moved, try limiting the lifetime of
+ the borrow using a scoped block:
+
+ ```
+ struct FancyNum {
+ num: u8
+ }
+
+ fn main() {
+ let fancy_num = FancyNum { num: 5 };
+
+ {
+ let fancy_ref = &fancy_num;
+ println!("main function: {}", fancy_ref.num);
+ // `fancy_ref` goes out of scope here
+ }
+
+ let x = move || {
+ // `fancy_num` can be moved now (no more references exist)
+ println!("child function: {}", fancy_num.num);
+ };
+
+ x();
+ }
+ ```
+
+ If the lifetime of a reference isn't enough, such as in the case of threading,
+ consider using an `Arc` to create a reference-counted value:
+
+ ```
+ use std::sync::Arc;
+ use std::thread;
+
+ struct FancyNum {
+ num: u8
+ }
+
+ fn main() {
+ let fancy_ref1 = Arc::new(FancyNum { num: 5 });
+ let fancy_ref2 = fancy_ref1.clone();
+
+ let x = thread::spawn(move || {
+ // `fancy_ref1` can be moved and has a `'static` lifetime
+ println!("child thread: {}", fancy_ref1.num);
+ });
+
+ x.join().expect("child thread should finish");
+ println!("main thread: {}", fancy_ref2.num);
+ }
+ ```
+ "##,
+
E0506: r##"
This error occurs when an attempt is made to assign to a borrowed value.
http://doc.rust-lang.org/stable/book/references-and-borrowing.html
"##,
+E0509: r##"
+This error occurs when an attempt is made to move out of a value whose type
+implements the `Drop` trait.
+
+Example of erroneous code:
+
+```compile_fail
+struct FancyNum {
+ num: usize
+}
+
+struct DropStruct {
+ fancy: FancyNum
+}
+
+impl Drop for DropStruct {
+ fn drop(&mut self) {
+ // Destruct DropStruct, possibly using FancyNum
+ }
+}
+
+fn main() {
+ let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
+ let fancy_field = drop_struct.fancy; // Error E0509
+ println!("Fancy: {}", fancy_field.num);
+ // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
+}
+```
+
+Here, we tried to move a field out of a struct of type `DropStruct` which
+implements the `Drop` trait. However, a struct cannot be dropped if one or
+more of its fields have been moved.
+
+Structs implementing the `Drop` trait have an implicit destructor that gets
+called when they go out of scope. This destructor may use the fields of the
+struct, so moving out of the struct could make it impossible to run the
+destructor. Therefore, we must think of all values whose type implements the
+`Drop` trait as single units whose fields cannot be moved.
+
+This error can be fixed by creating a reference to the fields of a struct,
+enum, or tuple using the `ref` keyword:
+
+```
+struct FancyNum {
+ num: usize
+}
+
+struct DropStruct {
+ fancy: FancyNum
+}
+
+impl Drop for DropStruct {
+ fn drop(&mut self) {
+ // Destruct DropStruct, possibly using FancyNum
+ }
+}
+
+fn main() {
+ let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
+ let ref fancy_field = drop_struct.fancy; // No more errors!
+ println!("Fancy: {}", fancy_field.num);
+ // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
+}
+```
+
+Note that this technique can also be used in the arms of a match expression:
+
+```
+struct FancyNum {
+ num: usize
+}
+
+enum DropEnum {
+ Fancy(FancyNum)
+}
+
+impl Drop for DropEnum {
+ fn drop(&mut self) {
+ // Destruct DropEnum, possibly using FancyNum
+ }
+}
+
+fn main() {
+ // Creates and enum of type `DropEnum`, which implements `Drop`
+ let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
+ match drop_enum {
+ // Creates a reference to the inside of `DropEnum::Fancy`
+ DropEnum::Fancy(ref fancy_field) => // No error!
+ println!("It was fancy-- {}!", fancy_field.num),
+ }
+ // implicit call to `drop_enum.drop()` as drop_enum goes out of scope
+}
+```
+"##,
+
}
register_diagnostics! {
E0500, // closure requires unique access to `..` but .. is already borrowed
E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
E0503, // cannot use `..` because it was mutably borrowed
- E0504, // cannot move `..` into closure because it is borrowed
E0505, // cannot move out of `..` because it is borrowed
E0508, // cannot move out of type `..`, a non-copy fixed-size array
- E0509, // cannot move out of type `..`, which defines the `Drop` trait
E0524, // two closures require unique access to `..` at the same time
}