Skip to content

Commit 0eab656

Browse files
Add a section dedicated to Edition 2024 changes to temporary scopes
1 parent 0668397 commit 0eab656

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

Diff for: src/destructors.md

+92
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ smallest scope that contains the expression and is one of the following:
211211
guard.
212212
* The body expression for a match arm.
213213
* The second operand of a [lazy boolean expression].
214+
* *Starting from Edition 2024* the pattern-matching condition and consequent body of [`if let`].
215+
* *Starting from Edition 2024* the entirety of the tail expression of a block.
214216

215217
> **Notes**:
216218
>
@@ -260,6 +262,96 @@ match PrintOnDrop("Matched value in final expression") {
260262
}
261263
```
262264

265+
#### Changes to temporary scopes by Edition 2024
266+
267+
Edition 2024 introduces two changes to the language regarding temporary scopes.
268+
First, temporary values generated from evaluating the pattern-matching condition
269+
of `if let` will be dropped earlier in general.
270+
271+
```rust,edition2024
272+
struct Droppy(u8);
273+
impl Droppy {
274+
fn get(&self) -> Option<&u8> {
275+
Some(&self.0)
276+
}
277+
}
278+
impl Drop for Droppy {
279+
fn drop(&mut self) {
280+
println!("drop({})", self.0);
281+
}
282+
}
283+
284+
fn call(x: &u8, y: u8, z: &u8) {
285+
println!("call with {x} {y} {z}");
286+
}
287+
288+
let x1 = 0;
289+
let x2 = 3;
290+
291+
call(
292+
if let Some(x) = Droppy(0).get() {
293+
println!("if let consequence");
294+
&x1
295+
} else {
296+
&x2
297+
},
298+
{
299+
let y = Droppy(1);
300+
*y.get().unwrap()
301+
},
302+
Droppy(2).get().unwrap()
303+
);
304+
println!("call ended");
305+
```
306+
307+
This will print the following
308+
```
309+
if let consequence
310+
drop(0)
311+
drop(1)
312+
call with 0 1 2
313+
drop(2)
314+
call ended
315+
```
316+
317+
In other words, `Droppy(0)` is dropped before `Droppy(1)` because its temporary scope is
318+
limited by Edition 2024 to the proper end of the `if let` expression.
319+
320+
Second, temporary values generated from evaluating the tail expression of a block
321+
or a function body will be dropped earlier than the local variable bindings.
322+
The following example demonstrates the Edition 2024 order of events that values
323+
and local variables are dropped.
324+
325+
```rust,edition2024
326+
struct Droppy(u8);
327+
impl Droppy {
328+
fn get(&self) -> Option<&u8> {
329+
Some(&self.0)
330+
}
331+
}
332+
impl Drop for Droppy {
333+
fn drop(&mut self) {
334+
println!("drop({})", self.0);
335+
}
336+
}
337+
338+
fn call() -> u8 {
339+
let x = Droppy(0);
340+
*x.get() + *Droppy(1).get()
341+
}
342+
343+
call();
344+
```
345+
346+
The print-out from this program will be the following.
347+
348+
```
349+
drop(1)
350+
drop(0)
351+
```
352+
353+
In other words, `Droppy(1)` is dropped earlier than `x`.
354+
263355
### Operands
264356

265357
r[destructors.scope.operands]

0 commit comments

Comments
 (0)