- Feature Name: deprecate_unwind_safe
- Start Date: 2022-01-17
- RFC PR: rust-lang/rfcs#3260
- Rust Issue: rust-lang/rust#0000
Currently rust has the UnwindSafe and RefUnwindSafe marker traits. This RFC proposes to deprecate them, and remove the F: UnwindSafe
bound on catch_unwind.
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.
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!()
});
UnwindSafe and RefUnwindSafe are now deprecated, and the UnwindSafe bound on the F generic parameter of catch_unwind is removed.
We lose any value that UnwindSafe was actually providing as a lint.
- We could keep UnwindSafe as-is without deprecating it.
- Rename UnwindSafe to something that does not mention "safety".
- We could make using something !UnwindSafe through catch_unwind a warning via language magic instead of completely removing it. This would probably require a fundamentally new feature of trait resolution, to turn a missing trait implementation into a warning.
In the pull request where UnwindSafe was moved to core, it was mentioned the libs team may want to deprecate it rust-lang/rust#84662 (comment)
I found a comment in this issue mentioning deprecation as far back as 2019: rust-lang/rust#40628 (comment)
- How will this impact the ecosystem? How will libraries with an MSRV deal with this?