Skip to content

Commit 1928fdd

Browse files
authored
Merge pull request #128 from matthewjasper/destruction
Document destructors/drop.
2 parents 7b232f1 + c9d2f07 commit 1928fdd

File tree

4 files changed

+117
-16
lines changed

4 files changed

+117
-16
lines changed

src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
- [Interior mutability](interior-mutability.md)
6767
- [Subtyping](subtyping.md)
6868
- [Type coercions](type-coercions.md)
69+
- [Destructors](destructors.md)
6970

7071
- [Special traits](special-traits.md)
7172
- [The Copy trait](the-copy-trait.md)

src/destructors.md

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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
86+
[tuple]: types.html#tuple-types
87+
[enum variant]: types.html#enumeration-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

src/expressions/operator-expr.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,15 @@ same trait object.
301301
## Assignment expressions
302302

303303
An _assignment expression_ consists of an
304-
[lvalue](expressions.html#lvalues-and-rvalues) expression followed
305-
by an equals sign (`=`) and an
306-
[rvalue](expressions.html#lvalues-and-rvalues) expression.
307-
308-
Evaluating an assignment expression [either copies or
309-
moves](expressions.html#moved-and-copied-types) its right-hand operand to its left-hand
310-
operand. The left-hand operand must be an lvalue: using an rvalue results in a
311-
compiler error, rather than promoting it to a temporary.
304+
[lvalue](expressions.html#lvalues-and-rvalues) expression followed by an equals
305+
sign (`=`) and an [rvalue](expressions.html#lvalues-and-rvalues) expression.
306+
307+
Evaluating an assignment expression [drops](destructors.hmtl) the left-hand
308+
operand, unless it's an unitialized local variable or field of a local variable,
309+
and [either copies or moves](expressions.html#moved-and-copied-types) its
310+
right-hand operand to its left-hand operand. The left-hand operand must be an
311+
lvalue: using an rvalue results in a compiler error, rather than promoting it
312+
to a temporary.
312313

313314
```rust
314315
# let mut x = 0;

src/glossory.md

+14-8
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ must abide by that constraint.
2525
### Combinator
2626

2727
Combinators are higher-order functions that apply only functions and
28-
earlier defined combinators to provide a result from its arguments.
28+
earlier defined combinators to provide a result from its arguments.
2929
They can be used to manage control flow in a modular fashion.
3030

3131
### Dispatch
@@ -37,25 +37,31 @@ through a mechanism called ‘trait objects’.
3737

3838
### Dynamically Sized Type
3939

40-
A dynamically sized type (DST) is a type without a statically known size or alignment.
40+
A dynamically sized type (DST) is a type without a statically known size or alignment.
4141

4242
### Expression
4343

44-
An expression is a combination of values, constants, variables, operators
44+
An expression is a combination of values, constants, variables, operators
4545
and functions that evaluate to a single value, with or without side-effects.
4646

4747
For example, `2 + (3 * 4)` is an expression that returns the value 14.
4848

49+
### Initialized
50+
51+
A variable is initialized if it has been assigned a value and hasn't since been
52+
moved from. All other lvalues are assumed to be initialized. Only unsafe Rust
53+
can create such an lvalue without initializing it.
54+
4955
### Prelude
5056

5157
Prelude, or The Rust Prelude, is a small collection of items - mostly traits - that are
5258
imported into very module of every crate. The traits in the prelude are pervasive.
5359

5460
### Slice
5561

56-
A slice is dynamically-sized view into a contiguous sequence, written as `[T]`.
62+
A slice is dynamically-sized view into a contiguous sequence, written as `[T]`.
5763

58-
It is often seen in its borrowed forms, either mutable or shared. The shared
64+
It is often seen in its borrowed forms, either mutable or shared. The shared
5965
slice type is `&[T]`, while the mutable slice type is `&mut [T]`, where `T` represents
6066
the element type.
6167

@@ -66,8 +72,8 @@ that commands a computer to perform an action.
6672

6773
### String literal
6874

69-
A string literal is a string stored directly in the final binary, and so will be
70-
valid for the `'static` duration.
75+
A string literal is a string stored directly in the final binary, and so will be
76+
valid for the `'static` duration.
7177

7278
Its type is `'static` duration borrowed string slice, `&'static str`.
7379

@@ -82,6 +88,6 @@ Strings slices are always valid UTF-8.
8288
### Trait
8389

8490
A trait is a language item that is used for describing the functionalities a type must provide.
85-
It allow a type to make certain promises about its behavior.
91+
It allow a type to make certain promises about its behavior.
8692

8793
Generic functions and generic structs can exploit traits to constrain, or bound, the types they accept.

0 commit comments

Comments
 (0)