1
1
# Destructors
2
2
3
+ r[ destructors.intro]
3
4
When an [ initialized]   ; [ variable] or [ temporary] goes out of
4
5
[ scope] ( #drop-scopes ) , its * destructor* is run, or it is * dropped* . [ Assignment]
5
6
also runs the destructor of its left-hand operand, if it's initialized. If a
6
7
variable has been partially initialized, only its initialized fields are
7
8
dropped.
8
9
10
+ r[ destructors.operation]
9
11
The destructor of a type ` T ` consists of:
10
12
11
13
1 . 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:
20
22
* [ Trait objects] run the destructor of the underlying type.
21
23
* Other types don't result in any further drops.
22
24
25
+ r[ destructors.drop_in_place]
23
26
If a destructor must be run manually, such as when implementing your own smart
24
27
pointer, [ ` std::ptr::drop_in_place ` ] can be used.
25
28
@@ -57,48 +60,84 @@ core::mem::forget(partial_move.1);
57
60
58
61
## Drop scopes
59
62
63
+ r[ destructors.scope]
64
+
65
+ r[ destructors.scope.intro]
60
66
Each variable or temporary is associated to a * drop scope* . When control flow
61
67
leaves a drop scope all variables associated to that scope are dropped in
62
68
reverse order of declaration (for variables) or creation (for temporaries).
63
69
70
+ r[ destructors.scope.desugaring]
64
71
Drop scopes are determined after replacing [ ` for ` ] , [ ` if let ` ] , and
65
72
[ ` while let ` ] expressions with the equivalent expressions using [ ` match ` ] .
73
+
74
+ r[ destructors.scope.operators]
66
75
Overloaded operators are not distinguished from built-in operators and [ binding
67
76
modes] are not considered.
68
77
78
+ r[ destructors.scope.list]
69
79
Given a function, or closure, there are drop scopes for:
70
80
81
+ r[ destructors.scope.function]
71
82
* The entire function
83
+
84
+ r[ destructors.scope.statement]
72
85
* Each [ statement]
86
+
87
+ r[ destructors.scope.expression]
73
88
* Each [ expression]
89
+
90
+ r[ destructors.scope.block]
74
91
* Each block, including the function body
75
92
* In the case of a [ block expression] , the scope for the block and the
76
93
expression are the same scope.
94
+
95
+ r[ destructors.scope.match-arm]
77
96
* Each arm of a ` match ` expression
78
97
98
+ r[ destructors.scope.nesting]
79
99
Drop scopes are nested within one another as follows. When multiple scopes are
80
100
left at once, such as when returning from a function, variables are dropped
81
101
from the inside outwards.
82
102
103
+ r[ destructors.scope.nesting.function]
83
104
* The entire function scope is the outer most scope.
105
+
106
+ r[ destructors.scope.nesting.function-body]
84
107
* The function body block is contained within the scope of the entire function.
108
+
109
+ r[ destructors.scope.nesting.expr-statement]
85
110
* The parent of the expression in an expression statement is the scope of the
86
111
statement.
112
+
113
+ r[ destructors.scope.nesting.let-initializer]
87
114
* The parent of the initializer of a [ ` let ` statement] is the ` let ` statement's
88
115
scope.
116
+
117
+ r[ destructors.scope.nesting.statement]
89
118
* The parent of a statement scope is the scope of the block that contains the
90
119
statement.
120
+
121
+ r[ destructors.scope.nesting.match-guard]
91
122
* The parent of the expression for a ` match ` guard is the scope of the arm that
92
123
the guard is for.
124
+
125
+ r[ destructors.scope.nesting.match-arm]
93
126
* The parent of the expression after the ` => ` in a ` match ` expression is the
94
127
scope of the arm that it's in.
128
+
129
+ r[ destructors.scope.nesting.match]
95
130
* The parent of the arm scope is the scope of the ` match ` expression that it
96
131
belongs to.
132
+
133
+ r[ destructors.scope.nesting.other]
97
134
* The parent of all other scopes is the scope of the immediately enclosing
98
135
expression.
99
136
100
137
### Scopes of function parameters
101
138
139
+ r[ destructors.scope.params]
140
+
102
141
All function parameters are in the scope of the entire function body, so are
103
142
dropped last when evaluating the function. Each actual function parameter is
104
143
dropped after any bindings introduced in that parameter's pattern.
@@ -125,6 +164,9 @@ patterns_in_parameters(
125
164
126
165
### Scopes of local variables
127
166
167
+ r[ destructors.scope.bindings]
168
+
169
+ r[ destructors.scope.bindings.intro]
128
170
Local variables declared in a ` let ` statement are associated to the scope of
129
171
the block that contains the ` let ` statement. Local variables declared in a
130
172
` 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");
144
186
let declared_last = PrintOnDrop (" Dropped first in outer scope" );
145
187
```
146
188
189
+ r[ destructors.scope.bindings.match-pattern-order]
147
190
If multiple patterns are used in the same arm for a ` match ` expression, then an
148
191
unspecified pattern will be used to determine the drop order.
149
192
150
193
### Temporary scopes
151
194
195
+ r[ destructors.scope.temporary]
196
+
197
+ r[ destructors.scope.temporary.intro]
152
198
The * temporary scope* of an expression is the scope that is used for the
153
199
temporary variable that holds the result of that expression when used in a
154
200
[ place context] , unless it is [ promoted] .
155
201
202
+ r[ destructors.scope.temporary.enclosing]
156
203
Apart from lifetime extension, the temporary scope of an expression is the
157
204
smallest scope that contains the expression and is one of the following:
158
205
@@ -215,6 +262,8 @@ match PrintOnDrop("Matched value in final expression") {
215
262
216
263
### Operands
217
264
265
+ r[ destructors.scope.operands]
266
+
218
267
Temporaries are also created to hold the result of operands to an expression
219
268
while the other operands are evaluated. The temporaries are associated to the
220
269
scope of the expression with that operand. Since the temporaries are moved from
@@ -245,6 +294,8 @@ loop {
245
294
246
295
### Constant promotion
247
296
297
+ r[ destructors.scope.const-promotion]
298
+
248
299
Promotion of a value expression to a ` 'static ` slot occurs when the expression
249
300
could be written in a constant and borrowed, and that borrow could be dereferenced
250
301
where
@@ -256,9 +307,12 @@ always has the type `&'static Option<_>`, as it contains nothing disallowed).
256
307
257
308
### Temporary lifetime extension
258
309
310
+ r[ destructors.scope.lifetime-extension]
311
+
259
312
> ** Note** : The exact rules for temporary lifetime extension are subject to
260
313
> change. This is describing the current behavior only.
261
314
315
+ r[ destructors.scope.lifetime-extension.let]
262
316
The temporary scopes for expressions in ` let ` statements are sometimes
263
317
* extended* to the scope of the block containing the ` let ` statement. This is
264
318
done when the usual temporary scope would be too small, based on certain
@@ -271,6 +325,7 @@ let x = &mut 0;
271
325
println! (" {}" , x );
272
326
```
273
327
328
+ r[ destructors.scope.lifetime-extension.sub-expressions]
274
329
If a [ borrow] [ borrow expression ] , [ dereference] [ dereference expression ] ,
275
330
[ field] [ field expression ] , or [ tuple indexing expression] has an extended
276
331
temporary scope then so does its operand. If an [ indexing expression] has an
@@ -279,6 +334,9 @@ temporary scope.
279
334
280
335
#### Extending based on patterns
281
336
337
+ r[ destructors.scope.lifetime-extension.patterns]
338
+
339
+ r[ destructors.scope.lifetime-extension.patterns.extending]
282
340
An * extending pattern* is either
283
341
284
342
* An [ identifier pattern] that binds by reference or mutable reference.
@@ -289,11 +347,14 @@ An *extending pattern* is either
289
347
So ` ref x ` , ` V(ref x) ` and ` [ref x, y] ` are all extending patterns, but ` x ` ,
290
348
` &ref x ` and ` &(ref x,) ` are not.
291
349
350
+ r[ destructors.scope.lifetime-extension.patterns.let]
292
351
If the pattern in a ` let ` statement is an extending pattern then the temporary
293
352
scope of the initializer expression is extended.
294
353
295
354
#### Extending based on expressions
296
355
356
+ r[ destructors.scope.lifetime-extension.exprs]
357
+
297
358
For a let statement with an initializer, an * extending expression* is an
298
359
expression which is one of the following:
299
360
@@ -346,6 +407,8 @@ let x = (&temp()).use_temp(); // ERROR
346
407
347
408
## Not running destructors
348
409
410
+ r[ destructors.forget]
411
+
349
412
[ ` std::mem::forget ` ] can be used to prevent the destructor of a variable from being run,
350
413
and [ ` std::mem::ManuallyDrop ` ] provides a wrapper to prevent a
351
414
variable or field from being dropped automatically.
0 commit comments