Idewave-cli: my pet project

I tried to apply this code snippet on real project and got a lot of errors like:

error[E0195]: lifetime parameters or bounds on method `handle` do not match the trait declaration
  --> src\client\auth\connect_to_realm.rs:14:14
   |
14 |     async fn handle(&mut self, _: &mut HandlerInput) -> HandlerResult {
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
   |
  ::: src\types\traits.rs:19:20
   |
19 |     async fn handle(&mut self, input: &mut HandlerInput) -> HandlerResult;
   |                    - lifetimes in impl do not match this method in trait

also when I try to await the result of handle method, I got another error:

error[E0277]: `Result<HandlerOutput, std::io::Error>` is not a future
   --> src\client\mod.rs:335:78
    |
335 | ...                   let response = handler.handle(&mut handler_input).await;
    |                                                                        ^^^^^^ `Result<HandlerOutput, std::io::Error>` is not a future
    |
    = help: the trait `futures::Future` is not implemented for `Result<HandlerOutput, std::io::Error>`
    = note: Result<HandlerOutput, std::io::Error> must be a future or must implement `IntoFuture` to be awaited
    = note: required because of the requirements on the impl of `std::future::IntoFuture` for `Result<HandlerOutput, std::io::Error>`
help: remove the `.await`
    |
335 -                             let response = handler.handle(&mut handler_input).await;
335 +                             let response = handler.handle(&mut handler_input);

This is code part where I do handlers processing:

pub type ProcessorResult = Vec<Box<dyn PacketHandler>>;

pub type ProcessorFunction = Box<dyn Fn(&mut HandlerInput) -> ProcessorResult + Send>;

fn get_login_processors() -> Vec<ProcessorFunction> {
	return vec![
		Box::new(AuthProcessor::process_input),
	];
}

fn get_realm_processors() -> Vec<ProcessorFunction> {
	return vec![
		Box::new(AuraProcessor::process_input),
		// ...
	];
}

let processors = match connected_to_realm {
	true => Self::get_realm_processors(),
	false => Self::get_login_processors(),
};

let mut handler_input = HandlerInput {
	session: Arc::clone(&session),
	// packet: size + opcode + body, need to parse separately
	data: Some(&packet),
	data_storage: Arc::clone(&data_storage),
	message_income: message_income.clone(),
	dialog_income: dialog_income.clone(),
};

let handler_list = processors
	.iter()
	.map(|processor| processor(&mut handler_input))
	.flatten()
	.collect::<ProcessorResult>();

for mut handler in handler_list {
    let response = handler.handle(&mut handler_input).await;
}

Could you help to fix this issue ?

Hmm, those are strange errors!

For the second error, that might be (assuming the PacketHandler is the trait in the first error) that you might just be seeing an incorrect expansion due to hitting the first error.

For the first error, try adding explicit lifetimes and see if it gives you a better error: normally it already does but perhaps async-trait is confusing it. By default you will get an expansion that looks something like:

async fn handle<'a, 'b>(&'a mut self, _: &'b mut HandlerInput) -> HandlerResult<'a>

That is, any lifetimes in the result are assumed to come from the self parameter. It's a confusing error, though, as the lifetimes should be inferred the same for both the trait and impl...

I added but error same:

error[E0195]: lifetime parameters or bounds on method `handle` do not match the trait declaration
  --> src\client\warden\send_data.rs:21:20
   |
21 |     async fn handle<'a, 'b>(&'a mut self, _: &'b mut HandlerInput) -> HandlerResult {
   |                    ^^^^^^^^ lifetimes do not match method in trait

probably you have another solutions ?

BTW, my IDE show me a warning for this line:

Explicit lifetimes given in parameter types where they could be elided

So it suggests to remove this lifetimes.

I created minimal example for reproduce the issue:

fn get_login_processors() -> Vec<ProcessorFunction> {
    return vec![
        Box::new(TestProcessor::process_input),
    ];
}

fn get_realm_processors() -> Vec<ProcessorFunction> {
    return vec![
        Box::new(TestProcessor2::process_input),
        Box::new(TestProcessor3::process_input),
    ];
}

pub fn test() {
    let (input_tx, _) = mpsc::channel::<IncomeMessageType>();
    let input = &mut HandlerInput {
        session: Arc::new(SyncMutex::new(Session::new())),
        data: None,
        data_storage: Arc::new(SyncMutex::new(DataStorage::new())),
        dialog_income: DialogIncome::new(input_tx.clone()),
        message_income: MessageIncome::new(input_tx.clone()),
    };

    let is_connected_to_realm = true;

    let mut handlers = match is_connected_to_realm {
        true => get_login_processors(),
        false => get_realm_processors(),
    };

    for handler in handlers.iter_mut() {
        handler.handle(input);
    }
}

Error is next:

error[E0599]: no method named `handle` found for mutable reference `&mut Box<dyn for<'r, 's> Fn(&'r mut HandlerInput<'s>) -> Vec<Box<(dyn PacketHandler + 'static)>> + Send>` in the current scope
   --> src\test.rs:213:17
    |
213 |         handler.handle(input);
    |                 ^^^^^^ method not found in `&mut Box<dyn for<'r, 's> Fn(&'r mut HandlerInput<'s>) -> Vec<Box<(dyn PacketHandler + 'static)>> + Send>`
    |
    = note: `handler` is a function, perhaps you wish to call it
    = help: items from traits can only be used if the trait is implemented and in scope
note: `PacketHandler` defines an item `handle`, perhaps you need to implement it
   --> src\test.rs:93:1
    |
93  | trait PacketHandler {
    | ^^^^^^^^^^^^^^^^^^^

probably typing issue, but I am not sure for now where is it

well, this issue was fixed. I am trying to reproduce step-by-step what is going on.

fixed ! The issue was in missed import, also I put wrong param name into functions when copy-paste impl Handler definition, instead of input I passed _. Now it compiles !

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.