@@ -429,6 +429,101 @@ You can find more information about borrowing in the rust-book:
429429http://doc.rust-lang.org/stable/book/references-and-borrowing.html
430430"## ,
431431
432+ E0509 : r##"
433+ This error occurs when an attempt is made to move out of a value whose type
434+ implements the `Drop` trait.
435+
436+ Example of erroneous code:
437+
438+ ```compile_fail
439+ struct FancyNum {
440+ num: usize
441+ }
442+
443+ struct DropStruct {
444+ fancy: FancyNum
445+ }
446+
447+ impl Drop for DropStruct {
448+ fn drop(&mut self) {
449+ // Destruct DropStruct, possibly using FancyNum
450+ }
451+ }
452+
453+ fn main() {
454+ let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
455+ let fancy_field = drop_struct.fancy; // Error E0509
456+ println!("Fancy: {}", fancy_field.num);
457+ // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
458+ }
459+ ```
460+
461+ Here, we tried to move a field out of a struct of type `DropStruct` which
462+ implements the `Drop` trait. However, a struct cannot be dropped if one or
463+ more of its fields have been moved.
464+
465+ Structs implementing the `Drop` trait have an implicit destructor that gets
466+ called when they go out of scope. This destructor may use the fields of the
467+ struct, so moving out of the struct could make it impossible to run the
468+ destructor. Therefore, we must think of all values whose type implements the
469+ `Drop` trait as single units whose fields cannot be moved.
470+
471+ This error can be fixed by creating a reference to the fields of a struct,
472+ enum, or tuple using the `ref` keyword:
473+
474+ ```
475+ struct FancyNum {
476+ num: usize
477+ }
478+
479+ struct DropStruct {
480+ fancy: FancyNum
481+ }
482+
483+ impl Drop for DropStruct {
484+ fn drop(&mut self) {
485+ // Destruct DropStruct, possibly using FancyNum
486+ }
487+ }
488+
489+ fn main() {
490+ let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
491+ let ref fancy_field = drop_struct.fancy; // No more errors!
492+ println!("Fancy: {}", fancy_field.num);
493+ // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
494+ }
495+ ```
496+
497+ Note that this technique can also be used in the arms of a match expression:
498+
499+ ```
500+ struct FancyNum {
501+ num: usize
502+ }
503+
504+ enum DropEnum {
505+ Fancy(FancyNum)
506+ }
507+
508+ impl Drop for DropEnum {
509+ fn drop(&mut self) {
510+ // Destruct DropEnum, possibly using FancyNum
511+ }
512+ }
513+
514+ fn main() {
515+ // Creates and enum of type `DropEnum`, which implements `Drop`
516+ let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
517+ match drop_enum {
518+ // Creates a reference to the inside of `DropEnum::Fancy`
519+ DropEnum::Fancy(ref fancy_field) => // No error!
520+ println!("It was fancy-- {}!", fancy_field.num),
521+ }
522+ // implicit call to `drop_enum.drop()` as drop_enum goes out of scope
523+ }
524+ ```
525+ "## ,
526+
432527}
433528
434529register_diagnostics ! {
@@ -443,6 +538,5 @@ register_diagnostics! {
443538 E0505 , // cannot move out of `..` because it is borrowed
444539 E0506 , // cannot assign to `..` because it is borrowed
445540 E0508 , // cannot move out of type `..`, a non-copy fixed-size array
446- E0509 , // cannot move out of type `..`, which defines the `Drop` trait
447541 E0524 , // two closures require unique access to `..` at the same time
448542}
0 commit comments