Specify temporary lifetime extension through expressions
Reference PR for rust-lang/rust#146098. This includes a reworked definition of extending expressions with the aim of expressing the new semantics more uniformly.
Thanks @dianne; will have a look.
@ehuss and I looked carefully through this today. Some thoughts.
After staring at this awhile, I see why this makes it easier to express the core idea of https://github.com/rust-lang/rust/pull/146098 -- that the relative drop order within an expression should be consistent regardless of where that expression is. Expressing the rules inductively for defining an extending expression ends up pushing against this.
So it does, I think, make a deep sort of sense to drop the inductive approach, as this PR does.
At the same time, the inductive approach was carrying a lot of load. The reader could visualize walking down an expression, outside to inside, at each step checking whether it was still an extending expression. Then there was essentially one key rule that leaned on that:
The operand of an extending [borrow] expression has its [temporary scope] [extended].
What this PR does, in dropping the inductive framing, is to widen the definition of an extending expression significantly, and thereby put a lot more load on the rules that follow to narrow this back down. That's where it ends up getting a bit subtle. With this approach, both @ehuss and I found building intuition and checking the correctness of the rules to be more difficult. So, in dropping the inductive approach, I think we have some work to do in order to recover the same level of clarity.
Adding some !EXAMPLE admonitions that walk through applying these rules would help and be a good start here. It'll also be worth more carefully defining what it means to "extend to" or "extend through" something. The bit where we define some things as "extending through" but then "clamp" them so as to only "extend to" with the final rule ("A temporary scope extended through the scope of a non-extending expression is [extended] to that expression's [temporary scope].") is another bit of subtlety that it might be worth finding another way to express.
I'll leave some other thoughts inline.
I'll try and address individual points soon, but first one higher-level note that I'll try to use as guidance when restructuring:
At the same time, the inductive approach was carrying a lot of load. The reader could visualize walking down an expression, outside to inside, at each step checking whether it was still an extending expression.
This PR's approach still has a visual intuition to it, so it should be presented in a way that makes that clear: instead of walking down an extending expression to check whether an &'s operand is extended, you walk up from an & and check whether you're in an extending expression at each step to determine the temporary scope of the &'s operand. Possibly a separate inductive definition would be useful for making that clear? Along with examples, of course. I was worried defining too many things all at once would make it difficult to follow, but examples should help.
This PR's approach still has a visual intuition to it, so it should be presented in a way that makes that clear: instead of walking down an extending expression to check whether an
&'s operand is extended, you walk up from an&and check whether you're in an extending expression at each step to determine the temporary scope of the&'s operand. Possibly a separate inductive definition would be useful for making that clear? Along with examples, of course.
Yes, exactly. This upward walk is what I'd been expecting but it has to be teased out a bit from the presentation here. Hopefully making that more clear will make the rules here more clear.
:umbrella: The latest upstream changes made this pull request unmergeable. Please resolve the merge conflicts.
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.
Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.
I did a pass to clean up definitions, reframe "extending based on expressions" as a property of & expressions (rather than of extending expressions or let statements), and add clarification and examples. Some parts are still awkward, unfortunately. I've left review comments on a couple things in particular I'm not happy with yet.
We looked through this in the lang-docs office hours call today. The recent changes here are great. Big improvement in clarity. Thanks to @dianne for those.
We talked about how this might benefit from an introduction (perhaps in an admonition) to the "extending based on expressions" section that tries to give some intuition -- a reading guide -- to a reader coming into this section.
I'm going to give this another careful read through, and @ehuss is planning to run some tests with the PR to make sure the interaction of this with the 2024 edition change is clear, but overall, this seems really close.
:umbrella: The latest upstream changes (possibly b14b4e40f53ca468beaf2f5d0dfb4f4c4ba6bc7b) made this pull request unmergeable. Please resolve the merge conflicts.
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.
Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.