Rollup merge of #33383 - cramertj:E0509, r=Manishearth
Add detailed error explanation for E0509 Part of #32777
This commit is contained in:
commit
57fa783d3c
@ -653,6 +653,101 @@ You can find more information about borrowing in the rust-book:
|
||||
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! {
|
||||
@ -664,6 +759,5 @@ register_diagnostics! {
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user