You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An *extending expression* is an expression which is one of the following:
468
+
The borrow scope of an expression is defined in terms of *extending expressions* and their *extending parents*. An extending expression is an expression which is one of the following:
463
469
464
-
* The initializer expression of a `let` statement or the body expression of a [static][static item] or [constant item].
465
-
* The operand of a [borrow] expression.
466
-
* The [super operands] of a [super macro call] expression.
470
+
* The operand of a [borrow] expression, the extending parent of which is the borrow expression.
471
+
* The [super operands] of a [super macro call] expression, the extending parent of which is the macro call expression.
467
472
* The operand(s) of an [array][array expression], [cast][cast
468
473
expression], [braced struct][struct expression], or [tuple][tuple expression]
469
-
expression.
470
-
* The arguments to a [tuple struct] or [tuple enum variant] constructor expression.
471
-
* The final expression of a [block expression]except for an [async block expression].
472
-
* The final expression of an [`if`] expression's consequent, `else if`, or `else` block.
473
-
* An arm expression of a [`match`] expression.
474
+
expression, the extending parent of which is the array, cast, braced struct, or tuple expression.
475
+
* The arguments to a [tuple struct] or [tuple enum variant] constructor expression, the extending parent of which is the constructor expression.
476
+
* The final expression of a plain [block expression]or [`unsafe` block expression], the extending parent of which is the block expression.
477
+
* The final expression of an [`if`] expression's consequent, `else if`, or `else` block, the extending parent of which is the `if` expression.
478
+
* An arm expression of a [`match`] expression, the extending parent of which is the `match` expression.
474
479
475
480
> [!NOTE]
476
481
> The desugaring of a [destructuring assignment] makes its assigned value operand (the RHS) an extending expression within a newly-introduced block. For details, see [expr.assign.destructure.tmp-ext].
@@ -483,20 +488,32 @@ An *extending expression* is an expression which is one of the following:
483
488
So the borrow expressions in `{ &mut 0 }`, `(&1, &mut 2)`, and `Some(&mut 3)`
484
489
are all extending expressions. The borrows in `&0 + &1` and `f(&mut 0)` are not.
The [scopes][temporary scopes] of the [super temporaries] of an extending [super macro call] expression are *extended through* the scope of the super macro call expression.
If a temporary scope is extended through the scope of an extending expression, it is extended through that scope's [parent][destructors.scope.nesting].
492
+
The borrow scope of an extending expressionis the borrow scope of its extending parent.
494
493
495
494
r[destructors.scope.lifetime-extension.exprs.let]
496
-
A temporary scope extended through a `let` statement scope is [extended] to the scope of the block containing the `let` statement.
495
+
The borrow scope of the initializer expression of a `let` statement is the scope of the block containing the `let` statement.
496
+
497
+
> [!EXAMPLE]
498
+
> In this example, the temporary value holding the result of `temp()` is extended to the end of the block in which `x` is declared:
499
+
>
500
+
> ```rust,edition2024
501
+
> # fn temp() {}
502
+
> let x = { &temp() };
503
+
> println!("{x:?}");
504
+
> ```
505
+
>
506
+
> `temp()` is the operand of a borrow expression, so its temporary scope is its borrow scope.
507
+
> To determine its borrow scope, look outward:
508
+
>
509
+
> * Since borrow expressions' operands are extending, the borrow scope of `temp()` is the borrow scope of its extending parent, the borrow expression.
510
+
> * `&temp()` is the final expression of a plain block. Since the final expressions of plain blocks are extending, the extended temporary scope of `&temp()` is the borrow scope of its extending parent, the block expression.
511
+
> * `{ &temp() }` is the initializer expression of a `let` statement, so its borrow scope is the scope of the block containg that `let` statement.
512
+
>
513
+
> If not for temporary lifetime extension, the result of `temp()` would be dropped after evaluating the tail expression of the block `{ &temp() }` ([destructors.scope.temporary.enclosing]).
A temporary scope extended through a [static][static item] or [constant item] scope or a [const block][const block expression] scope is [extended] to the end of the program.
516
+
The borrow scope of the body expression of a [static][static item] or [constant item], and of the final expression of a [const blockexpression], is the entire program. This prevents destructors from being run.
A temporary scope extended through the scope of a non-extending expression is [extended] to that expression's [temporary scope].
527
+
The borrow scope of any other expression is its non-extended temporary scope, as defined by [destructors.scope.temporary.enclosing].
528
+
529
+
> [!EXAMPLE]
530
+
> In this example, the temporary value holding the result of `temp()` is extended to the end of the statement:
531
+
>
532
+
> ```rust,edition2024
533
+
> # fn temp() {}
534
+
> # fn use_temp(_: &()) {}
535
+
> use_temp({ &temp() });
536
+
> ```
537
+
>
538
+
> `temp()` is the operand of a borrow expression, so its temporary scope is its borrow scope.
539
+
> To determine its borrow scope, look outward:
540
+
>
541
+
> * Since borrow expressions' operands are extending, the borrow scope of `temp()` is the borrow scope of its extending parent, the borrow expression.
542
+
> * `&temp()` is the final expression of a plain block. Since the final expressions of plain blocks are extending, the borrow scope of `&temp()` is the borrow scope of its extending parent, the block expression.
543
+
> * `{ &temp() }` is the argument of a call expression, which is not extending. Since no other cases apply, its borrow scope is its temporary scope.
544
+
> * Per [destructors.scope.temporary.enclosing], the temporary scope of `{ &temp() }`, and thus the borrow scope of `temp()`, is the scope of the statement.
545
+
>
546
+
> If not for temporary lifetime extension, the result of `temp()` would be dropped after evaluating the tail expression of the block `{ &temp() }` ([destructors.scope.temporary.enclosing]).
511
547
512
548
#### Examples
513
549
@@ -556,19 +592,6 @@ let x = format_args!("{:?}", temp()); // As above.
556
592
# assert_eq!(0, X.load(Relaxed));
557
593
```
558
594
559
-
```rust,edition2024
560
-
# fn temp() {}
561
-
# fn use_temp(_: &()) {}
562
-
// The final expression of a block is extending. Since the block below
563
-
// is not itself extending, the temporary is extended to the block
564
-
// expression's temporary scope, ending at the semicolon.
565
-
use_temp({ &temp() });
566
-
// As above, the final expressions of `if`/`else` blocks are
567
-
// extending, which extends the temporaries to the `if` expression's
568
-
// temporary scope.
569
-
use_temp(if true { &temp() } else { &temp() });
570
-
```
571
-
572
595
Here are some examples where expressions don't have extended temporary scopes:
573
596
574
597
```rust,compile_fail,E0716
@@ -684,7 +707,6 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi
0 commit comments