Skip to content

Commit 8b24e65

Browse files
diannetraviscross
authored andcommitted
specify lifetime extension of pin! and format_args! arguments
1 parent d01f991 commit 8b24e65

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

src/destructors.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ let &ref x = &*&temp(); // OK
474474
r[destructors.scope.lifetime-extension.exprs]
475475
#### Extending based on expressions
476476

477+
r[destructors.scope.lifetime-extension.exprs.extending]
477478
For a let statement with an initializer, an *extending expression* is an
478479
expression which is one of the following:
479480

@@ -486,13 +487,19 @@ expression which is one of the following:
486487
* The final expression of an extending [block expression] except for an [async block expression].
487488
* The final expression of an extending [`if`] expression's consequent, `else if`, or `else` block.
488489
* An arm expression of an extending [`match`] expression.
490+
* The argument(s) to an extending [`pin!`] or [`format_args!`] [macro invocation] expression.
489491

490492
So the borrow expressions in `&mut 0`, `(&1, &mut 2)`, and `Some(&mut 3)`
491493
are all extending expressions. The borrows in `&0 + &1` and `f(&mut 0)` are not.
492494

495+
r[destructors.scope.lifetime-extension.exprs.borrow]
493496
The operand of any extending borrow expression has its temporary scope
494497
extended.
495498

499+
r[destructors.scope.lifetime-extension.exprs.macros]
500+
The built-in macros [`pin!`] and [`format_args!`] create temporaries.
501+
Any extending [`pin!`] or [`format_args!`] [macro invocation] expression has an extended temporary scope.
502+
496503
> [!NOTE]
497504
> `rustc` does not treat [array repeat operands] of extending [array] expressions as extending expressions. Whether it should is an open question.
498505
>
@@ -504,6 +511,7 @@ Here are some examples where expressions have extended temporary scopes:
504511

505512
```rust,edition2024
506513
# use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
514+
# use std::pin::pin;
507515
# static X: AtomicU64 = AtomicU64::new(0);
508516
# struct S;
509517
# impl Drop for S { fn drop(&mut self) { X.fetch_add(1, Relaxed); } }
@@ -528,6 +536,8 @@ let x = if true { &temp() } else { &temp() };
528536
# x;
529537
let x = match () { _ => &temp() }; // `match` arm expression.
530538
# x;
539+
let x = pin!(&temp()); // Argument to `pin!`.
540+
# x;
531541
//
532542
// All of the temporaries above are still live here.
533543
# assert_eq!(0, X.load(Relaxed));
@@ -618,6 +628,7 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi
618628
[initialized]: glossary.md#initialized
619629
[interior mutability]: interior-mutability.md
620630
[lazy boolean expression]: expressions/operator-expr.md#lazy-boolean-operators
631+
[macro invocation]: macros.md#macro-invocation
621632
[non-unwinding ABI boundary]: items/functions.md#unwinding
622633
[panic]: panic.md
623634
[place context]: expressions.md#place-expressions-and-value-expressions
@@ -664,3 +675,6 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi
664675
[`match`]: expressions/match-expr.md
665676
[`while let`]: expressions/loop-expr.md#while-let-patterns
666677
[`while`]: expressions/loop-expr.md#predicate-loops
678+
679+
[`pin!`]: std::pin::pin
680+
[`format_args!`]: core::format_args

0 commit comments

Comments
 (0)