Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add detailed error explanation for E0504 #33386

Merged
merged 1 commit into from
May 11, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is causing compilation to fail; it makes the error above invalid. you need to include a closing }

"##,

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