Rust errors / Ownership and borrowing
Rust compiler error · checked with rustc 1.99.0
Rust error E0509: cannot move out of type `DropStruct`, which implements the `Drop` trait
What it meansThis error occurs when an attempt is made to move out of a value whose type implements the Drop trait.
What rustc prints
error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait --> main.rs:17:23 | 17 | let fancy_field = drop_struct.fancy; // Error E0509 | ^^^^^^^^^^^^^^^^^ | | | cannot move out of here | move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait | note: if `FancyNum` implemented `Clone`, you could clone the value --> main.rs:1:1 | 1 | struct FancyNum { | ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type ... 17 | let fancy_field = drop_struct.fancy; // Error E0509 | ----------------- you could clone this value help: consider borrowing here | 17 | let fancy_field = &drop_struct.fancy; // Error E0509 | +
Real output of rustc 1.99.0 compiling the official example below (2021 edition). Your names and line numbers will differ; the first line is the part to match.
The compiler team's explanation
This error occurs when an attempt is made to move out of a value whose type implements the Drop trait.
Erroneous code example:
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
}From rustc --explain E0509 (1.99.0), part of the Rust project, MIT or Apache-2.0. Official page.
Related errors
- E0382borrow of moved value
- E0499cannot borrow as mutable more than once at a time
- E0502cannot borrow as mutable because it is also borrowed as immutable
- E0106missing lifetime specifier
- E0507cannot move out of
- E0508cannot move out of type `[NonCopy; 1]`, a non-copy array
- E0521borrowed data escapes outside of closure
- E0557feature has been removed
Up next
Often hit nextE0382: borrow of moved valueA related error from the same family.Read it next →Did this answer your question?