Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a section dedicated to Edition 2024 changes to temporary scopes #1592

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions src/destructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,20 +211,22 @@ smallest scope that contains the expression and is one of the following:
guard.
* The body expression for a match arm.
* Each operand of a [lazy boolean expression].
* The pattern-matching condition and consequent body of [`if let`] ([destructors.scope.temporary.edition2024]).
* The entirety of the tail expression of a block ([destructors.scope.temporary.edition2024]).

> **Notes**:
>
> Temporaries that are created in the final expression of a function
> body are dropped *after* any named variables bound in the function body.
> Their drop scope is the entire function, as there is no smaller enclosing temporary scope.
>
> The [scrutinee] of a `match` expression is not a temporary scope, so
> temporaries in the scrutinee can be dropped after the `match` expression. For
> example, the temporary for `1` in `match 1 { ref mut z => z };` lives until
> the end of the statement.

r[destructors.scope.temporary.edition2024]
> **Edition differences**: The 2024 edition added two new temporary scope narrowing rules: `if let` temporaries are dropped before the `else` block, and temporaries of tail expressions of blocks are dropped immediately after the tail expression is evaluated.

Some examples:

<!--TODO: edition2024 -->
```rust
# struct PrintOnDrop(&'static str);
# impl Drop for PrintOnDrop {
Expand All @@ -242,17 +244,25 @@ if PrintOnDrop("If condition").0 == "If condition" {
unreachable!()
};

if let "if let scrutinee" = PrintOnDrop("if let scrutinee").0 {
PrintOnDrop("if let consequent").0
// `if let consequent` dropped here
}
// `if let scrutinee` is dropped here
else {
PrintOnDrop("if let else").0
// `if let else` dropped here
};

// Dropped before the first ||
(PrintOnDrop("first operand").0 == ""
// Dropped before the )
|| PrintOnDrop("second operand").0 == "")
// Dropped before the ;
|| PrintOnDrop("third operand").0 == "";

// Dropped at the end of the function, after local variables.
// Changing this to a statement containing a return expression would make the
// temporary be dropped before the local variables. Binding to a variable
// which is then returned would also make the temporary be dropped first.
// Scrutinee is dropped at the end of the function, before local variables
// (because this is the tail expression of the function body block).
match PrintOnDrop("Matched value in final expression") {
// Dropped once the condition has been evaluated
_ if PrintOnDrop("guard condition").0 == "" => (),
Expand Down