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