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.
Since the fix to `format_args!` hasn't landed yet, we'll state the
intended rule and leave a note about the current situation.
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
+102Lines changed: 102 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -255,6 +255,92 @@ 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
+
<!-- FIXME: Remove after https://github.com/rust-lang/rust/pull/145882 lands. -->
274
+
> [!NOTE]
275
+
> When there is only one placeholder, `rustc` does not yet treat the corresponding argument as a super operand.
276
+
>
277
+
> For details, see Rust issue [#145880](https://github.com/rust-lang/rust/issues/145880).
278
+
279
+
<!-- FIXME: Simplify after https://github.com/rust-lang/rust/pull/145882 lands. -->
280
+
```rust,edition2024
281
+
# fn temp() -> String { String::from("") }
282
+
// Due to the call being an extending expression and the argument
283
+
// being a super operand, the inner block is an extending expression,
284
+
// so the scope of the temporary created in its trailing expression
285
+
// is extended.
286
+
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*.
291
+
292
+
<!-- FIXME: Simplify after https://github.com/rust-lang/rust/pull/145882 lands. -->
293
+
```rust
294
+
# fntemp() ->String { String::from("") }
295
+
letx=format_args!("{}{}", temp(), temp());
296
+
x; // <-- The temporaries are extended, allowing use here.
297
+
```
298
+
299
+
The expansion of a call to [`format_args!`] sometimes creates other internal *super temporaries*.
300
+
301
+
```rust,compile_fail,E0716
302
+
let x = {
303
+
// This call creates an internal temporary.
304
+
let x = format_args!("{:?}", 0);
305
+
x // <-- The temporary is extended, allowing its use here.
306
+
}; // <-- The temporary is dropped here.
307
+
x; // ERROR
308
+
```
309
+
310
+
```rust
311
+
// This call doesn't create an internal temporary.
312
+
letx= { letx=format_args!("{}", 0); x };
313
+
x; // OK
314
+
```
315
+
316
+
> [!NOTE]
317
+
> The details of when [`format_args!`] does or does not create internal temporaries are currently unspecified.
318
+
319
+
r[expr.super-macros.pin]
320
+
#### `pin!`
321
+
322
+
r[expr.super-macros.pin.super-operands]
323
+
The argument to [`pin!`] is a *super operand*.
324
+
325
+
```rust,edition2024
326
+
# use core::pin::pin;
327
+
# fn temp() {}
328
+
// As above for `format_args!`.
329
+
let _ = pin!({ &temp() }); // OK
330
+
```
331
+
332
+
r[expr.super-macros.pin.super-temporaries]
333
+
The argument to [`pin!`] is a [value expression context] and creates a *super temporary*.
334
+
335
+
```rust
336
+
# usecore::pin::pin;
337
+
# fntemp() {}
338
+
// The argument is evaluated into a super temporary.
339
+
letx=pin!(temp());
340
+
// The temporary is extended, allowing its use here.
341
+
x; // OK
342
+
```
343
+
258
344
r[expr.implicit-borrow]
259
345
### Implicit Borrows
260
346
@@ -285,6 +371,7 @@ Implicit borrows may be taken in the following expressions:
285
371
* Operand of the [dereference operator][deref] (`*`).
286
372
* Operands of [comparison].
287
373
* Left operands of the [compound assignment].
374
+
* Arguments to [`format_args!`] except the format string.
288
375
289
376
r[expr.overload]
290
377
## Overloading Traits
@@ -311,30 +398,39 @@ They are never allowed before:
0 commit comments