I want to refactor my code to use async fn
for handler functions. This is minimal code sample that similar to what I want to refactor:
#[derive(Debug)]
pub struct HandlerInput<'a> {
pub data: Option<&'a [u8]>,
}
#[derive(Debug)]
pub enum HandlerOutput {
Data((u32, Vec<u8>, Vec<u8>)),
ConnectionRequest(String, u16),
Freeze,
Void,
}
pub type HandlerResult = Result<HandlerOutput, Error>;
pub type HandlerFunction = Box<dyn FnMut(&mut HandlerInput) -> HandlerResult + Send>;
pub type ProcessorResult = Vec<HandlerFunction>;
pub type ProcessorFunction = Box<dyn Fn(&mut HandlerInput) -> ProcessorResult + Send>;
// I want to make this function async
pub fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
Ok(HandlerOutput::Void)
}
pub trait OpcodeProcessor {
fn process_input(input: &mut HandlerInput) -> ProcessorResult;
}
pub struct AuthProcessor;
impl OpcodeProcessor for AuthProcessor {
fn process_input(input: &mut HandlerInput) -> ProcessorResult {
let mut reader = Cursor::new(input.data.unwrap());
let opcode = reader.read_u8().unwrap();
let mut message = String::new();
let handlers: Vec<HandlerFunction> = match opcode {
0 => {
message = String::from("LOGIN_CHALLENGE");
vec![Box::new(handler)]
},
1 => {
message = String::from("LOGIN_PROOF");
vec![Box::new(handler)]
},
2 => {
message = String::from("REALM_LIST");
vec![
Box::new(handler),
Box::new(handler),
Box::new(handler),
]
}
_ => vec![],
};
handlers
}
}
So, I tried to replace fn handler
with async fn handler
, also fixed type for HandlerResult
, but got an errors:
error[E0277]: the size for values of type `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)` cannot be known at compilation time
--> src/lib.rs:27:69
|
27 | pub async fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
| _____________________________________________________________________-
28 | | Ok(HandlerOutput::Void)
29 | | }
| | ^
| | |
| |_doesn't have a size known at compile-time
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
= note: the return type of a function must have a statically known size
error[E0618]: expected function, found `Box<dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send>`
--> src/lib.rs:84:19
|
83 | for mut handler in handler_list {
| ----------- `handler` has type `Box<dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send>`
84 | match handler(&mut handler_input).await {
| ^^^^^^^--------------------
| |
| call expression requires function
error[E0271]: type mismatch resolving `for<'r, 's> <for<'t0, 't1> fn(&'t0 mut HandlerInput<'t1>) -> impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)> {handler} as FnOnce<(&'r mut HandlerInput<'s>,)>>::Output == (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
--> src/lib.rs:47:22
|
47 | vec![Box::new(handler)]
| ^^^^^^^^^^^^^^^^^ expected trait object `dyn Future`, found opaque type
|
note: while checking the return type of the `async fn`
--> src/lib.rs:27:55
|
27 | pub async fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
| ^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected trait object `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
found opaque type `impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)>`
= note: required for the cast to the object type `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send`
help: consider `await`ing on the `Future`
|
47 | vec![Box::new(handler).await]
| ++++++
error[E0271]: type mismatch resolving `for<'r, 's> <for<'t0, 't1> fn(&'t0 mut HandlerInput<'t1>) -> impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)> {handler} as FnOnce<(&'r mut HandlerInput<'s>,)>>::Output == (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
--> src/lib.rs:51:22
|
51 | vec![Box::new(handler)]
| ^^^^^^^^^^^^^^^^^ expected trait object `dyn Future`, found opaque type
|
note: while checking the return type of the `async fn`
--> src/lib.rs:27:55
|
27 | pub async fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
| ^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected trait object `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
found opaque type `impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)>`
= note: required for the cast to the object type `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send`
help: consider `await`ing on the `Future`
|
51 | vec![Box::new(handler).await]
| ++++++
error[E0271]: type mismatch resolving `for<'r, 's> <for<'t0, 't1> fn(&'t0 mut HandlerInput<'t1>) -> impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)> {handler} as FnOnce<(&'r mut HandlerInput<'s>,)>>::Output == (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
--> src/lib.rs:56:21
|
56 | Box::new(handler),
| ^^^^^^^^^^^^^^^^^ expected trait object `dyn Future`, found opaque type
|
note: while checking the return type of the `async fn`
--> src/lib.rs:27:55
|
27 | pub async fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
| ^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected trait object `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
found opaque type `impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)>`
= note: required for the cast to the object type `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send`
help: consider `await`ing on the `Future`
|
56 | Box::new(handler).await,
| ++++++
error[E0271]: type mismatch resolving `for<'r, 's> <for<'t0, 't1> fn(&'t0 mut HandlerInput<'t1>) -> impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)> {handler} as FnOnce<(&'r mut HandlerInput<'s>,)>>::Output == (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
--> src/lib.rs:57:21
|
57 | Box::new(handler),
| ^^^^^^^^^^^^^^^^^ expected trait object `dyn Future`, found opaque type
|
note: while checking the return type of the `async fn`
--> src/lib.rs:27:55
|
27 | pub async fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
| ^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected trait object `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
found opaque type `impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)>`
= note: required for the cast to the object type `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send`
help: consider `await`ing on the `Future`
|
57 | Box::new(handler).await,
| ++++++
error[E0271]: type mismatch resolving `for<'r, 's> <for<'t0, 't1> fn(&'t0 mut HandlerInput<'t1>) -> impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)> {handler} as FnOnce<(&'r mut HandlerInput<'s>,)>>::Output == (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
--> src/lib.rs:58:21
|
58 | Box::new(handler),
| ^^^^^^^^^^^^^^^^^ expected trait object `dyn Future`, found opaque type
|
note: while checking the return type of the `async fn`
--> src/lib.rs:27:55
|
27 | pub async fn handler(input: &mut HandlerInput<'_>) -> HandlerResult {
| ^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected trait object `(dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)`
found opaque type `impl Future<Output = (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static)>`
= note: required for the cast to the object type `dyn for<'r, 's> FnMut(&'r mut HandlerInput<'s>) -> (dyn Future<Output = Result<HandlerOutput, std::io::Error>> + 'static) + Send`
help: consider `await`ing on the `Future`
|
58 | Box::new(handler).await,
This is code sandbox for old version (compiles correctly).
This is sandbox for new version (not compiled, show errors).
Could somebody please explain how to fix the code and make handlers possible to be async ?