@@ -434,9 +434,9 @@ expression which is one of the following:
434434 expression] , [ braced struct] [ struct expression ] , or [ tuple] [ tuple expression ]
435435 expression.
436436* The arguments to an extending [ tuple struct] or [ tuple variant] constructor expression.
437- * The final expression of any extending [ block expression] .
438- * The arm(s) of an extending [ ` match ` ] expression.
439- * The final expressions of an extending [ ` if ` ] expression's consequent, ` else if ` , and ` else ` blocks .
437+ * The final expression of an extending [ block expression ] except for an [ async block expression] .
438+ * The final expression of an extending [ ` if ` ] expression's consequent, ` else if ` , or ` else ` block .
439+ * An arm expression of an extending [ ` match ` ] expression.
440440
441441So the borrow expressions in ` &mut 0 ` , ` (&1, &mut 2) ` , and ` Some(&mut 3) `
442442are all extending expressions. The borrows in ` &0 + &1 ` and ` f(&mut 0) ` are not.
@@ -448,42 +448,92 @@ extended.
448448
449449Here are some examples where expressions have extended temporary scopes:
450450
451- ``` rust
452- # fn temp () {}
453- // The temporary that stores the result of `temp()` lives in the same scope
454- // as x in these cases.
455- let x = & temp ();
451+ ``` rust,edition2024
452+ # use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
453+ # static X: AtomicU64 = AtomicU64::new(0);
454+ # struct S;
455+ # impl Drop for S { fn drop(&mut self) { X.fetch_add(1, Relaxed); } }
456+ # const fn temp() -> S { S }
457+ let x = &temp(); // Operand of borrow.
456458# x;
457- let x = & temp () as & dyn Send ;
459+ let x = &raw const *&temp(); // Operand of raw borrow.
460+ # assert_eq!(X.load(Relaxed), 0);
461+ let x = &temp() as &dyn Send; // Operand of cast.
458462# x;
459- let x = (& * & temp (),);
463+ let x = (&*&temp(),); // Operand of tuple constructor.
460464# x;
461- let x = { [Some (& temp ()) ] };
465+ let x = { [Some(&temp())] }; // Final expr of block.
462466# x;
463- let x = match () { _ => & temp () };
467+ let x = const { &temp() }; // Final expr of `const` block.
468+ # x;
469+ let x = unsafe { &temp() }; // Final expr of `unsafe` block.
464470# x;
465471let x = if true { &temp() } else { &temp() };
472+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
473+ // Final exprs of `if`/`else` blocks.
474+ # x;
475+ let x = match () { _ => &temp() }; // `match` arm expression.
466476# x;
467- let ref x = temp ();
477+ let ref x = temp(); // Initializer expression.
468478# x;
469- let ref x = * & temp ();
479+ let ref x = *&temp(); // Initializer expression.
470480# x;
481+ //
482+ // All of the temporaries above are still live here.
483+ # assert_eq!(X.load(Relaxed), 0);
471484```
472485
473486Here are some examples where expressions don't have extended temporary scopes:
474487
475- ``` rust,compile_fail
488+ ``` rust,compile_fail,E0716
489+ # fn temp() {}
490+ // Arguments to function calls are not extending expressions. The
491+ // temporary is dropped at the semicolon.
492+ let x = core::convert::identity(&temp()); // ERROR
493+ # x;
494+ ```
495+
496+ ``` rust,compile_fail,E0716
476497# fn temp() {}
477498# trait Use { fn use_temp(&self) -> &Self { self } }
478499# impl Use for () {}
479- // The temporary that stores the result of `temp()` only lives until the
480- // end of the let statement in these cases.
500+ // Receivers of method calls are not extending expressions.
501+ let x = (&temp()).use_temp(); // ERROR
502+ # x;
503+ ```
504+
505+ ``` rust,compile_fail,E0716
506+ # fn temp() {}
507+ // Scrutinees of match expressions are not extending expressions.
508+ let x = match &temp() { x => x }; // ERROR
509+ # x;
510+ ```
481511
482- let x = std::convert::identity(&temp()); // ERROR
512+ ``` rust,compile_fail,E0515
513+ # fn temp() {}
514+ // Final expressions of `async` blocks are not extending expressions.
515+ let x = async { &temp() }; // ERROR
483516# x;
484- let x = (&temp()).use_temp(); // ERROR
517+ ```
518+
519+ ``` rust,compile_fail,E0515
520+ # fn temp() {}
521+ // Final expressions of closures are not extending expressions.
522+ let x = || &temp(); // ERROR
485523# x;
486- let x = match &temp() { x => x }; // ERROR
524+ ```
525+
526+ ``` rust,compile_fail,E0716
527+ # fn temp() {}
528+ // Operands of loop breaks are not extending expressions.
529+ let x = loop { break &temp() }; // ERROR
530+ # x;
531+ ```
532+
533+ ``` rust,compile_fail,E0716
534+ # fn temp() {}
535+ // Operands of breaks to labels are not extending expressions.
536+ let x = 'a: { break 'a &temp() }; // ERROR
487537# x;
488538```
489539
@@ -544,6 +594,7 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi
544594[ tuple variant ] : type.enum.declaration
545595
546596[ array expression ] : expressions/array-expr.md#array-expressions
597+ [ async block expression ] : expr.block.async
547598[ block expression ] : expressions/block-expr.md
548599[ borrow expression ] : expressions/operator-expr.md#borrow-operators
549600[ cast expression ] : expressions/operator-expr.md#type-cast-expressions
0 commit comments