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
Rather than discussing the built-in macros directly in the context of
extending expressions, let's define "super macros", "super operands",
and "super temporaries". It's unfortunate to have to introduce so
many terms, but it still seems a bit clearer as the terms help to
disentangle the many different things at play.
If a [borrow][borrow expression], [dereference][dereference expression],
402
-
[field][field expression], or [tuple indexing expression] has an extended
403
-
temporary scope then so does its operand. If an [indexing expression] has an
404
-
extended temporary scope then the indexed expression also has an extended
405
-
temporary scope.
401
+
If a [borrow], [dereference][dereference expression], [field][field expression], or [tuple indexing expression] has an extended temporary scope then so does its operand. If an [indexing expression] has an extended temporary scope then the indexed expression also has an extended temporary scope.
406
402
407
403
r[destructors.scope.lifetime-extension.patterns]
408
404
#### Extending based on patterns
@@ -479,26 +475,24 @@ For a let statement with an initializer, an *extending expression* is an
479
475
expression which is one of the following:
480
476
481
477
* The initializer expression.
482
-
* The operand of an extending [borrow expression].
478
+
* The operand of an extending [borrow] expression.
479
+
* The [super operands] of an extending [super macro call] expression.
483
480
* The operand(s) of an extending [array][array expression], [cast][cast
484
481
expression], [braced struct][struct expression], or [tuple][tuple expression]
485
482
expression.
486
483
* The arguments to an extending [tuple struct] or [tuple variant] constructor expression.
487
484
* The final expression of an extending [block expression] except for an [async block expression].
488
485
* The final expression of an extending [`if`] expression's consequent, `else if`, or `else` block.
489
486
* An arm expression of an extending [`match`] expression.
490
-
* The argument(s) to an extending [`pin!`] or [`format_args!`][macro invocation] expression.
491
487
492
488
So the borrow expressions in `&mut 0`, `(&1, &mut 2)`, and `Some(&mut 3)`
493
489
are all extending expressions. The borrows in `&0 + &1` and `f(&mut 0)` are not.
Copy file name to clipboardExpand all lines: src/expressions.md
+96Lines changed: 96 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -255,6 +255,86 @@ When using a value expression in most place expression contexts, a temporary unn
255
255
The expression evaluates to that location instead, except if [promoted] to a `static`.
256
256
The [drop scope] of the temporary is usually the end of the enclosing statement.
257
257
258
+
r[expr.super-macros]
259
+
### Super macros
260
+
261
+
r[expr.super-macros.intro]
262
+
Certain built-in macros may create [temporaries] whose [scopes][temporary scopes] may be [extended]. These temporaries are *super temporaries* and these macros are *super macros*. [Invocations][macro invocations] of these macros are *super macro call expressions*. Arguments to these macros may be *super operands*.
263
+
264
+
> [!NOTE]
265
+
> When a super macro call expression is an [extending expression], its super operands are [extending expressions] and the [scopes][temporary scopes] of the super temporaries are [extended]. See [destructors.scope.lifetime-extension.exprs].
266
+
267
+
r[expr.super-macros.format_args]
268
+
#### `format_args!`
269
+
270
+
r[expr.super-macros.format_args.super-operands]
271
+
Except for the format string argument, all arguments passed to [`format_args!`] are *super operands*.
272
+
273
+
<!-- TODO: Simplify after https://github.com/rust-lang/rust/pull/145882 lands. -->
274
+
```rust,edition2024
275
+
# fn temp() -> String { String::from("") }
276
+
// Due to the call being an extending expression and the argument
277
+
// being a super operand, the inner block is an extending expression,
278
+
// so the scope of the temporary created in its trailing expression
279
+
// is extended.
280
+
let _ = format_args!("{:?}{}", (), { &temp() }); // OK
The super operands of [`format_args!`] are [implicitly borrowed] and are therefore [place expression contexts]. When a [value expression] is passed as an argument, it creates a *super temporary*.
285
+
286
+
<!-- TODO: Simplify after https://github.com/rust-lang/rust/pull/145882 lands. -->
287
+
```rust
288
+
# fntemp() ->String { String::from("") }
289
+
letx=format_args!("{}{}", temp(), temp());
290
+
x; // <-- The temporaries are extended, allowing use here.
291
+
```
292
+
293
+
The expansion of a call to [`format_args!`] sometimes creates other internal *super temporaries*.
294
+
295
+
```rust,compile_fail,E0716
296
+
let x = {
297
+
// This call creates an internal temporary.
298
+
let x = format_args!("{:?}", 0);
299
+
x // <-- The temporary is extended, allowing its use here.
300
+
}; // <-- The temporary is dropped here.
301
+
x; // ERROR
302
+
```
303
+
304
+
```rust
305
+
// This call doesn't create an internal temporary.
306
+
letx= { letx=format_args!("{}", 0); x };
307
+
x; // OK
308
+
```
309
+
310
+
> [!NOTE]
311
+
> The details of when [`format_args!`] does or does not create internal temporaries are currently unspecified.
312
+
313
+
r[expr.super-macros.pin]
314
+
#### `pin!`
315
+
316
+
r[expr.super-macros.pin.super-operands]
317
+
The argument to [`pin!`] is a *super operand*.
318
+
319
+
```rust,edition2024
320
+
# use core::pin::pin;
321
+
# fn temp() {}
322
+
// As above for `format_args!`.
323
+
let _ = pin!({ &temp() }); // OK
324
+
```
325
+
326
+
r[expr.super-macros.pin.super-temporaries]
327
+
The argument to [`pin!`] is a [value expression context] and creates a *super temporary*.
328
+
329
+
```rust
330
+
# usecore::pin::pin;
331
+
# fntemp() {}
332
+
// The argument is evaluated into a super temporary.
333
+
letx=pin!(temp());
334
+
// The temporary is extended, allowing its use here.
335
+
x; // OK
336
+
```
337
+
258
338
r[expr.implicit-borrow]
259
339
### Implicit Borrows
260
340
@@ -285,6 +365,7 @@ Implicit borrows may be taken in the following expressions:
285
365
* Operand of the [dereference operator][deref] (`*`).
286
366
* Operands of [comparison].
287
367
* Left operands of the [compound assignment].
368
+
* Arguments to [`format_args!`] except the format string.
288
369
289
370
r[expr.overload]
290
371
## Overloading Traits
@@ -311,30 +392,39 @@ They are never allowed before:
0 commit comments