-
Notifications
You must be signed in to change notification settings - Fork 14k
Temporary lifetime extension for blocks #146098
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
base: main
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
78995b7 to
2e55e56
Compare
|
@rustbot label -stable-nominated I'm not intending to stable-nominate this, at least. Someone else can, but I don't expect it's needed or that it would be accepted. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment has been minimized.
This comment has been minimized.
2e55e56 to
eafdca9
Compare
|
Does this only affect code in Rust 2024, or would you expect any visible difference in earlier editions? |
|
Suppose we have a macro Or to generalize this, the aim of this PR is that in a non-extending context, If new expressions are added to Rust that are both extending and temporary scopes, I'd want this behavior to apply to them as well. |
|
Since this would effectively reduce the scope of the Rust 2024 tail expression temporary scope change, we'd also want to be sure to reflect that in the behavior of the |
|
I haven't done extensive testing, but see this test diff for that lint: lint-tail-expr-drop-order-borrowck.rs. I'm applying the lifetime extension rules on all editions, and lifetime extension prevents the temporary scope from being registered as potentially forwards-incompatible (even though the extended scopes are technically the same as the old scopes in old editions). Though I think I've convinced myself at this point that lifetime extension doesn't need to be applied to block tails of non-extending old-edition blocks1, so potentially the lint change could be implemented in some other way instead. Footnotes
|
|
☔ The latest upstream changes (presumably #146666) made this pull request unmergeable. Please resolve the merge conflicts. |
eafdca9 to
e649bbe
Compare
|
I've made some revisions. This should now properly handle I think the implementation will likely need optimization and cleanup, but it might take a bit of refactoring to get it to a good place, so I'd like to get a vibe check on the design first, if there's room for it in a lang team meeting. @rustbot label +I-lang-nominated |
|
r? @nnethercote rustbot has assigned @nnethercote. Use |
This removes some unneeded indirection and consolidates the logic for scope resolution.
This means less boilerplate when building the THIR and less possibility for confusion about what to do with the returned scopes from `ScopeTree::temporary_scope`. Possibly migrating `TempLifetime` to `rustc_middle::middle::region` and tweaking its doc comments is left for future work.
bb6b7b6 to
793b852
Compare
This comment has been minimized.
This comment has been minimized.
|
Looks like flakiness? I'll retry CI. By coincidence, the error message is a great reminder that the edition guide's chapter on Rust 2024 block tail temporary scopes will need updating too. I'll make a note in the PR text so it doesn't slip by. Edit: Just noticed another PR failed due to an npm install error too. Looks like it's #t-infra > CI keeps failing because of npm error. |
793b852 to
b8e32ed
Compare
This comment has been minimized.
This comment has been minimized.
b8e32ed to
d77f9ca
Compare
|
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🎉 Experiment
Footnotes
|
|
That's a lot of prepare-fail crates. I'll try re-running it. Looking at the build failures though, it's about the same as before so far.
|
|
@craterbot run mode=build-and-test crates=https://crater-reports.s3.amazonaws.com/pr-146098-6/retry-regressed-list.txt |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
@craterbot p=1 (We can bump the priority when it's going to run quickly due to checking a small number of crates.) |
|
📝 Configuration of the ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
cleanup: merge `RvalueScopes` into `ScopeTree` This gets rid of `RvalueCandidate`, inlines the definition of `RvalueScopes` into `ScopeTree`, and removes two `RvalueScopes`-specific modules, consolidating the scoping logic a bit. Removing the extra step of going from `RvalueCandidate`s to `RvalueScopes` and removing the duplication between them should also hopefully improve perf. I've also taken the liberty of doing a bit of renaming and comment updates, changing some "rvalue scope"s to "extended temporary scope"s. This is a bit closer to the Reference's terminology and makes it clearer that it's specific to temporary lifetime extension. This isn't comprehensive. In particular, I've left `record_rvalue_scope_if_borrow_expr` untouched since #146098 gets rid of it. Pulled out from #146098. r? BoxyUwU as the reviewer of #146098 (though feel free to reassign/claim! this is just cleanup) cc `@dingxiangfei2009`
|
🎉 Experiment
Footnotes
|
|
☔ The latest upstream changes (presumably #148658) made this pull request unmergeable. Please resolve the merge conflicts. |
cleanup: merge `RvalueScopes` into `ScopeTree` This gets rid of `RvalueCandidate`, inlines the definition of `RvalueScopes` into `ScopeTree`, and removes two `RvalueScopes`-specific modules, consolidating the scoping logic a bit. Removing the extra step of going from `RvalueCandidate`s to `RvalueScopes` and removing the duplication between them should also hopefully improve perf. I've also taken the liberty of doing a bit of renaming and comment updates, changing some "rvalue scope"s to "extended temporary scope"s. This is a bit closer to the Reference's terminology and makes it clearer that it's specific to temporary lifetime extension. This isn't comprehensive. In particular, I've left `record_rvalue_scope_if_borrow_expr` untouched since rust-lang/rust#146098 gets rid of it. Pulled out from rust-lang/rust#146098. r? BoxyUwU as the reviewer of rust-lang/rust#146098 (though feel free to reassign/claim! this is just cleanup) cc `@dingxiangfei2009`
NB: The cleanups and refactors from this are currently being split into smaller PRs.
RvalueScopesintoScopeTree#148658 is this PR's commit 07d6b64This implements a revised version of the temporary lifetime extension semantics I suggested in #145838 (comment), with the goal of making temporary lifetimes and drop order more consistent between extending and non-extending blocks. As a consequence, this undoes the breaking change introduced by #145838 (but in exchange has a much larger surface area).
The change this PR hopes to enforce is a general rule: any expression's temporaries should have the same relative drop order regardless of whether the expression is in an extending context or not:
let _ = $expr;anddrop($expr);should have the same drop order. To achieve that, this PR applies lifetime extension rules bottom-up, starting from borrow expressions andsuper let, rather than top-down fromletstatements andconsts/statics. For example:now extends the lifetime of
temp()to outlive the block tail in Rust 2024 regardless of whether the block is an extending expression in aletstatement initializer (in which context it was already extended to outlive the block before this PR). The scoping rules for tails of extending blocks remain the same: extending subexpressions' temporary scopes are extended based on the source of the lifetime extension (e.g. to match the scope of a parentletstatement's bindings). For blocks not extended by any other source, extending borrows in the tail expression now share a temporary scope with the result of the block. This can in turn extend nested blocks within blocks' tail expressions:Since this uses the same rules as
let, it only applies to extending sub-expressions.This also applies to
ifexpressions' blocks and to match arms in all editions, since lifetime extension applies to both of them as well and they both drop their non-extended temporaries. This is where breakage from #145838 was observed:now extends
temp()to have the same temporary scope as the result of theifexpression.As a further consequence, this makes
super letinifexpressions' blocks more consistent with block expressions:previously only worked in extending contexts (since the
super lets would be extended), and now it works everywhere.Reference PR: rust-lang/reference#2051
Edition Guide PR: rust-lang/edition-guide#379
@rustbot label +T-lang