In May, in the pull request where UnwindSafe was moved to core, it was mentioned the libs team may want to deprecate it Move UnwindSafe, RefUnwindSafe, AssertUnwindSafe to core by dtolnay · Pull Request #84662 · rust-lang/rust · GitHub
I found a comment in this issue mentioning deprecation as far back as 2019: `UnwindSafe` is unergonomic · Issue #40628 · rust-lang/rust · GitHub
- Feature Name: deprecate_unwind_safe
- Start Date: 2022-01-17
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
Summary
Currently rust has the UnwindSafe and RefUnwindSafe marker traits. This RFC proposes to deprecate them, and remove the F: UnwindSafe
bound on catch_unwind.
Motivation
Unwind safety is not actually related to safety. It acts as a lint. AssertUnwindSafe can be used to ignore it, and using it does not require unsafe. If using it results in undefined behaviour or unsoundness, the problem lies elsewhere. The existence of unwind safety makes it seem as if you can rely on it for soundness, which is not true (See discussion in UnwindSafe docs are unclear.)
It can also be problematic when a type does not implement the marker trait, but it could, notably with trait objects (See discussion in UnwindSafe
is unergonomic). It can also be a pain point for library authors, who are not sure if they should add a bound on them for their generic types to guarantee their types are UnwindSafe, which would make their downstream users sometimes have to use AssertUnwindSafe despite not using catch_unwind just to satisfy the bounds.
Guide-level explanation
UnwindSafe and RefUnwindSafe are deprecated, and you never need to use them. If you can cause undefined behaviour with catch_unwind, something else is unsound.
The following now compiles:
let x = std::cell::UnsafeCell::new(1u8);
let result = std::panic::catch_unwind(|| {
println!("{:p}", x.get());
panic!()
});
Which used to require AssertUnwindSafe:
let x = std::panic::AssertUnwindSafe(std::cell::UnsafeCell::new(1u8));
let result = std::panic::catch_unwind(|| {
println!("{:p}", x.get());
panic!()
});
Reference-level explanation
UnwindSafe and RefUnwindSafe are now deprecated, and the UnwindSafe bound on the F generic parameter of catch_unwind is removed.
Drawbacks
We lose any value that UnwindSafe was actually providing as a lint.
Rationale and alternatives
- We could keep UnwindSafe without deprecating it.
- We could make using something !UnwindSafe through catch_unwind a warning via language magic instead of completely removing it
Prior art
In the pull request where UnwindSafe was moved to core, it was mentioned the libs team may want to deprecate it Move UnwindSafe, RefUnwindSafe, AssertUnwindSafe to core by dtolnay · Pull Request #84662 · rust-lang/rust · GitHub
I found a comment in this issue mentioning deprecation as far back as 2019: `UnwindSafe` is unergonomic · Issue #40628 · rust-lang/rust · GitHub
Unresolved questions
- How will this impact the ecosystem? How will libraries with an MSRV deal with this?