Rust: E0562 al implementar un rasgo genérico
Estoy probando Rust y ❤️ hasta ahora.
Pero actualmente estoy atrapado con rasgos genéricos :)
Status quo:
Existe este rasgo que quiero implementar, que no puedo modificar:
pub trait Handler<R, B, E> {
fn run(&mut self, event: http::Request<B>) -> Result<R, E>;
}
Una implementación de ese rasgo en la misma biblioteca es:
impl<Function, R, B, E> Handler<R, B, E> for Function
where
Function: FnMut(http::Request<B>) -> Result<R, E>,
{
fn run(&mut self, event: http::Request<B>) -> Result<R, E> {
(*self)(event)
}
}
Y esta implementación se puede utilizar de la siguiente manera:
fn handler(req: http::Request<Body>) -> Result<impl IntoResponse, MyError> {
...
}
Con el IntoReponserasgo:
pub trait IntoResponse {
fn into_response(self) -> Response<Body>;
}
Lo que quiero hacer:
Quiero implementar ese rasgo para que una estructura pueda usarse con los tipos mencionados anteriormente.
Lo intenté:
impl Handler<impl IntoResponse, Body, MyError> for GQLHandler {
fn run(&mut self, req: http::Request<Body>) -> Result<impl IntoResponse, MyError> {
...
}
}
Pero eso resulta en los errores:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> handlers/gql.rs:18:14
|
18 | impl Handler<impl IntoResponse, Body, NowError> for GQLHandler {
| ^^^^^^^^^^^^^^^^^
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> handlers/gql.rs:19:59
|
19 | fn run(&mut self, req: http::Request<Body>) -> Result<impl IntoResponse, NowError> {
| ^^^^^^^^^^^^^^^^^
Funciona por causa si lo implemento para un tipo específico, por ejemplo
impl Handler<http::Response<Body>, Body, NowError> for GQLHandler {
fn run(&mut self, req: http::Request<Body>) -> Result<http::Response<Body>, NowError> {
pero me gustaría mantener el de impl Traitalguna manera.
Esperamos cualquier sugerencia.
Gracias y saludos Thomas
EDITAR:
Siguiendo con la respuesta de @ MaxV (¡Gracias!), Lamentablemente, eso no funcionó para mí (por eso no acepté esta respuesta todavía).
Ver este patio de recreo
Cuando intento regresar Ok(...)con un tipo implementado IntoResponse, aparece el siguiente error:
|
3 | impl<T: IntoResponse> Handler<T, Body, MyError> for GQLHandler {
| - this type parameter
4 | fn run(&mut self, req: Request<Body>) -> Result<T, MyError> {
5 | Ok(Response::<()>::new(()))
| ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `http::Response`
|
= note: expected type parameter `T`
found struct `http::Response<()>`
a pesar de que implementé IntoResponsepara Response:
trait IntoResponse{
fn foo(&self);
}
impl IntoResponse for Response<()>
{
fn foo(&self) {}
}
¿Qué me estoy perdiendo?
Respuestas
Nueva respuesta
Parece que estás buscando tipos existenciales :
En este momento, no es posible devolver un
impl Traittipo de una implementación de rasgo. Esta es una gran restricción que este RFC corrige <...>
Los tipos existenciales RFC se fusionaron pero la implementación no se estabilizó. Puede seguir el progreso allí .
Respuesta original
No puede usar implallí, pero puede resolverlo de esta manera:
Patio de recreo
impl<T: IntoResponse> Handler<T, Body, MyError> for GQLHandler {
fn run(&mut self, req: http::Request<Body>) -> Result<T, MyError> {
// ...
}
}