]> git.lizzy.rs Git - rust.git/commitdiff
Add detailed error explanation for E0504
authorTaylor Cramer <cramertj@cs.washington.edu>
Tue, 3 May 2016 18:56:25 +0000 (11:56 -0700)
committerTaylor Cramer <cramertj@cs.washington.edu>
Mon, 9 May 2016 18:05:11 +0000 (11:05 -0700)
Removed unnecessary use of threads from E0504

Cleaned up line ending on E0504

Added more examples for E0504

Changed to erroneous code wording

Switched Rc example to thread/Arc example

Added comments describing why errors no longer occur

src/librustc_borrowck/diagnostics.rs

index 03fb5260c39920a5246a59ec2bf53717c055812a..1802ab43161fbc4ca4086bfcf936442533a1e733 100644 (file)
@@ -454,6 +454,110 @@ fn foo(a: &mut i32) {
 ```
 "##,
 
+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.
 
@@ -661,7 +765,6 @@ fn main() {
     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