Skip to content

Document destructors/drop. #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
- [Interior mutability](interior-mutability.md)
- [Subtyping](subtyping.md)
- [Type coercions](type-coercions.md)
- [Destructors](destructors.md)

- [Special traits](special-traits.md)
- [The Copy trait](the-copy-trait.md)
Expand Down
93 changes: 93 additions & 0 deletions src/destructors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Destructors

When an [initialized] [variable] in Rust goes out of scope or a [temporary]
is no longer needed its _destructor_ is run. [Assignment] also runs the
destructor of its left-hand operand, unless it's an unitialized variable. If a
[struct] variable has been partially initialized, only its initialized fields
are dropped.

The destrutor of a type consists of

1. Calling its [`std::ops::Drop::drop`] method, if it has one.
2. Recursively running the destructor of all of its fields.
* The fields of a [struct], [tuple] or [enum variant] are dropped in
declaration order. \*
* The elements of an [array] or owned [slice][array] are dropped from the
first element to the last. \*
* The captured values of a [closure] are dropped in an unspecified order.
* [Trait objects] run the destructor of the underlying type.
* Other types don't result in any further drops.

\* This order was stabilized in [RFC 1857].

Variables are dropped in reverse order of declaration. Variables declared in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a part of block expressions, but I'm not going to worry about that for this PR.

the same pattern drop in an unspecified ordered.

If a destructor must be run manually, such as when implementing your own smart
pointer, [`std::ptr::drop_in_place`] can be used.

Some examples:

```rust
struct ShowOnDrop(&'static str);

impl Drop for ShowOnDrop {
fn drop(&mut self) {
println!("{}", self.0);
}
}

{
let mut overwritten = ShowOnDrop("Drops when overwritten");
overwritten = ShowOnDrop("drops when scope ends");
}
# println!("");
{
let declared_first = ShowOnDrop("Dropped last");
let declared_last = ShowOnDrop("Dropped first");
}
# println!("");
{
// Tuple elements drop in forwards order
let tuple = (ShowOnDrop("Tuple first"), ShowOnDrop("Tuple second"));
}
# println!("");
loop {
// Tuple expression doesn't finish evaluating so temporaries drop in reverse order:
let partial_tuple = (ShowOnDrop("Temp first"), ShowOnDrop("Temp second"), break);
}
# println!("");
{
let moved;
// No destructor run on assignment.
moved = ShowOnDrop("Drops when moved");
// drops now, but is then uninitialized
moved;
let uninitialized: ShowOnDrop;
// Only first element drops
let mut partially_initialized: (ShowOnDrop, ShowOnDrop);
partially_initialized.0 = ShowOnDrop("Partial tuple first");
}
```

## Not running destructors

Not running destructors in Rust is safe even if it has a type that isn't
`'static`. [`std::mem::ManuallyDrop`] provides a wrapper to prevent a
variable or field from being dropped automatically.

[initialized]: glossary.html#initialized
[variable]: variables.html
[temporary]: expressions.html#temporary-lifetimes
[Assignment]: expressions/operator-expr.html#assignment-expressions
[`std::ops::Drop::drop`]: ../std/ops/trait.Drop.html
[RFC 1857]: https://github.com/rust-lang/rfcs/blob/master/text/1857-stabilize-drop-order.md
[struct]: types.html#struct
[tuple]: types.html#tuple-types
[enum variant]: types.html#enumeration-types
[array]: types.html#array-and-slice-types
[closure]: types.html#closure-types
[Trait objects]: types.html#trait-objects
[`std::ptr::drop_in_place`]: ../std/ptr/fn.drop_in_place.html
[`std::mem::forget`]: ../std/mem/fn.forget.html
[`std::mem::ManuallyDrop`]: ../std/mem/union.ManuallyDrop.html
17 changes: 9 additions & 8 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,14 +301,15 @@ same trait object.
## Assignment expressions

An _assignment expression_ consists of an
[lvalue](expressions.html#lvalues-and-rvalues) expression followed
by an equals sign (`=`) and an
[rvalue](expressions.html#lvalues-and-rvalues) expression.

Evaluating an assignment expression [either copies or
moves](expressions.html#moved-and-copied-types) its right-hand operand to its left-hand
operand. The left-hand operand must be an lvalue: using an rvalue results in a
compiler error, rather than promoting it to a temporary.
[lvalue](expressions.html#lvalues-and-rvalues) expression followed by an equals
sign (`=`) and an [rvalue](expressions.html#lvalues-and-rvalues) expression.

Evaluating an assignment expression [drops](destructors.hmtl) the left-hand
operand, unless it's an unitialized local variable or field of a local variable,
and [either copies or moves](expressions.html#moved-and-copied-types) its
right-hand operand to its left-hand operand. The left-hand operand must be an
lvalue: using an rvalue results in a compiler error, rather than promoting it
to a temporary.

```rust
# let mut x = 0;
Expand Down
22 changes: 14 additions & 8 deletions src/glossory.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ must abide by that constraint.
### Combinator

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

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

### Dynamically Sized Type

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

### Expression

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

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

### Initialized

A variable is initialized if it has been assigned a value and hasn't since been
moved from. All other lvalues are assumed to be initialized. Only unsafe Rust
can create such an lvalue without initializing it.

### Prelude

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

### Slice

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

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

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

### String literal

A string literal is a string stored directly in the final binary, and so will be
valid for the `'static` duration.
A string literal is a string stored directly in the final binary, and so will be
valid for the `'static` duration.

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

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

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

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