]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_error_codes/src/error_codes/E0509.md
Rollup merge of #92310 - ehuss:rustdoc-ice, r=estebank
[rust.git] / compiler / rustc_error_codes / src / error_codes / E0509.md
1 This error occurs when an attempt is made to move out of a value whose type
2 implements the `Drop` trait.
3
4 Erroneous code example:
5
6 ```compile_fail,E0509
7 struct FancyNum {
8     num: usize
9 }
10
11 struct DropStruct {
12     fancy: FancyNum
13 }
14
15 impl Drop for DropStruct {
16     fn drop(&mut self) {
17         // Destruct DropStruct, possibly using FancyNum
18     }
19 }
20
21 fn main() {
22     let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
23     let fancy_field = drop_struct.fancy; // Error E0509
24     println!("Fancy: {}", fancy_field.num);
25     // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
26 }
27 ```
28
29 Here, we tried to move a field out of a struct of type `DropStruct` which
30 implements the `Drop` trait. However, a struct cannot be dropped if one or
31 more of its fields have been moved.
32
33 Structs implementing the `Drop` trait have an implicit destructor that gets
34 called when they go out of scope. This destructor may use the fields of the
35 struct, so moving out of the struct could make it impossible to run the
36 destructor. Therefore, we must think of all values whose type implements the
37 `Drop` trait as single units whose fields cannot be moved.
38
39 This error can be fixed by creating a reference to the fields of a struct,
40 enum, or tuple using the `ref` keyword:
41
42 ```
43 struct FancyNum {
44     num: usize
45 }
46
47 struct DropStruct {
48     fancy: FancyNum
49 }
50
51 impl Drop for DropStruct {
52     fn drop(&mut self) {
53         // Destruct DropStruct, possibly using FancyNum
54     }
55 }
56
57 fn main() {
58     let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
59     let ref fancy_field = drop_struct.fancy; // No more errors!
60     println!("Fancy: {}", fancy_field.num);
61     // implicit call to `drop_struct.drop()` as drop_struct goes out of scope
62 }
63 ```
64
65 Note that this technique can also be used in the arms of a match expression:
66
67 ```
68 struct FancyNum {
69     num: usize
70 }
71
72 enum DropEnum {
73     Fancy(FancyNum)
74 }
75
76 impl Drop for DropEnum {
77     fn drop(&mut self) {
78         // Destruct DropEnum, possibly using FancyNum
79     }
80 }
81
82 fn main() {
83     // Creates and enum of type `DropEnum`, which implements `Drop`
84     let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
85     match drop_enum {
86         // Creates a reference to the inside of `DropEnum::Fancy`
87         DropEnum::Fancy(ref fancy_field) => // No error!
88             println!("It was fancy-- {}!", fancy_field.num),
89     }
90     // implicit call to `drop_enum.drop()` as drop_enum goes out of scope
91 }
92 ```