-
Notifications
You must be signed in to change notification settings - Fork 13.7k
don't apply temporary lifetime extension rules to non-extended super let
#145838
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: master
Are you sure you want to change the base?
Conversation
This comment has been minimized.
This comment has been minimized.
0542d4f
to
a35548f
Compare
Copied from #145784 (comment), since I think this is a notable caveat of this PR and worth considering before approving it: This comes with a bit of a gotcha in terms of temporary lifetimes: it might be strange that the non_extending({ let x = { &temp() }; f(x) }); // ok than in non_extending({ super let x = { &temp() }; f(x) }); // error Though the case for |
Also copied since it motivates this PR: I think something like this may be necessary for the identity &EXPR === { super let x = &EXPR; x } to hold in both extending and non-extending contexts without changing how block tail expression scopes work. Substituting, e.g. &{ &temp() } drops { super let x = &{ &temp() }; x } would extend it to outlive |
To confirm, with this PR, does this behavior hold (in Rust 2024)?: fn f<T>(_: LogDrop<'_>, x: T) -> T { x }
// These two should be the same.
assert_drop_order(1..=3, |e| {
let _v = f(e.log(2), &{ &raw const *&e.log(1) });
drop(e.log(3));
});
assert_drop_order(1..=3, |e| {
let _v = f(e.log(2), {
super let v = &{ &raw const *&e.log(1) };
v
});
drop(e.log(3));
});
// These two should be the same.
assert_drop_order(1..=3, |e| {
let _v = f(e.log(1), &&raw const *&e.log(2));
drop(e.log(3));
});
assert_drop_order(1..=3, |e| {
let _v = f(e.log(1), {
super let v = &&raw const *&e.log(2);
v
});
drop(e.log(3));
});
// These two should be the same.
assert_drop_order(1..=2, |e| {
let _v = &{ &raw const *&e.log(2) };
drop(e.log(1));
});
assert_drop_order(1..=2, |e| {
let _v = {
super let v = &{ &raw const *&e.log(2) };
v
};
drop(e.log(1));
}); (If any of these are missing, please add them as tests.) |
Does this PR affect any edition 2021 code? |
a35548f
to
f0c43cf
Compare
Those all hold under this PR, yes. I've added them all as tests (with some additional versioning to account for the Edition-dependent drop order in the first one); thanks!
Not that I'm aware of. That detail matters in Edition 2024, since the nested |
This comment has been minimized.
This comment has been minimized.
f0c43cf
to
387cfa5
Compare
// We have extending borrow expressions within the initializer | ||
// expression. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// We have extending borrow expressions within the initializer | |
// expression. | |
// We have extending borrow expressions within a non-extending | |
// expression within the initializer expression. |
(Revising my earlier text here.)
Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
cc @m-ou-se @rust-lang/libs-api |
387cfa5
to
23caea2
Compare
I've reviewed 13 of the test failures in #145838 (comment) (top-to-bottom from |
Saethlin told me that I should wait for the retry before checking the test failures. |
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
🎉 Experiment
Footnotes
|
At a glance, the "build compiler error" failures look real, following the pattern of using In the mean time, I've implemented my lifetime extension suggestion for block tails. It's not ready for review yet, but it lives at #146098 now for testing/discussion purposes. |
Retrying since there's a lot of "cannot find directory"s. |
👌 Experiment ℹ️ 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 |
🎉 Experiment
Footnotes
|
22 isn't too bad to sift through. I'll write up a list of what I find. As before, the build failures look real and the test failures I've seen so far look spurious. |
Build failures (all real, same crates as in #145838 (comment), though the last failure there is missing):
For completeness, the last build failure from the first crater run:
Test failures (all spurious):
|
In case anyone else is wondering about the disappearance of https://github.com/musicodeXQQ/updownserv. |
// Don't lifetime-extend child `super let`s or block tail expressions' temporaries in | ||
// the initializer when this `super let` is not itself extended by a parent `let` | ||
// (#145784). Block tail expressions are temporary drop scopes in Editions 2024 and | ||
// later, their temps shouldn't outlive the block in e.g. `f(pin!({ &temp() }))`. | ||
extend_initializer = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an initial quick review - I don't really know this code and really need to dig in to review this properly. My general initial thought is that this change is kind of not-so-great. I wonder if there's some kind of refactoring that could be done to this that would make this code more "clean"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I also tried making the if
expression containing that evaluate to a bool
(so it could be assigned to a variable), and I tried let extend_initializer;
(so it could be assigned in each branch), but in both cases it felt even messier with the else
block needed. Maybe it would be nicer as a match
? I hesitated since it looked like would require a lot of reindentation, but I'll give it a shot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like it didn't even require reindenting or reflowing! I think it's much nicer as a match
, but possibly it could be cleaned up with further refactoring to not require assigning to a bool variable at all. (diff)
Co-authored-by: Travis Cross <[email protected]>
7f4b0f4
to
d5b5a4a
Compare
Reference PR: rust-lang/reference#1980
This changes the semantics for
super let
(and macros implemented in terms of it, such aspin!
,format_args!
,write!
, andprintln!
) as suggested by @theemathas in #145784 (comment), makingsuper let
initializers only count as extending expressions when thesuper let
itself is within an extending block. Sincesuper let
initializers aren't temporary drop scopes, their temporaries outside of inner temporary scopes are effectively always extended, even when not in extending positions; this only affects two cases as far as I can tell:f(pin!({ &temp() }))
droptemp()
at the end of the block in Rust 2024, whereas previously it would live until after the call tof
because syntactically thetemp()
was in an extending position as a result ofsuper let
inpin!
's expansion.super let
nested within a non-extendedsuper let
is no longer extended. i.e. a normallet
is required to treatsuper let
s as extending (in which case nestedsuper let
s will also be extending).Closes #145784
This is a breaking change. Both static and dynamic semantics are affected. The most likely breakage is for programs to stop compiling, but it's technically possible for drop order to silently change as well (as in #145784). Since this affects stable macros, it probably would need a crater run.
Nominating for discussion alongside #145784: @rustbot label +I-lang-nominated +I-libs-api-nominated
Tracking issue for
super let
: #139076