-
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. 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
With regard to the Reference docs, the ways this is exposed (as far as I'm aware) are through If The same goes for This extends to fn main() {
assert_drop_order(1..=2, |o| {
println!("{:?}{:?}", { &o.log(2) }, drop(o.log(1)));
});
} This didn't compile before 1.89, but in 1.89, 1.90-beta, and nightly the It also doesn't compile in 1.89 with only a single Footnotes
|
23caea2
to
7f4b0f4
Compare
It'd be best to (at least) document this in the Reference. E.g., we could say that certain built-in macros are extending expressions, and then we could list them and describe the caveats about when they are or are not extending expressions. |
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.
This looks correct to me. It results in the right behavior for pin!() and format_args!() (the only stable uses of super let
).
It does make super let
as a statement even weirder, but that's not surprising. We already concluded that { super let _ = ..; ..}
should be some sort of expression/operator/syntax of its own, rather than a block with a statement. This is just an extra argument for that.
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