@@ -653,6 +653,101 @@ You can find more information about borrowing in the rust-book:
653653http://doc.rust-lang.org/stable/book/references-and-borrowing.html
654654"## ,
655655
656+ E0509 : r##"
657+ This error occurs when an attempt is made to move out of a value whose type
658+ implements the `Drop` trait.
659+
660+ Example of erroneous code:
661+
662+ ```compile_fail
663+ struct FancyNum {
664+ num: usize
665+ }
666+
667+ struct DropStruct {
668+ fancy: FancyNum
669+ }
670+
671+ impl Drop for DropStruct {
672+ fn drop(&mut self) {
673+ // Destruct DropStruct, possibly using FancyNum
674+ }
675+ }
676+
677+ fn main() {
678+ let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
679+ let fancy_field = drop_struct.fancy; // Error E0509
680+ println!("Fancy: {}", fancy_field.num);
681+ // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
682+ }
683+ ```
684+
685+ Here, we tried to move a field out of a struct of type `DropStruct` which
686+ implements the `Drop` trait. However, a struct cannot be dropped if one or
687+ more of its fields have been moved.
688+
689+ Structs implementing the `Drop` trait have an implicit destructor that gets
690+ called when they go out of scope. This destructor may use the fields of the
691+ struct, so moving out of the struct could make it impossible to run the
692+ destructor. Therefore, we must think of all values whose type implements the
693+ `Drop` trait as single units whose fields cannot be moved.
694+
695+ This error can be fixed by creating a reference to the fields of a struct,
696+ enum, or tuple using the `ref` keyword:
697+
698+ ```
699+ struct FancyNum {
700+ num: usize
701+ }
702+
703+ struct DropStruct {
704+ fancy: FancyNum
705+ }
706+
707+ impl Drop for DropStruct {
708+ fn drop(&mut self) {
709+ // Destruct DropStruct, possibly using FancyNum
710+ }
711+ }
712+
713+ fn main() {
714+ let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
715+ let ref fancy_field = drop_struct.fancy; // No more errors!
716+ println!("Fancy: {}", fancy_field.num);
717+ // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
718+ }
719+ ```
720+
721+ Note that this technique can also be used in the arms of a match expression:
722+
723+ ```
724+ struct FancyNum {
725+ num: usize
726+ }
727+
728+ enum DropEnum {
729+ Fancy(FancyNum)
730+ }
731+
732+ impl Drop for DropEnum {
733+ fn drop(&mut self) {
734+ // Destruct DropEnum, possibly using FancyNum
735+ }
736+ }
737+
738+ fn main() {
739+ // Creates and enum of type `DropEnum`, which implements `Drop`
740+ let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
741+ match drop_enum {
742+ // Creates a reference to the inside of `DropEnum::Fancy`
743+ DropEnum::Fancy(ref fancy_field) => // No error!
744+ println!("It was fancy-- {}!", fancy_field.num),
745+ }
746+ // implicit call to `drop_enum.drop()` as drop_enum goes out of scope
747+ }
748+ ```
749+ "## ,
750+
656751}
657752
658753register_diagnostics ! {
@@ -664,6 +759,5 @@ register_diagnostics! {
664759 E0504 , // cannot move `..` into closure because it is borrowed
665760 E0505 , // cannot move out of `..` because it is borrowed
666761 E0508 , // cannot move out of type `..`, a non-copy fixed-size array
667- E0509 , // cannot move out of type `..`, which defines the `Drop` trait
668762 E0524 , // two closures require unique access to `..` at the same time
669763}
0 commit comments