rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.12k stars 12.69k forks source link

Drop with guaranteed move elision #62508

Open tmandry opened 5 years ago

tmandry commented 5 years ago

Today, calling drop(_1) results in the following MIR:

_2 = move _1;
std::mem::drop::<T>(_2) -> [return .., unwind ..];

We could instead inline this directly to a MIR drop, with no move. This makes it simpler to do some optimizations in MIR.

This issue specifically tracks having such a drop available in HIR lowering; whether or not to bless std::mem::drop with this guarantee is up for discussion.

cc @cramertj @withoutboats

tmandry commented 5 years ago

await is my primary motivation here, but I'm sure there are others. Today, foo.await; translates roughly to

{
  let pinned = foo;
  // use `Pin::new_unchecked(&mut pinned)`
}  // `pinned` implicitly dropped here

Implicit drops at the end of scope are lowered directly to MIR drop. Because this does not involve moving, the invariants around Pin::new_unchecked are satisfied. However, if we could write it like this:

{
  // use `Pin::new_unchecked(&mut foo)`
  drop(foo);
}

and calling std::mem::drop(foo) was guaranteed not to move foo, then we would get rid of all moves. This would solve #59087 and #62321 with respect to await.

We also need to emit StorageDead on both the return and unwind edges of our MIR drop, or we'll break generator optimizations merged in #60187. (See #61015)

tmandry commented 5 years ago

I would guess that adding this guarantee to std::mem::drop is going to require an RFC (cc @rust-lang/lang). If so, let's define a separate unstable function that we can make the guarantee for. As long as we can invoke it from HIR lowering, that would unblock the case I care most about.

scottmcm commented 5 years ago

How close would it get if drop were just marked [inline(always)]? (Assuming the perf of running the mir inliner for that is acceptable, since there's no body so it'd be hopefully easy.)

cramertj commented 5 years ago

@scottmcm I definitely wouldn't consider the possibility of inlining and optimization enough to be relied on for soundness of any async fn, especially in debug mode.