This below doesn't compile? WTF??!?
Every tutorial I have read says that when working with generics this is how you do the implementation. Apparently not.
pub struct ThreadPool<F>
where
F: FnOnce(std::net::TcpStream) + Send + 'static,
{
func: F,
}
impl<F> ThreadPool<F>
^^^^^^^^^^^^^ `F` cannot be sent between threads safely
{
}
Yes, but there is a different syntax for implementing a trait and different for providing an implementation AFAIC.
So why on earth would I bother implementing a trait?
Sorry, this does not makes sense. It simply doesn't make sense.
This isn't implementing a trait. It's just moving a where clause from the struct item to the impl item.
The where clause places restrictions on the generic parameters. The reason the word “trait” was used is just because those restrictions are mostly expressed using traits like Send and FnOnce. Such restrictions are called “trait bounds.”
Yes, RFC 2089 will eliminate the need for repetition in some cases. Though note that in this particular case, you can already avoid repetition by removing the bounds from your struct definition.
By removing the bounds from struct you mean doing this:?
pub struct ThreadPool<F>
{
}
Would that mean that I won't be able to 'Send' F between threads? If so, this is not an option because I need to be able to send F between threads.
Second point, you've mentioned that compiler already tells me how to solve it:
error[E0277]: `F` cannot be sent between threads safely
--> src/thread_pool.rs:20:9
|
8 | pub struct ThreadPool<F>
| ---------- required by a bound in this
9 | where
10 | F: FnOnce(std::net::TcpStream) + Send + 'static,
| ---- required by this bound in `thread_pool::ThreadPool`
...
20 | impl<F> ThreadPool<F>
| ^^^^^^^^^^^^^ `F` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `F`
help: consider restricting type parameter `F`
|
20 | impl<F: std::marker::Send> ThreadPool<F>
| ^^^^^^^^^^^^^^^^^^^
Really? Does it really tell me? Because I've actually tried to do what the compiler tells me and it didn't work.
No, F still automatically implements Send as long as all its data does. So any type that was sendable before will still be sendable.
This change does make it possible to construct ThreadPool<F> for cases where F is non-sendable, but generally one prevents by putting the public constructor function, or other required functions, in an impl block with appropriate bounds. Programs that try to use ThreadPool with a non-Send type will still end up getting the same basic error message as before.
The compiler prints two different error messages for the original code, with a “help” suggestion for each error: