Optimize away poison guards when std is built with panic=abort by tmandry · Pull Request #100603 · rust-lang/rust (original) (raw)

Note: To take advantage of this PR, you will have to use -Zbuild-std or build your own toolchain. rustup toolchains always link to a libstd that was compiled with panic=unwind, since it's compatible with panic=abort code.

When std is compiled with panic=abort we can remove a lot of the poison machinery from the locks. This changes the Flag and Guard types to be ZSTs. It also adds an uninhabited member to PoisonError so the compiler knows it can optimize away the Result::Err paths, and make LockResult<T> layout-equivalent to T.

Is this a breaking change?

PoisonError::new now panics if invoked from a libstd built with panic="abort" (or any non-unwind strategy). It is unclear to me whether to consider this a breaking change.

In order to encounter this behavior, both of the following must be true:

Using a libstd with panic="abort"

This is pretty uncommon. We don't build libstd with that in rustup, except in (Tier 2-3) platforms that do not support unwinding, most notably wasm.

Most people who do this are using cargo's -Z build-std feature, which is unstable.

panic="abort" is not a supported option in Rust's build system. It is possible to configure it using CARGO_TARGET_xxx_RUSTFLAGS, but I believe this only works on non-host platforms.

Creating PoisonError manually

This is also unlikely. The only common use case I can think of is in tests, and you can't run tests with panic="abort" without the unstable -Z panic_abort_tests flag.

It's possible that someone is implementing their own locks using std's PoisonError and defining "thread failure" to mean something other than "panic". If this is the case then we would break their code if it was used with a panic="abort" libstd. The locking crates I know of don't replicate std's poison API, but I haven't done much research into this yet.

I've touched on a fair number of considerations here. Which ones do people consider relevant?