Skip to content

Commit 5d236de

Browse files
committed
Adjust tail expression temporary scope chapter for new scoping rules
1 parent 5c62125 commit 5d236de

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

src/rust-2024/temporary-tail-expr-scope.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,35 +55,49 @@ In 2021 the local variable `c` is dropped before the temporary created by `c.bor
5555

5656
### Temporary scope may be narrowed
5757

58-
When a temporary is created in order to evaluate an expression, the temporary is dropped based on the [temporary scope rules]. Those rules define how long the temporary will be kept alive. Before 2024, temporaries from tail expressions of a block would be extended outside the block to the next temporary scope boundary. In many cases this would be the end of a statement or function body. In 2024, the temporaries of the tail expression may now be dropped immediately at the end of the block (before any local variables in the block).
58+
When a temporary is created in order to evaluate an expression, the temporary is dropped based on the [temporary scope rules]. Those rules define how long the temporary will be kept alive. Before 2024, temporaries from tail expressions of a block would live past the block to the next temporary scope boundary. In many cases this would be the end of a statement or function body. In 2024, the temporaries of the tail expression may now be dropped immediately at the end of the block (before any local variables in the block).
5959

6060
This narrowing of the temporary scope may cause programs to fail to compile in 2024. For example:
6161

6262
```rust,edition2024,E0716,compile_fail
6363
// This example works in 2021, but fails to compile in 2024.
6464
fn main() {
65-
let x = { &String::from("1234") }.len();
65+
let x = { String::from(" 1234 ").trim() }.len();
6666
}
6767
```
6868

69-
In this example, in 2021, the temporary `String` is extended outside of the block, past the call to `len()`, and is dropped at the end of the statement. In 2024, it is dropped immediately at the end of the block, causing a compile error about the temporary being dropped while borrowed.
69+
In this example, in 2021, the temporary `String` lives past the call to `len()` and is dropped at the end of the statement. In 2024, it is dropped immediately at the end of the block, causing a compile error about the temporary being dropped while borrowed.
7070

71-
The solution for these kinds of situations is to lift the block expression out to a local variable so that the temporary lives long enough:
71+
One solution for these kinds of situations is to lift the temporary out to a local variable so that it lives long enough:
7272

7373
```rust,edition2024
7474
fn main() {
75-
let s = { &String::from("1234") };
76-
let x = s.len();
75+
let s = String::from(" 1234 ");
76+
let x = { s.trim() }.len();
7777
}
7878
```
7979

80-
This particular example takes advantage of [temporary lifetime extension]. Temporary lifetime extension is a set of specific rules which allow temporaries to live longer than they normally would. Because the `String` temporary is behind a reference, the `String` temporary is extended long enough for the next statement to call `len()` on it.
81-
8280
See the [`if let` temporary scope] chapter for a similar change made to temporary scopes of `if let` expressions.
8381

8482
[`if let` temporary scope]: temporary-if-let-scope.md
8583
[temporary scope rules]: ../../reference/destructors.html#temporary-scopes
86-
[temporary lifetime extension]: ../../reference/destructors.html#temporary-lifetime-extension
84+
85+
### Interaction with temporary lifetime extension
86+
87+
[Temporary lifetime extension] is a set of specific rules which allow temporaries to live longer than they normally would, including past block tail expressions. For example:
88+
89+
```rust,edition2024
90+
fn main() {
91+
let x = { &String::from("1234") }.len();
92+
}
93+
```
94+
95+
Because the expression evaluating to the temporary `String` is the operand of a borrow expression, that temporary's scope may be extended.
96+
In this case, it appears syntactically in an [extending] position within the block, so the temporary `String` is extended outside of the block, past the call to `len()`.
97+
Since the block does not however appear in an extending position for the `let` statement as a whole, the temporary `String` is not extended further and is dropped at the end of the statement.
98+
99+
[Temporary lifetime extension]: ../../reference/destructors.html#temporary-lifetime-extension
100+
[extending]: ../../reference/destructors.html#extending-based-on-expressions
87101

88102
## Migration
89103

0 commit comments

Comments
 (0)