@@ -653,6 +653,101 @@ You can find more information about borrowing in the rust-book:
653
653
http://doc.rust-lang.org/stable/book/references-and-borrowing.html
654
654
"## ,
655
655
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
+
656
751
}
657
752
658
753
register_diagnostics ! {
@@ -664,6 +759,5 @@ register_diagnostics! {
664
759
E0504 , // cannot move `..` into closure because it is borrowed
665
760
E0505 , // cannot move out of `..` because it is borrowed
666
761
E0508 , // cannot move out of type `..`, a non-copy fixed-size array
667
- E0509 , // cannot move out of type `..`, which defines the `Drop` trait
668
762
E0524 , // two closures require unique access to `..` at the same time
669
763
}
0 commit comments