@@ -429,6 +429,101 @@ You can find more information about borrowing in the rust-book:
429
429
http://doc.rust-lang.org/stable/book/references-and-borrowing.html
430
430
"## ,
431
431
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
+
432
527
}
433
528
434
529
register_diagnostics ! {
@@ -443,6 +538,5 @@ register_diagnostics! {
443
538
E0505 , // cannot move out of `..` because it is borrowed
444
539
E0506 , // cannot assign to `..` because it is borrowed
445
540
E0508 , // cannot move out of type `..`, a non-copy fixed-size array
446
- E0509 , // cannot move out of type `..`, which defines the `Drop` trait
447
541
E0524 , // two closures require unique access to `..` at the same time
448
542
}
0 commit comments