Skip to content

Commit 7d7bf59

Browse files
committed
Add spec identifier syntax to destructors.md
1 parent 0b18ee6 commit 7d7bf59

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/destructors.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
# Destructors
2+
r[destructors]
23

4+
5+
r[destructors.general]
36
When an [initialized] [variable] or [temporary] goes out of
47
[scope](#drop-scopes), its *destructor* is run, or it is *dropped*. [Assignment]
58
also runs the destructor of its left-hand operand, if it's initialized. If a
69
variable has been partially initialized, only its initialized fields are
710
dropped.
811

12+
r[destructors.operation]
913
The destructor of a type `T` consists of:
1014

1115
1. 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]
2328
If a destructor must be run manually, such as when implementing your own smart
2429
pointer, [`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]
6069
Each variable or temporary is associated to a *drop scope*. When control flow
6170
leaves a drop scope all variables associated to that scope are dropped in
6271
reverse order of declaration (for variables) or creation (for temporaries).
6372

73+
r[destructor.scope.desugaring]
6474
Drop 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]
6678
Overloaded operators are not distinguished from built-in operators and [binding
6779
modes] are not considered.
6880

81+
r[destructor.scope.list]
6982
Given 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]
79102
Drop scopes are nested within one another as follows. When multiple scopes are
80103
left at once, such as when returning from a function, variables are dropped
81104
from 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+
102144
All function parameters are in the scope of the entire function body, so are
103145
dropped last when evaluating the function. Each actual function parameter is
104146
dropped 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]
128173
Local variables declared in a `let` statement are associated to the scope of
129174
the 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");
144189
let declared_last = PrintOnDrop("Dropped first in outer scope");
145190
```
146191

192+
r[destructors.scope.bindings.match-pattern-order]
147193
If multiple patterns are used in the same arm for a `match` expression, then an
148194
unspecified 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]
152202
The *temporary scope* of an expression is the scope that is used for the
153203
temporary 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]
156207
Apart from lifetime extension, the temporary scope of an expression is the
157208
smallest 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+
218271
Temporaries are also created to hold the result of operands to an expression
219272
while the other operands are evaluated. The temporaries are associated to the
220273
scope 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+
248303
Promotion of a value expression to a `'static` slot occurs when the expression
249304
could be written in a constant and borrowed, and that borrow could be dereferenced
250305
where
@@ -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+
262321
The temporary scopes for expressions in `let` statements are sometimes
263322
*extended* to the scope of the block containing the `let` statement. This is
264323
done when the usual temporary scope would be too small, based on certain
@@ -271,6 +330,7 @@ let x = &mut 0;
271330
println!("{}", x);
272331
```
273332

333+
r[destructors.scope.lifetime-extension.sub-expressions]
274334
If a [borrow][borrow expression], [dereference][dereference expression],
275335
[field][field expression], or [tuple indexing expression] has an extended
276336
temporary 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]
282346
An *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
289353
So `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]
292357
If the pattern in a `let` statement is an extending pattern then the temporary
293358
scope of the initializer expression is extended.
294359

295360
#### Extending based on expressions
296361

362+
r[destructors.scope.lifetime-extension.exprs]
363+
297364
For a let statement with an initializer, an *extending expression* is an
298365
expression 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,
350419
and [`std::mem::ManuallyDrop`] provides a wrapper to prevent a
351420
variable or field from being dropped automatically.

0 commit comments

Comments
 (0)