Skip to content

Commit

Permalink
Add detailed error explanation for E0504
Browse files Browse the repository at this point in the history
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
  • Loading branch information
cramertj committed May 9, 2016
1 parent af0a433 commit 38a5338
Showing 1 changed file with 104 additions and 1 deletion.
105 changes: 104 additions & 1 deletion src/librustc_borrowck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -661,7 +765,6 @@ 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
Expand Down

0 comments on commit 38a5338

Please sign in to comment.