Hi,
I was hacking on my personal project trying to generalize a few things and I stumbled on an error that I don't quite understand. I have a following trait:
trait Service: Send + Sync {
type Response: Send + Serialize;
type Request: DeserializeOwned + Send;
fn handle_request(
&self,
message: Self::Request,
) -> Pin<Box<dyn Future<Output = Self::Response> + Send + '_>>;
}
When I implement the trait on a concrete type everything is fine, here is an example:
impl Service for WorldServer
{
type Response = WorldResponse;
type Request = WorldRequest;
fn handle_request(
&self,
message: Self::Request,
) -> Pin<Box<dyn Future<Output = Self::Response> + Send + '_>> {
Box::pin(async {
match message {
WorldRequest::HelloRequest(hello_request) => WorldResponse::HelloResponse(self.hello(hello_request.name).await),
}
})
}
}
This is basically matching the message and calling a concrete method on the WorldServer
type. At the moment it only handles one function, but you can imaging more functions being handled in the match
statement.
Now I wanted to change the implementation so the Service
is implemented for any type that implements a certain trait, for example:
impl<T> Service for T
where
T: World + Sync + Send,
{
type Response = WorldResponse;
type Request = WorldRequest;
fn handle_request(
&self,
message: Self::Request,
) -> Pin<Box<dyn Future<Output = Self::Response> + Send + '_>> {
Box::pin(async {
match message {
WorldRequest::HelloRequest(hello_request) => WorldResponse::HelloResponse(self.hello(hello_request.name).await),
}
})
}
}
Here I implement for any type T, which implements the World
trait (which is also a trait that WorldServer
had implemented in the previous example). The problem is that now I get the following error:
error: future cannot be sent between threads safely
--> utils/src/main.rs:123:9
|
123 | / ... Box::pin(async {
124 | | ... match message {
125 | | ... WorldRequest::HelloRequest(hello_request) => WorldResponse::HelloResponse(self.he...
126 | | ... }
127 | | ... })
| |________^ future created by async block is not `Send`
|
= help: within `[async block@utils/src/main.rs:123:18: 127:10]`, the trait `std::marker::Send` is not implemented for `impl futures::Future<Output = std::string::String>`
note: future is not `Send` as it awaits another future which is not `Send`
--> utils/src/main.rs:125:91
|
125 | ...dResponse::HelloResponse(self.hello(hello_request.name).await),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl futures::Future<Output = std::string::String>`, which is not `Send`
= note: required for the cast from `Pin<Box<[async block@utils/src/main.rs:123:18: 127:10]>>` to `Pin<Box<dyn futures::Future<Output = WorldResponse> + std::marker::Send>>`
I'm guessing that because the trait has different bounds than the concrete type, I'm missing some bounds in the definition, but I fail to see what would help here. Any ideas on what's going on here?