Can I force a std::‌thread::JoinHandle to be `dyn Any + RefUnwindSafe + UnwindSafe + std::marker::Send`?

I have:

use core::panic::UnwindSafe;
use core::panic::RefUnwindSafe;
use core::any::Any;
pub type SuperSafe = Box<dyn Any + RefUnwindSafe + UnwindSafe + std::marker::Send>;

fn main() {
    let j = std::thread::spawn(move||{});
    let t: SuperSafe = Box::new(j);
}

but I get

error[E0277]: the type `UnsafeCell<Option<Result<(), Box<(dyn Any + Send + 'static)>>>>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
 --> src/main.rs:8:24
  |
8 |     let t: SuperSafe = Box::new(j);
  |                        ^^^^^^^^^^^ `UnsafeCell<Option<Result<(), Box<(dyn Any + Send + 'static)>>>>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
  |
  = help: within `std::thread::Packet<'static, ()>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<Option<Result<(), Box<(dyn Any + Send + 'static)>>>>`
  = note: required because it appears within the type `std::thread::Packet<'static, ()>`
  = note: required because of the requirements on the impl of `UnwindSafe` for `Arc<std::thread::Packet<'static, ()>>`
  = note: required because it appears within the type `std::thread::JoinInner<'static, ()>`
  = note: required because it appears within the type `JoinHandle<()>`
  = note: required for the cast to the object type `dyn Any + RefUnwindSafe + Send + UnwindSafe`

probably because of UnsafeCell, that brings interior mutability. Is there a way to force a JoinHandle to be dyn Any + RefUnwindSafe + UnwindSafe + std::marker::Send? Is there an alternative instead of std::thread::spawn?

I don't want to implement RefUnwindSafe and UnwindSafe and promise I'll never use interior mutability. I wanted to do something without unsafe.

Playground: Rust Playground

To be honest, I see no reason so far why JoinHandle shouldn’t implement both RefUnwindSafe and UnwindSafe; presumably that’s just an oversight that happened because of the (indirectly) contained UnsafeCell. Feel free to open an issue.

With regards to unsafe code, unsafe code is not needed to lift a missing [Ref]UnwindSafe bound, instead you can use the AssertUnwindSafe struct to wrap the thing. Depending on your use case, in case you do use Box::new(AssertUnwindSafe(j)) do note that the dyn Any + … will only be able to successfully downcast to AssertUnwindSafe<JoinHandle<()>> then, not directly to JoinHandle<()> without the wrapper.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.