Skip to content

Commit 25cb880

Browse files
committed
Revise text on built-in macro lifetime extension
In particular, let's break apart the items for `pin!` and `format_args!` so we can be specific about which argument positions are extending expressions. Let's drop the section that talks about these macros creating temporaries. They do, but that's an internal detail. The important part as it pertains to this rule is that these argument positions are extending expressions, which means that a borrow in this position is extending, which means that "the operand of any extending borrow expression has its temporary scope extended".
1 parent 64f24fb commit 25cb880

File tree

1 file changed

+9
-9
lines changed

1 file changed

+9
-9
lines changed

src/destructors.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -487,19 +487,16 @@ expression which is one of the following:
487487
* The final expression of an extending [block expression] except for an [async block expression].
488488
* The final expression of an extending [`if`] expression's consequent, `else if`, or `else` block.
489489
* An arm expression of an extending [`match`] expression.
490-
* The argument(s) to an extending [`pin!`] or [`format_args!`] [macro invocation] expression.
490+
* The argument to an extending [`pin!`] [macro invocation] expression.
491+
* Any arguments following the format string to the [`format_args!`] [macro invocation] expression.
491492

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

495-
r[destructors.scope.lifetime-extension.exprs.borrow]
496+
r[destructors.scope.lifetime-extension.exprs.borrows]
496497
The operand of any extending borrow expression has its temporary scope
497498
extended.
498499

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-
503500
> [!NOTE]
504501
> `rustc` does not treat [array repeat operands] of extending [array] expressions as extending expressions. Whether it should is an open question.
505502
>
@@ -513,6 +510,7 @@ Here are some examples where expressions have extended temporary scopes:
513510
# use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
514511
# use std::pin::pin;
515512
# static X: AtomicU64 = AtomicU64::new(0);
513+
# #[derive(Debug)]
516514
# struct S;
517515
# impl Drop for S { fn drop(&mut self) { X.fetch_add(1, Relaxed); } }
518516
# const fn temp() -> S { S }
@@ -538,6 +536,9 @@ let x = match () { _ => &temp() }; // `match` arm expression.
538536
# x;
539537
let x = pin!(&temp()); // Argument to `pin!`.
540538
# x;
539+
# // TODO: This needs <https://github.com/rust-lang/rust/pull/145882>.
540+
let x = format_args!("{:?}", &temp()); // Argument to `format_args!`.
541+
# x;
541542
//
542543
// All of the temporaries above are still live here.
543544
# assert_eq!(0, X.load(Relaxed));
@@ -668,13 +669,12 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi
668669
[tuple indexing expression]: expressions/tuple-expr.md#tuple-indexing-expressions
669670

670671
[`for`]: expressions/loop-expr.md#iterator-loops
672+
[`format_args!`]: core::format_args
671673
[`if let`]: expressions/if-expr.md#if-let-patterns
672674
[`if`]: expressions/if-expr.md#if-expressions
673675
[`let` statement]: statements.md#let-statements
674676
[`loop`]: expressions/loop-expr.md#infinite-loops
675677
[`match`]: expressions/match-expr.md
678+
[`pin!`]: std::pin::pin
676679
[`while let`]: expressions/loop-expr.md#while-let-patterns
677680
[`while`]: expressions/loop-expr.md#predicate-loops
678-
679-
[`pin!`]: std::pin::pin
680-
[`format_args!`]: core::format_args

0 commit comments

Comments
 (0)