Send non-static references to threads

Suppose I have a program like this:

fn foo<T: Send>(x: T) {
    let handle = thread::spawn(move || {
        // take ownership of the reference
        let y = x;
    });
    handle.join();
}

This should be safe, since the thread is joined before foo returns, therefore the thread never outlives x. However, Rust only allows sending types bounded by a 'static lifetime. How do I convince Rust to let me do this?

I know crossbeam::scope::spawn solves the problem in this particular instance. However, in my situation, the thread is not bound to a particular scope, but rather to another value (the thread is joined only when that value is dropped).

I also noticed that mem::transmute mentions extending lifetime. However, in my situation, T is not a direct reference, but rather a struct that contains reference (actually, it's a closure, but the idea is the same), so I don't know how mem::transmute would help.

Any suggestions?

You can't do this because destructors are not guaranteed to run.

You can transmute the type from MyStruct<'a> to MyStruct<'static>, which you can then move into the spawned thread. (Of course, you must then ensure that the thread really does finish before the original borrow ends, and that it does not expose the reference to any code that could copy it into a longer-lived location, since the compiler will not be able to enforce this anymore.)

Good point. I'll think more about it later. But suppose I can prove it's safe, then what?

In my case, T is a closure type, so I can't write it out. How would I add 'static to it then?

EDIT: wrap it in another struct maybe?

If you are in a situation where you know that the code doesn't leak the destructor using mem::forget, a reference cycle, or other means, then you can use an unsafe transmute.

You can transmute Box<dyn Fn() + Send + 'a> to Box<dyn Fn() + Send + 'static>.

1 Like

That will work I suppose. Is it possible without boxing the closure?

I'd assume when you're talking about spawning a whole new thread, a single allocation more really won't matter at all.

Ah, indeed. Thanks, everyone.

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.