How to think about function trait bounds (specifically that for thread::spawn())?
How to think about function trait bounds (specifically that for thread::spawn())?
spawn in std::thread - Rust
Spawns a new thread, returning a `JoinHandle` for it.
This pertains to Ch 16.03 of The Book, specifically Arc in multithreaded programs
I was just looking at the signature for thread::spawn (documentation linked to by post URL) wondering if and how the requirement for a thread-safe smart pointer is enforced by the type system. In short, how is the use of Arc necessitated by the type system??
For the signature, you get this:
rust
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
Where the parameter f is bound by F: FnOnce() -> T + Send + 'static.
And ... I'm not entirely sure how I should think about this.
Obviously, Send and 'static here are related to my question, where in some way the closure must be thread-safe (through the Send trait) and also have a whole-life-of-the-program lifetime (through the 'static lifetime). Therefore, in some way, something like Rc would be invalid but Arc would be.
But how exactly?
- Are the bounds on the return type of the function/closure, which then sort of back propagate onto the input parameters or captured values of the function/closure?
- Or are these somehow properties of the function itself?
- And why is
Tseparately bound bySend + 'staticwhen they are already present in the bounds onF?
My best guess is that the bounds on F are best parsed as ...
rust
F: ( FnOnce() -> T ) + Send + 'static
T: Send + 'static
IE, Everything separated by a + is unitary, and, therefore, FnOnce() -> T is a single bound and Send another separate bound.
But I'm unsure about that, haven't read that anywhere, and am not really sure how to understand how exactly a function can have Send or 'static without some logic linking that directly to its input parameters?
Thoughts?