11# Destructors
22
3+ r[ destructors.intro]
34When an [ initialized]   ; [ variable] or [ temporary] goes out of
45[ scope] ( #drop-scopes ) , its * destructor* is run, or it is * dropped* . [ Assignment]
56also runs the destructor of its left-hand operand, if it's initialized. If a
67variable has been partially initialized, only its initialized fields are
78dropped.
89
10+ r[ destructors.operation]
911The destructor of a type ` T ` consists of:
1012
11131 . If ` T: Drop ` , calling [ ` <T as std::ops::Drop>::drop ` ] ( std::ops::Drop::drop )
@@ -20,6 +22,7 @@ The destructor of a type `T` consists of:
2022 * [ Trait objects] run the destructor of the underlying type.
2123 * Other types don't result in any further drops.
2224
25+ r[ destructors.drop_in_place]
2326If a destructor must be run manually, such as when implementing your own smart
2427pointer, [ ` std::ptr::drop_in_place ` ] can be used.
2528
@@ -57,48 +60,84 @@ core::mem::forget(partial_move.1);
5760
5861## Drop scopes
5962
63+ r[ destructors.scope]
64+
65+ r[ destructors.scope.intro]
6066Each variable or temporary is associated to a * drop scope* . When control flow
6167leaves a drop scope all variables associated to that scope are dropped in
6268reverse order of declaration (for variables) or creation (for temporaries).
6369
70+ r[ destructors.scope.desugaring]
6471Drop scopes are determined after replacing [ ` for ` ] , [ ` if let ` ] , and
6572[ ` while let ` ] expressions with the equivalent expressions using [ ` match ` ] .
73+
74+ r[ destructors.scope.operators]
6675Overloaded operators are not distinguished from built-in operators and [ binding
6776modes] are not considered.
6877
78+ r[ destructors.scope.list]
6979Given a function, or closure, there are drop scopes for:
7080
81+ r[ destructors.scope.function]
7182* The entire function
83+
84+ r[ destructors.scope.statement]
7285* Each [ statement]
86+
87+ r[ destructors.scope.expression]
7388* Each [ expression]
89+
90+ r[ destructors.scope.block]
7491* Each block, including the function body
7592 * In the case of a [ block expression] , the scope for the block and the
7693 expression are the same scope.
94+
95+ r[ destructors.scope.match-arm]
7796* Each arm of a ` match ` expression
7897
98+ r[ destructors.scope.nesting]
7999Drop scopes are nested within one another as follows. When multiple scopes are
80100left at once, such as when returning from a function, variables are dropped
81101from the inside outwards.
82102
103+ r[ destructors.scope.nesting.function]
83104* The entire function scope is the outer most scope.
105+
106+ r[ destructors.scope.nesting.function-body]
84107* The function body block is contained within the scope of the entire function.
108+
109+ r[ destructors.scope.nesting.expr-statement]
85110* The parent of the expression in an expression statement is the scope of the
86111 statement.
112+
113+ r[ destructors.scope.nesting.let-initializer]
87114* The parent of the initializer of a [ ` let ` statement] is the ` let ` statement's
88115 scope.
116+
117+ r[ destructors.scope.nesting.statement]
89118* The parent of a statement scope is the scope of the block that contains the
90119 statement.
120+
121+ r[ destructors.scope.nesting.match-guard]
91122* The parent of the expression for a ` match ` guard is the scope of the arm that
92123 the guard is for.
124+
125+ r[ destructors.scope.nesting.match-arm]
93126* The parent of the expression after the ` => ` in a ` match ` expression is the
94127 scope of the arm that it's in.
128+
129+ r[ destructors.scope.nesting.match]
95130* The parent of the arm scope is the scope of the ` match ` expression that it
96131 belongs to.
132+
133+ r[ destructors.scope.nesting.other]
97134* The parent of all other scopes is the scope of the immediately enclosing
98135 expression.
99136
100137### Scopes of function parameters
101138
139+ r[ destructors.scope.params]
140+
102141All function parameters are in the scope of the entire function body, so are
103142dropped last when evaluating the function. Each actual function parameter is
104143dropped after any bindings introduced in that parameter's pattern.
@@ -125,6 +164,9 @@ patterns_in_parameters(
125164
126165### Scopes of local variables
127166
167+ r[ destructors.scope.bindings]
168+
169+ r[ destructors.scope.bindings.intro]
128170Local variables declared in a ` let ` statement are associated to the scope of
129171the block that contains the ` let ` statement. Local variables declared in a
130172` match ` expression are associated to the arm scope of the ` match ` arm that they
@@ -144,15 +186,20 @@ let declared_first = PrintOnDrop("Dropped last in outer scope");
144186let declared_last = PrintOnDrop (" Dropped first in outer scope" );
145187```
146188
189+ r[ destructors.scope.bindings.match-pattern-order]
147190If multiple patterns are used in the same arm for a ` match ` expression, then an
148191unspecified pattern will be used to determine the drop order.
149192
150193### Temporary scopes
151194
195+ r[ destructors.scope.temporary]
196+
197+ r[ destructors.scope.temporary.intro]
152198The * temporary scope* of an expression is the scope that is used for the
153199temporary variable that holds the result of that expression when used in a
154200[ place context] , unless it is [ promoted] .
155201
202+ r[ destructors.scope.temporary.enclosing]
156203Apart from lifetime extension, the temporary scope of an expression is the
157204smallest scope that contains the expression and is one of the following:
158205
@@ -215,6 +262,8 @@ match PrintOnDrop("Matched value in final expression") {
215262
216263### Operands
217264
265+ r[ destructors.scope.operands]
266+
218267Temporaries are also created to hold the result of operands to an expression
219268while the other operands are evaluated. The temporaries are associated to the
220269scope of the expression with that operand. Since the temporaries are moved from
@@ -245,6 +294,8 @@ loop {
245294
246295### Constant promotion
247296
297+ r[ destructors.scope.const-promotion]
298+
248299Promotion of a value expression to a ` 'static ` slot occurs when the expression
249300could be written in a constant and borrowed, and that borrow could be dereferenced
250301where
@@ -256,9 +307,12 @@ always has the type `&'static Option<_>`, as it contains nothing disallowed).
256307
257308### Temporary lifetime extension
258309
310+ r[ destructors.scope.lifetime-extension]
311+
259312> ** Note** : The exact rules for temporary lifetime extension are subject to
260313> change. This is describing the current behavior only.
261314
315+ r[ destructors.scope.lifetime-extension.let]
262316The temporary scopes for expressions in ` let ` statements are sometimes
263317* extended* to the scope of the block containing the ` let ` statement. This is
264318done when the usual temporary scope would be too small, based on certain
@@ -271,6 +325,7 @@ let x = &mut 0;
271325println! (" {}" , x );
272326```
273327
328+ r[ destructors.scope.lifetime-extension.sub-expressions]
274329If a [ borrow] [ borrow expression ] , [ dereference] [ dereference expression ] ,
275330[ field] [ field expression ] , or [ tuple indexing expression] has an extended
276331temporary scope then so does its operand. If an [ indexing expression] has an
@@ -279,6 +334,9 @@ temporary scope.
279334
280335#### Extending based on patterns
281336
337+ r[ destructors.scope.lifetime-extension.patterns]
338+
339+ r[ destructors.scope.lifetime-extension.patterns.extending]
282340An * extending pattern* is either
283341
284342* An [ identifier pattern] that binds by reference or mutable reference.
@@ -289,11 +347,14 @@ An *extending pattern* is either
289347So ` ref x ` , ` V(ref x) ` and ` [ref x, y] ` are all extending patterns, but ` x ` ,
290348` &ref x ` and ` &(ref x,) ` are not.
291349
350+ r[ destructors.scope.lifetime-extension.patterns.let]
292351If the pattern in a ` let ` statement is an extending pattern then the temporary
293352scope of the initializer expression is extended.
294353
295354#### Extending based on expressions
296355
356+ r[ destructors.scope.lifetime-extension.exprs]
357+
297358For a let statement with an initializer, an * extending expression* is an
298359expression which is one of the following:
299360
@@ -346,6 +407,8 @@ let x = (&temp()).use_temp(); // ERROR
346407
347408## Not running destructors
348409
410+ r[ destructors.forget]
411+
349412[ ` std::mem::forget ` ] can be used to prevent the destructor of a variable from being run,
350413and [ ` std::mem::ManuallyDrop ` ] provides a wrapper to prevent a
351414variable or field from being dropped automatically.
0 commit comments