]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/destructors.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / reference / src / destructors.md
1 # Destructors
2
3 When an [initialized] [variable] in Rust goes out of scope or a [temporary]
4 is no longer needed its _destructor_ is run. [Assignment] also runs the
5 destructor of its left-hand operand, unless it's an unitialized variable. If a
6 [struct] variable has been partially initialized, only its initialized fields
7 are dropped.
8
9 The destrutor of a type consists of
10
11 1. Calling its [`std::ops::Drop::drop`] method, if it has one.
12 2. Recursively running the destructor of all of its fields.
13 * The fields of a [struct], [tuple] or [enum variant] are dropped in
14 declaration order. \*
15 * The elements of an [array] or owned [slice][array] are dropped from the
16 first element to the last. \*
17 * The captured values of a [closure] are dropped in an unspecified order.
18 * [Trait objects] run the destructor of the underlying type.
19 * Other types don't result in any further drops.
20
21 \* This order was stabilized in [RFC 1857].
22
23 Variables are dropped in reverse order of declaration. Variables declared in
24 the same pattern drop in an unspecified ordered.
25
26 If a destructor must be run manually, such as when implementing your own smart
27 pointer, [`std::ptr::drop_in_place`] can be used.
28
29 Some examples:
30
31 ```rust
32 struct ShowOnDrop(&'static str);
33
34 impl Drop for ShowOnDrop {
35 fn drop(&mut self) {
36 println!("{}", self.0);
37 }
38 }
39
40 {
41 let mut overwritten = ShowOnDrop("Drops when overwritten");
42 overwritten = ShowOnDrop("drops when scope ends");
43 }
44 # println!("");
45 {
46 let declared_first = ShowOnDrop("Dropped last");
47 let declared_last = ShowOnDrop("Dropped first");
48 }
49 # println!("");
50 {
51 // Tuple elements drop in forwards order
52 let tuple = (ShowOnDrop("Tuple first"), ShowOnDrop("Tuple second"));
53 }
54 # println!("");
55 loop {
56 // Tuple expression doesn't finish evaluating so temporaries drop in reverse order:
57 let partial_tuple = (ShowOnDrop("Temp first"), ShowOnDrop("Temp second"), break);
58 }
59 # println!("");
60 {
61 let moved;
62 // No destructor run on assignment.
63 moved = ShowOnDrop("Drops when moved");
64 // drops now, but is then uninitialized
65 moved;
66 let uninitialized: ShowOnDrop;
67 // Only first element drops
68 let mut partially_initialized: (ShowOnDrop, ShowOnDrop);
69 partially_initialized.0 = ShowOnDrop("Partial tuple first");
70 }
71 ```
72
73 ## Not running destructors
74
75 Not running destructors in Rust is safe even if it has a type that isn't
76 `'static`. [`std::mem::ManuallyDrop`] provides a wrapper to prevent a
77 variable or field from being dropped automatically.
78
79 [initialized]: glossary.html#initialized
80 [variable]: variables.html
81 [temporary]: expressions.html#temporary-lifetimes
82 [Assignment]: expressions/operator-expr.html#assignment-expressions
83 [`std::ops::Drop::drop`]: ../std/ops/trait.Drop.html
84 [RFC 1857]: https://github.com/rust-lang/rfcs/blob/master/text/1857-stabilize-drop-order.md
85 [struct]: types.html#struct-types
86 [tuple]: types.html#tuple-types
87 [enum variant]: types.html#enumerated-types
88 [array]: types.html#array-and-slice-types
89 [closure]: types.html#closure-types
90 [Trait objects]: types.html#trait-objects
91 [`std::ptr::drop_in_place`]: ../std/ptr/fn.drop_in_place.html
92 [`std::mem::forget`]: ../std/mem/fn.forget.html
93 [`std::mem::ManuallyDrop`]: ../std/mem/union.ManuallyDrop.html