| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
| // file at the top-level directory of this distribution and at |
| // http://rust-lang.org/COPYRIGHT. |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| |
| #![allow(non_snake_case)] |
| |
| register_long_diagnostics! { |
| |
| E0373: r##" |
| This error occurs when an attempt is made to use data captured by a closure, |
| when that data may no longer exist. It's most commonly seen when attempting to |
| return a closure: |
| |
| ```compile_fail |
| fn foo() -> Box<Fn(u32) -> u32> { |
| let x = 0u32; |
| Box::new(|y| x + y) |
| } |
| ``` |
| |
| Notice that `x` is stack-allocated by `foo()`. By default, Rust captures |
| closed-over data by reference. This means that once `foo()` returns, `x` no |
| longer exists. An attempt to access `x` within the closure would thus be |
| unsafe. |
| |
| Another situation where this might be encountered is when spawning threads: |
| |
| ```compile_fail |
| fn foo() { |
| let x = 0u32; |
| let y = 1u32; |
| |
| let thr = std::thread::spawn(|| { |
| x + y |
| }); |
| } |
| ``` |
| |
| Since our new thread runs in parallel, the stack frame containing `x` and `y` |
| may well have disappeared by the time we try to use them. Even if we call |
| `thr.join()` within foo (which blocks until `thr` has completed, ensuring the |
| stack frame won't disappear), we will not succeed: the compiler cannot prove |
| that this behaviour is safe, and so won't let us do it. |
| |
| The solution to this problem is usually to switch to using a `move` closure. |
| This approach moves (or copies, where possible) data into the closure, rather |
| than taking references to it. For example: |
| |
| ``` |
| fn foo() -> Box<Fn(u32) -> u32> { |
| let x = 0u32; |
| Box::new(move |y| x + y) |
| } |
| ``` |
| |
| Now that the closure has its own copy of the data, there's no need to worry |
| about safety. |
| "##, |
| |
| E0381: r##" |
| It is not allowed to use or capture an uninitialized variable. For example: |
| |
| ```compile_fail |
| fn main() { |
| let x: i32; |
| let y = x; // error, use of possibly uninitialized variable |
| } |
| ``` |
| |
| To fix this, ensure that any declared variables are initialized before being |
| used. Example: |
| |
| ``` |
| fn main() { |
| let x: i32 = 0; |
| let y = x; // ok! |
| } |
| ``` |
| "##, |
| |
| E0382: r##" |
| This error occurs when an attempt is made to use a variable after its contents |
| have been moved elsewhere. For example: |
| |
| ```compile_fail |
| struct MyStruct { s: u32 } |
| |
| fn main() { |
| let mut x = MyStruct{ s: 5u32 }; |
| let y = x; |
| x.s = 6; |
| println!("{}", x.s); |
| } |
| ``` |
| |
| Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out |
| of `x` when we set `y`. This is fundamental to Rust's ownership system: outside |
| of workarounds like `Rc`, a value cannot be owned by more than one variable. |
| |
| If we own the type, the easiest way to address this problem is to implement |
| `Copy` and `Clone` on it, as shown below. This allows `y` to copy the |
| information in `x`, while leaving the original version owned by `x`. Subsequent |
| changes to `x` will not be reflected when accessing `y`. |
| |
| ``` |
| #[derive(Copy, Clone)] |
| struct MyStruct { s: u32 } |
| |
| fn main() { |
| let mut x = MyStruct{ s: 5u32 }; |
| let y = x; |
| x.s = 6; |
| println!("{}", x.s); |
| } |
| ``` |
| |
| Alternatively, if we don't control the struct's definition, or mutable shared |
| ownership is truly required, we can use `Rc` and `RefCell`: |
| |
| ``` |
| use std::cell::RefCell; |
| use std::rc::Rc; |
| |
| struct MyStruct { s: u32 } |
| |
| fn main() { |
| let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 })); |
| let y = x.clone(); |
| x.borrow_mut().s = 6; |
| println!("{}", x.borrow().s); |
| } |
| ``` |
| |
| With this approach, x and y share ownership of the data via the `Rc` (reference |
| count type). `RefCell` essentially performs runtime borrow checking: ensuring |
| that at most one writer or multiple readers can access the data at any one time. |
| |
| If you wish to learn more about ownership in Rust, start with the chapter in the |
| Book: |
| |
| https://doc.rust-lang.org/book/ownership.html |
| "##, |
| |
| E0383: r##" |
| This error occurs when an attempt is made to partially reinitialize a |
| structure that is currently uninitialized. |
| |
| For example, this can happen when a drop has taken place: |
| |
| ```ignore |
| struct Foo { |
| a: u32, |
| } |
| |
| let mut x = Foo { a: 1 }; |
| drop(x); // `x` is now uninitialized |
| x.a = 2; // error, partial reinitialization of uninitialized structure `t` |
| ``` |
| |
| This error can be fixed by fully reinitializing the structure in question: |
| |
| ``` |
| struct Foo { |
| a: u32, |
| } |
| |
| let mut x = Foo { a: 1 }; |
| drop(x); |
| x = Foo { a: 2 }; |
| ``` |
| "##, |
| |
| E0384: r##" |
| This error occurs when an attempt is made to reassign an immutable variable. |
| For example: |
| |
| ```compile_fail |
| fn main(){ |
| let x = 3; |
| x = 5; // error, reassignment of immutable variable |
| } |
| ``` |
| |
| By default, variables in Rust are immutable. To fix this error, add the keyword |
| `mut` after the keyword `let` when declaring the variable. For example: |
| |
| ``` |
| fn main(){ |
| let mut x = 3; |
| x = 5; |
| } |
| ``` |
| "##, |
| |
| E0386: r##" |
| This error occurs when an attempt is made to mutate the target of a mutable |
| reference stored inside an immutable container. |
| |
| For example, this can happen when storing a `&mut` inside an immutable `Box`: |
| |
| ```compile_fail |
| let mut x: i64 = 1; |
| let y: Box<_> = Box::new(&mut x); |
| **y = 2; // error, cannot assign to data in an immutable container |
| ``` |
| |
| This error can be fixed by making the container mutable: |
| |
| ``` |
| let mut x: i64 = 1; |
| let mut y: Box<_> = Box::new(&mut x); |
| **y = 2; |
| ``` |
| |
| It can also be fixed by using a type with interior mutability, such as `Cell` |
| or `RefCell`: |
| |
| ``` |
| use std::cell::Cell; |
| |
| let x: i64 = 1; |
| let y: Box<Cell<_>> = Box::new(Cell::new(x)); |
| y.set(2); |
| ``` |
| "##, |
| |
| E0387: r##" |
| This error occurs when an attempt is made to mutate or mutably reference data |
| that a closure has captured immutably. Examples of this error are shown below: |
| |
| ```compile_fail |
| // Accepts a function or a closure that captures its environment immutably. |
| // Closures passed to foo will not be able to mutate their closed-over state. |
| fn foo<F: Fn()>(f: F) { } |
| |
| // Attempts to mutate closed-over data. Error message reads: |
| // `cannot assign to data in a captured outer variable...` |
| fn mutable() { |
| let mut x = 0u32; |
| foo(|| x = 2); |
| } |
| |
| // Attempts to take a mutable reference to closed-over data. Error message |
| // reads: `cannot borrow data mutably in a captured outer variable...` |
| fn mut_addr() { |
| let mut x = 0u32; |
| foo(|| { let y = &mut x; }); |
| } |
| ``` |
| |
| The problem here is that foo is defined as accepting a parameter of type `Fn`. |
| Closures passed into foo will thus be inferred to be of type `Fn`, meaning that |
| they capture their context immutably. |
| |
| If the definition of `foo` is under your control, the simplest solution is to |
| capture the data mutably. This can be done by defining `foo` to take FnMut |
| rather than Fn: |
| |
| ``` |
| fn foo<F: FnMut()>(f: F) { } |
| ``` |
| |
| Alternatively, we can consider using the `Cell` and `RefCell` types to achieve |
| interior mutability through a shared reference. Our example's `mutable` |
| function could be redefined as below: |
| |
| ``` |
| use std::cell::Cell; |
| |
| fn foo<F: Fn()>(f: F) { } |
| |
| fn mutable() { |
| let x = Cell::new(0u32); |
| foo(|| x.set(2)); |
| } |
| ``` |
| |
| You can read more about cell types in the API documentation: |
| |
| https://doc.rust-lang.org/std/cell/ |
| "##, |
| |
| E0389: r##" |
| An attempt was made to mutate data using a non-mutable reference. This |
| commonly occurs when attempting to assign to a non-mutable reference of a |
| mutable reference (`&(&mut T)`). |
| |
| Example of erroneous code: |
| |
| ```compile_fail |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy = FancyNum{ num: 5 }; |
| let fancy_ref = &(&mut fancy); |
| fancy_ref.num = 6; // error: cannot assign to data in a `&` reference |
| println!("{}", fancy_ref.num); |
| } |
| ``` |
| |
| Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an |
| immutable reference to a value borrows it immutably. There can be multiple |
| references of type `&(&mut T)` that point to the same value, so they must be |
| immutable to prevent multiple mutable references to the same value. |
| |
| To fix this, either remove the outer reference: |
| |
| ``` |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy = FancyNum{ num: 5 }; |
| |
| let fancy_ref = &mut fancy; |
| // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum) |
| |
| fancy_ref.num = 6; // No error! |
| |
| println!("{}", fancy_ref.num); |
| } |
| ``` |
| |
| Or make the outer reference mutable: |
| |
| ``` |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy = FancyNum{ num: 5 }; |
| |
| let fancy_ref = &mut (&mut fancy); |
| // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum) |
| |
| fancy_ref.num = 6; // No error! |
| |
| println!("{}", fancy_ref.num); |
| } |
| ``` |
| "##, |
| |
| E0499: r##" |
| A variable was borrowed as mutable more than once. Erroneous code example: |
| |
| ```compile_fail |
| let mut i = 0; |
| let mut x = &mut i; |
| let mut a = &mut i; |
| // error: cannot borrow `i` as mutable more than once at a time |
| ``` |
| |
| Please note that in rust, you can either have many immutable references, or one |
| mutable reference. Take a look at |
| https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more |
| information. Example: |
| |
| |
| ``` |
| let mut i = 0; |
| let mut x = &mut i; // ok! |
| |
| // or: |
| let mut i = 0; |
| let a = &i; // ok! |
| let b = &i; // still ok! |
| let c = &i; // still ok! |
| ``` |
| "##, |
| |
| E0500: r##" |
| A borrowed variable was used in another closure. Example of erroneous code: |
| |
| ```compile_fail |
| fn you_know_nothing(jon_snow: &mut i32) { |
| let nights_watch = || { |
| *jon_snow = 2; |
| }; |
| let starks = || { |
| *jon_snow = 3; // error: closure requires unique access to `jon_snow` |
| // but it is already borrowed |
| }; |
| } |
| ``` |
| |
| In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it |
| cannot be borrowed by the `starks` closure at the same time. To fix this issue, |
| you can put the closure in its own scope: |
| |
| ``` |
| fn you_know_nothing(jon_snow: &mut i32) { |
| { |
| let nights_watch = || { |
| *jon_snow = 2; |
| }; |
| } // At this point, `jon_snow` is free. |
| let starks = || { |
| *jon_snow = 3; |
| }; |
| } |
| ``` |
| |
| Or, if the type implements the `Clone` trait, you can clone it between |
| closures: |
| |
| ``` |
| fn you_know_nothing(jon_snow: &mut i32) { |
| let mut jon_copy = jon_snow.clone(); |
| let nights_watch = || { |
| jon_copy = 2; |
| }; |
| let starks = || { |
| *jon_snow = 3; |
| }; |
| } |
| ``` |
| "##, |
| |
| E0501: r##" |
| This error indicates that a mutable variable is being used while it is still |
| captured by a closure. Because the closure has borrowed the variable, it is not |
| available for use until the closure goes out of scope. |
| |
| Note that a capture will either move or borrow a variable, but in this |
| situation, the closure is borrowing the variable. Take a look at |
| http://rustbyexample.com/fn/closures/capture.html for more information about |
| capturing. |
| |
| Example of erroneous code: |
| |
| ```compile_fail |
| fn inside_closure(x: &mut i32) { |
| // Actions which require unique access |
| } |
| |
| fn outside_closure(x: &mut i32) { |
| // Actions which require unique access |
| } |
| |
| fn foo(a: &mut i32) { |
| let bar = || { |
| inside_closure(a) |
| }; |
| outside_closure(a); // error: cannot borrow `*a` as mutable because previous |
| // closure requires unique access. |
| } |
| ``` |
| |
| To fix this error, you can place the closure in its own scope: |
| |
| ``` |
| fn inside_closure(x: &mut i32) {} |
| fn outside_closure(x: &mut i32) {} |
| |
| fn foo(a: &mut i32) { |
| { |
| let bar = || { |
| inside_closure(a) |
| }; |
| } // borrow on `a` ends. |
| outside_closure(a); // ok! |
| } |
| ``` |
| |
| Or you can pass the variable as a parameter to the closure: |
| |
| ``` |
| fn inside_closure(x: &mut i32) {} |
| fn outside_closure(x: &mut i32) {} |
| |
| fn foo(a: &mut i32) { |
| let bar = |s: &mut i32| { |
| inside_closure(s) |
| }; |
| outside_closure(a); |
| bar(a); |
| } |
| ``` |
| |
| It may be possible to define the closure later: |
| |
| ``` |
| fn inside_closure(x: &mut i32) {} |
| fn outside_closure(x: &mut i32) {} |
| |
| fn foo(a: &mut i32) { |
| outside_closure(a); |
| let bar = || { |
| inside_closure(a) |
| }; |
| } |
| ``` |
| "##, |
| |
| E0502: r##" |
| This error indicates that you are trying to borrow a variable as mutable when it |
| has already been borrowed as immutable. |
| |
| Example of erroneous code: |
| |
| ```compile_fail |
| fn bar(x: &mut i32) {} |
| fn foo(a: &mut i32) { |
| let ref y = a; // a is borrowed as immutable. |
| bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed |
| // as immutable |
| } |
| ``` |
| |
| To fix this error, ensure that you don't have any other references to the |
| variable before trying to access it mutably: |
| |
| ``` |
| fn bar(x: &mut i32) {} |
| fn foo(a: &mut i32) { |
| bar(a); |
| let ref y = a; // ok! |
| } |
| ``` |
| |
| For more information on the rust ownership system, take a look at |
| https://doc.rust-lang.org/stable/book/references-and-borrowing.html. |
| "##, |
| |
| E0503: r##" |
| A value was used after it was mutably borrowed. |
| |
| Example of erroneous code: |
| |
| ```compile_fail |
| fn main() { |
| let mut value = 3; |
| // Create a mutable borrow of `value`. This borrow |
| // lives until the end of this function. |
| let _borrow = &mut value; |
| let _sum = value + 1; // error: cannot use `value` because |
| // it was mutably borrowed |
| } |
| ``` |
| |
| In this example, `value` is mutably borrowed by `borrow` and cannot be |
| used to calculate `sum`. This is not possible because this would violate |
| Rust's mutability rules. |
| |
| You can fix this error by limiting the scope of the borrow: |
| |
| ``` |
| fn main() { |
| let mut value = 3; |
| // By creating a new block, you can limit the scope |
| // of the reference. |
| { |
| let _borrow = &mut value; // Use `_borrow` inside this block. |
| } |
| // The block has ended and with it the borrow. |
| // You can now use `value` again. |
| let _sum = value + 1; |
| } |
| ``` |
| |
| Or by cloning `value` before borrowing it: |
| |
| ``` |
| fn main() { |
| let mut value = 3; |
| // We clone `value`, creating a copy. |
| let value_cloned = value.clone(); |
| // The mutable borrow is a reference to `value` and |
| // not to `value_cloned`... |
| let _borrow = &mut value; |
| // ... which means we can still use `value_cloned`, |
| let _sum = value_cloned + 1; |
| // even though the borrow only ends here. |
| } |
| ``` |
| |
| You can find more information about borrowing in the rust-book: |
| http://doc.rust-lang.org/stable/book/references-and-borrowing.html |
| "##, |
| |
| 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. |
| |
| Example of erroneous code: |
| |
| ```compile_fail |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy_num = FancyNum { num: 5 }; |
| let fancy_ref = &fancy_num; |
| fancy_num = FancyNum { num: 6 }; |
| // error: cannot assign to `fancy_num` because it is borrowed |
| |
| println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); |
| } |
| ``` |
| |
| Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't |
| be assigned to a new value as it would invalidate the reference. |
| |
| Alternatively, we can move out of `fancy_num` into a second `fancy_num`: |
| |
| ``` |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy_num = FancyNum { num: 5 }; |
| let moved_num = fancy_num; |
| fancy_num = FancyNum { num: 6 }; |
| |
| println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num); |
| } |
| ``` |
| |
| If the value has to be borrowed, try limiting the lifetime of the borrow using |
| a scoped block: |
| |
| ``` |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy_num = FancyNum { num: 5 }; |
| |
| { |
| let fancy_ref = &fancy_num; |
| println!("Ref: {}", fancy_ref.num); |
| } |
| |
| // Works because `fancy_ref` is no longer in scope |
| fancy_num = FancyNum { num: 6 }; |
| println!("Num: {}", fancy_num.num); |
| } |
| ``` |
| |
| Or by moving the reference into a function: |
| |
| ``` |
| struct FancyNum { |
| num: u8 |
| } |
| |
| fn main() { |
| let mut fancy_num = FancyNum { num: 5 }; |
| |
| print_fancy_ref(&fancy_num); |
| |
| // Works because function borrow has ended |
| fancy_num = FancyNum { num: 6 }; |
| println!("Num: {}", fancy_num.num); |
| } |
| |
| fn print_fancy_ref(fancy_ref: &FancyNum){ |
| println!("Ref: {}", fancy_ref.num); |
| } |
| ``` |
| "##, |
| |
| E0505: r##" |
| A value was moved out while it was still borrowed. |
| Erroneous code example: |
| |
| ```compile_fail |
| struct Value {} |
| |
| fn eat(val: Value) {} |
| |
| fn main() { |
| let x = Value{}; |
| { |
| let _ref_to_val: &Value = &x; |
| eat(x); |
| } |
| } |
| ``` |
| |
| Here, the function `eat` takes the ownership of `x`. However, |
| `x` cannot be moved because it was borrowed to `_ref_to_val`. |
| To fix that you can do few different things: |
| |
| * Try to avoid moving the variable. |
| * Release borrow before move. |
| * Implement the `Copy` trait on the type. |
| |
| Examples: |
| |
| ``` |
| struct Value {} |
| |
| fn eat(val: &Value) {} |
| |
| fn main() { |
| let x = Value{}; |
| { |
| let _ref_to_val: &Value = &x; |
| eat(&x); // pass by reference, if it's possible |
| } |
| } |
| ``` |
| |
| Or: |
| |
| ``` |
| struct Value {} |
| |
| fn eat(val: Value) {} |
| |
| fn main() { |
| let x = Value{}; |
| { |
| let _ref_to_val: &Value = &x; |
| } |
| eat(x); // release borrow and then move it. |
| } |
| ``` |
| |
| Or: |
| |
| ``` |
| #[derive(Clone, Copy)] // implement Copy trait |
| struct Value {} |
| |
| fn eat(val: Value) {} |
| |
| fn main() { |
| let x = Value{}; |
| { |
| let _ref_to_val: &Value = &x; |
| eat(x); // it will be copied here. |
| } |
| } |
| ``` |
| |
| You can find more information about borrowing in the rust-book: |
| http://doc.rust-lang.org/stable/book/references-and-borrowing.html |
| "##, |
| |
| E0507: r##" |
| You tried to move out of a value which was borrowed. Erroneous code example: |
| |
| ```compile_fail |
| use std::cell::RefCell; |
| |
| struct TheDarkKnight; |
| |
| impl TheDarkKnight { |
| fn nothing_is_true(self) {} |
| } |
| |
| fn main() { |
| let x = RefCell::new(TheDarkKnight); |
| |
| x.borrow().nothing_is_true(); // error: cannot move out of borrowed content |
| } |
| ``` |
| |
| Here, the `nothing_is_true` method takes the ownership of `self`. However, |
| `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, |
| which is a borrow of the content owned by the `RefCell`. To fix this error, |
| you have three choices: |
| |
| * Try to avoid moving the variable. |
| * Somehow reclaim the ownership. |
| * Implement the `Copy` trait on the type. |
| |
| Examples: |
| |
| ``` |
| use std::cell::RefCell; |
| |
| struct TheDarkKnight; |
| |
| impl TheDarkKnight { |
| fn nothing_is_true(&self) {} // First case, we don't take ownership |
| } |
| |
| fn main() { |
| let x = RefCell::new(TheDarkKnight); |
| |
| x.borrow().nothing_is_true(); // ok! |
| } |
| ``` |
| |
| Or: |
| |
| ``` |
| use std::cell::RefCell; |
| |
| struct TheDarkKnight; |
| |
| impl TheDarkKnight { |
| fn nothing_is_true(self) {} |
| } |
| |
| fn main() { |
| let x = RefCell::new(TheDarkKnight); |
| let x = x.into_inner(); // we get back ownership |
| |
| x.nothing_is_true(); // ok! |
| } |
| ``` |
| |
| Or: |
| |
| ``` |
| use std::cell::RefCell; |
| |
| #[derive(Clone, Copy)] // we implement the Copy trait |
| struct TheDarkKnight; |
| |
| impl TheDarkKnight { |
| fn nothing_is_true(self) {} |
| } |
| |
| fn main() { |
| let x = RefCell::new(TheDarkKnight); |
| |
| x.borrow().nothing_is_true(); // ok! |
| } |
| ``` |
| |
| Moving out of a member of a mutably borrowed struct is fine if you put something |
| back. `mem::replace` can be used for that: |
| |
| ```ignore |
| struct TheDarkKnight; |
| |
| impl TheDarkKnight { |
| fn nothing_is_true(self) {} |
| } |
| |
| struct Batcave { |
| knight: TheDarkKnight |
| } |
| |
| fn main() { |
| use std::mem; |
| |
| let mut cave = Batcave { |
| knight: TheDarkKnight |
| }; |
| let borrowed = &mut cave; |
| |
| borrowed.knight.nothing_is_true(); // E0507 |
| mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! |
| } |
| ``` |
| |
| You can find more information about borrowing in the rust-book: |
| http://doc.rust-lang.org/stable/book/references-and-borrowing.html |
| "##, |
| |
| E0508: r##" |
| A value was moved out of a non-copy fixed-size array. |
| |
| Example of erroneous code: |
| |
| ```compile_fail |
| struct NonCopy; |
| |
| fn main() { |
| let array = [NonCopy; 1]; |
| let _value = array[0]; // error: cannot move out of type `[NonCopy; 1]`, |
| // a non-copy fixed-size array |
| } |
| ``` |
| |
| The first element was moved out of the array, but this is not |
| possible because `NonCopy` does not implement the `Copy` trait. |
| |
| Consider borrowing the element instead of moving it: |
| |
| ``` |
| struct NonCopy; |
| |
| fn main() { |
| let array = [NonCopy; 1]; |
| let _value = &array[0]; // Borrowing is allowed, unlike moving. |
| } |
| ``` |
| |
| Alternatively, if your type implements `Clone` and you need to own the value, |
| consider borrowing and then cloning: |
| |
| ``` |
| #[derive(Clone)] |
| struct NonCopy; |
| |
| fn main() { |
| let array = [NonCopy; 1]; |
| // Now you can clone the array element. |
| let _value = array[0].clone(); |
| } |
| ``` |
| "##, |
| |
| 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! { |
| E0385, // {} in an aliasable location |
| E0388, // {} in a static location |
| E0524, // two closures require unique access to `..` at the same time |
| } |