mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-30 23:03:06 +03:00
f381e77d35
Move UnwindSafe, RefUnwindSafe, AssertUnwindSafe to core They were previously only available in std::panic, not core::panic. - https://doc.rust-lang.org/1.51.0/std/panic/trait.UnwindSafe.html - https://doc.rust-lang.org/1.51.0/std/panic/trait.RefUnwindSafe.html - https://doc.rust-lang.org/1.51.0/std/panic/struct.AssertUnwindSafe.html Where this is relevant: trait objects! Inside a `#![no_std]` library it's otherwise impossible to have a struct holding a trait object, and at the same time can be used from downstream std crates in a way that doesn't interfere with catch_unwind. ```rust // common library #![no_std] pub struct Thing { pub(crate) x: &'static (dyn SomeTrait + Send + Sync), } pub(crate) trait SomeTrait {...} ``` ```rust // downstream application fn main() { let thing: library::Thing = ...; let _ = std::panic::catch_unwind(|| { let _ = thing; }); // does not work :( } ``` See https://github.com/dtolnay/colorous/blob/a4131708e2f05d2377964981896ff62dbc9b027b/src/gradient.rs#L7-L15 for a real life example of needing to work around this problem. In particular that workaround would not even be viable if implementors of the trait were provided externally by a caller, as the `feature = "std"` would become non-additive in that case. What happens without the UnwindSafe constraints: ```rust fn main() { let gradient = colorous::VIRIDIS; let _ = std::panic::catch_unwind(|| { let _ = gradient; }); } ``` ```console error[E0277]: the type `(dyn colorous::gradient::EvalGradient + Send + Sync + 'static)` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary --> src/main.rs:3:13 | 3 | let _ = std::panic::catch_unwind(|| { let _ = gradient; }); | ^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn colorous::gradient::EvalGradient + Send + Sync + 'static)` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | ::: .rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:430:40 | 430 | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> { | ---------- required by this bound in `catch_unwind` | = help: within `Gradient`, the trait `RefUnwindSafe` is not implemented for `(dyn colorous::gradient::EvalGradient + Send + Sync + 'static)` = note: required because it appears within the type `&'static (dyn colorous::gradient::EvalGradient + Send + Sync + 'static)` = note: required because it appears within the type `Gradient` = note: required because of the requirements on the impl of `UnwindSafe` for `&Gradient` = note: required because it appears within the type `[closure@src/main.rs:3:38: 3:62]` ```