-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
[WIP] Lower core::ops::drop directly to MIR drop #62864
Conversation
This change causes drop() to always drop in-place. This is meant to allow internal optimizations (see rust-lang#62508). This does _not_ change the documented contract for drop(). Only internal compiler code is allowed to rely on this for now.
@tmandry I would be far more comfortable if this was an intrinsic, in case there are some weird interactions with callers of |
I would like clarification on "guarantee" here. It would be one thing for this to be a pure non-guaranteed optimization that If we're going to do this I would also like to see some tests checking that the static semantics of |
This PR as-implemented is what I think we should do, and the implementation looks like what I would expect. Nominating for the next lang team meeting so we can discuss exactly what guarantees we do or don't want to offer outside of the compiler/stdlib. IMO we do need to be getting into the business of guaranteeing some move elisions both for the purpose of pinning and for systems that can't afford multiple copies of large stack variables, but this PR likely isn't the time/place to begin doing that. |
Right now it is internal-only. This is in the PR description. But I guess the lang team can decide whether to expand this. |
@@ -53,7 +53,7 @@ impl Drop for S { | |||
// StorageLive(_3); | |||
// StorageLive(_4); | |||
// _4 = move _1; | |||
// _3 = const std::mem::drop::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7]; | |||
// drop(_4) -> [return: bb5, unwind: bb7]; |
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.
Does this change actually result in generators being smaller? I was under the impression that the move on the line above was the problem.
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.
No, this change does not change the size of generators, but it allows removing the let
binding inside the .await
expansion, which would reduce the size of generators.
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 doesn't seem to solve that problem either, there's still the move on the line above that needs to be removed.
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.
Yes, good catch, that move will need to be eliminated as well.
Okay, after some further discussion with @cramertj, I realized there are a couple problems with this approach to optimizing For one, the goal (see #62508 (comment)) was to be able to desugar let y = {
loop {
match poll(Pin::new_unchecked(&mut x)) { .. }
}
drop(x);
}; And thus eliminate the But, this won't work at all unless A basic NRVO pass would eliminate this move while allowing us to keep the desugaring the same. That might be a better approach here. The second issue is easier to fix: Eliminating all moves from MIR actually breaks the existing generator optimizations. The One way to fix this I mentioned in #62508 (comment) is to emit |
This change causes drop() to always drop in-place. This is meant to
allow internal optimizations (see #62508).
This does not change the documented contract for drop(). Only internal
compiler code is allowed to rely on this for now.
This is WIP still because it breaks the optimization implemented in #53080.
Closes #62508.
r? @cramertj
cc @arielb1 @eddyb