11# Destructors
2+ r[ destructors]
23
4+
5+ r[ destructors.general]
36When an [ initialized]   ; [ variable] or [ temporary] goes out of
47[ scope] ( #drop-scopes ) , its * destructor* is run, or it is * dropped* . [ Assignment]
58also runs the destructor of its left-hand operand, if it's initialized. If a
69variable has been partially initialized, only its initialized fields are
710dropped.
811
12+ r[ destructors.operation]
913The destructor of a type ` T ` consists of:
1014
11151 . If ` T: Drop ` , calling [ ` <T as std::ops::Drop>::drop ` ]
@@ -20,6 +24,7 @@ The destructor of a type `T` consists of:
2024 * [ Trait objects] run the destructor of the underlying type.
2125 * Other types don't result in any further drops.
2226
27+ r[ destructors.drop_in_place]
2328If a destructor must be run manually, such as when implementing your own smart
2429pointer, [ ` std::ptr::drop_in_place ` ] can be used.
2530
@@ -57,48 +62,85 @@ core::mem::forget(partial_move.1);
5762
5863## Drop scopes
5964
65+ r[ destructor.scope]
66+
67+
68+ r[ destructor.scope.general]
6069Each variable or temporary is associated to a * drop scope* . When control flow
6170leaves a drop scope all variables associated to that scope are dropped in
6271reverse order of declaration (for variables) or creation (for temporaries).
6372
73+ r[ destructor.scope.desugaring]
6474Drop scopes are determined after replacing [ ` for ` ] , [ ` if let ` ] , and
6575[ ` while let ` ] expressions with the equivalent expressions using [ ` match ` ] .
76+
77+ r[ destructor.scope.operators]
6678Overloaded operators are not distinguished from built-in operators and [ binding
6779modes] are not considered.
6880
81+ r[ destructor.scope.list]
6982Given a function, or closure, there are drop scopes for:
7083
84+ r[ destructor.scope.function]
7185* The entire function
86+
87+ r[ destructor.scope.statement]
7288* Each [ statement]
89+
90+ r[ destructor.scope.expression]
7391* Each [ expression]
92+
93+ r[ destructor.scope.block]
7494* Each block, including the function body
7595 * In the case of a [ block expression] , the scope for the block and the
7696 expression are the same scope.
97+
98+ r[ destructor.scope.match-arm]
7799* Each arm of a ` match ` expression
78100
101+ r[ destructor.scope.nesting]
79102Drop scopes are nested within one another as follows. When multiple scopes are
80103left at once, such as when returning from a function, variables are dropped
81104from the inside outwards.
82105
106+ r[ destructor.scope.nesting.function]
83107* The entire function scope is the outer most scope.
108+
109+ r[ destructor.scope.nesting.function-body]
84110* The function body block is contained within the scope of the entire function.
111+
112+ r[ destructor.scope.nesting.expr-statement]
85113* The parent of the expression in an expression statement is the scope of the
86114 statement.
115+
116+ r[ destructor.scope.nesting.let-initializer]
87117* The parent of the initializer of a [ ` let ` statement] is the ` let ` statement's
88118 scope.
119+
120+ r[ destructor.scope.nesting.statement]
89121* The parent of a statement scope is the scope of the block that contains the
90122 statement.
123+
124+ r[ destructor.scope.nesting.match-guard]
91125* The parent of the expression for a ` match ` guard is the scope of the arm that
92126 the guard is for.
127+
128+ r[ destructor.scope.nesting.match-arm]
93129* The parent of the expression after the ` => ` in a ` match ` expression is the
94130 scope of the arm that it's in.
131+
132+ r[ destructor.scope.nesting.match]
95133* The parent of the arm scope is the scope of the ` match ` expression that it
96134 belongs to.
135+
136+ r[ destructor.scope.nesting.other]
97137* The parent of all other scopes is the scope of the immediately enclosing
98138 expression.
99139
100140### Scopes of function parameters
101141
142+ r[ destructors.scope.params]
143+
102144All function parameters are in the scope of the entire function body, so are
103145dropped last when evaluating the function. Each actual function parameter is
104146dropped after any bindings introduced in that parameter's pattern.
@@ -125,6 +167,9 @@ patterns_in_parameters(
125167
126168### Scopes of local variables
127169
170+ r[ destructor.scope.bindings]
171+
172+ r[ destructor.scope.bindings.general]
128173Local variables declared in a ` let ` statement are associated to the scope of
129174the block that contains the ` let ` statement. Local variables declared in a
130175` match ` expression are associated to the arm scope of the ` match ` arm that they
@@ -144,15 +189,21 @@ let declared_first = PrintOnDrop("Dropped last in outer scope");
144189let declared_last = PrintOnDrop (" Dropped first in outer scope" );
145190```
146191
192+ r[ destructors.scope.bindings.match-pattern-order]
147193If multiple patterns are used in the same arm for a ` match ` expression, then an
148194unspecified pattern will be used to determine the drop order.
149195
150196### Temporary scopes
151197
198+ r[ destructors.scope.temporary]
199+
200+
201+ r[ destructor.scope.temporary.general]
152202The * temporary scope* of an expression is the scope that is used for the
153203temporary variable that holds the result of that expression when used in a
154204[ place context] , unless it is [ promoted] .
155205
206+ r[ destructor.scope.temporary.enclosing]
156207Apart from lifetime extension, the temporary scope of an expression is the
157208smallest scope that contains the expression and is one of the following:
158209
@@ -215,6 +266,8 @@ match PrintOnDrop("Matched value in final expression") {
215266
216267### Operands
217268
269+ r[ destructors.scope.operands]
270+
218271Temporaries are also created to hold the result of operands to an expression
219272while the other operands are evaluated. The temporaries are associated to the
220273scope of the expression with that operand. Since the temporaries are moved from
@@ -245,6 +298,8 @@ loop {
245298
246299### Constant promotion
247300
301+ r[ destructors.scope.const-promotion]
302+
248303Promotion of a value expression to a ` 'static ` slot occurs when the expression
249304could be written in a constant and borrowed, and that borrow could be dereferenced
250305where
@@ -256,9 +311,13 @@ always has the type `&'static Option<_>`, as it contains nothing disallowed).
256311
257312### Temporary lifetime extension
258313
314+ r[ destructors.scope.lifetime-extension]
315+
259316> ** Note** : The exact rules for temporary lifetime extension are subject to
260317> change. This is describing the current behavior only.
261318
319+ r[ destructors.scope.lifetime-extension.let]
320+
262321The temporary scopes for expressions in ` let ` statements are sometimes
263322* extended* to the scope of the block containing the ` let ` statement. This is
264323done when the usual temporary scope would be too small, based on certain
@@ -271,6 +330,7 @@ let x = &mut 0;
271330println! (" {}" , x );
272331```
273332
333+ r[ destructors.scope.lifetime-extension.sub-expressions]
274334If a [ borrow] [ borrow expression ] , [ dereference] [ dereference expression ] ,
275335[ field] [ field expression ] , or [ tuple indexing expression] has an extended
276336temporary scope then so does its operand. If an [ indexing expression] has an
@@ -279,6 +339,10 @@ temporary scope.
279339
280340#### Extending based on patterns
281341
342+ r[ destructors.scope.lifetime-extension.patterns]
343+
344+
345+ r[ destructors.scope.lifetime-extension.patterns.extending]
282346An * extending pattern* is either
283347
284348* An [ identifier pattern] that binds by reference or mutable reference.
@@ -289,11 +353,14 @@ An *extending pattern* is either
289353So ` ref x ` , ` V(ref x) ` and ` [ref x, y] ` are all extending patterns, but ` x ` ,
290354` &ref x ` and ` &(ref x,) ` are not.
291355
356+ r[ destructors.scope.lifetime-extension.patterns.let]
292357If the pattern in a ` let ` statement is an extending pattern then the temporary
293358scope of the initializer expression is extended.
294359
295360#### Extending based on expressions
296361
362+ r[ destructors.scope.lifetime-extension.exprs]
363+
297364For a let statement with an initializer, an * extending expression* is an
298365expression which is one of the following:
299366
@@ -346,6 +413,8 @@ let x = (&temp()).use_temp(); // ERROR
346413
347414## Not running destructors
348415
416+ r[ destructors.forget]
417+
349418[ ` std::mem::forget ` ] can be used to prevent the destructor of a variable from being run,
350419and [ ` std::mem::ManuallyDrop ` ] provides a wrapper to prevent a
351420variable or field from being dropped automatically.
0 commit comments