error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements when using actix and futures

#1

Hi ,

I am testing with Actix (Rust Beginner).

use std::collections::HashMap;
use std::io;
use std::io::Error;

use actix::prelude::*;
use futures::Future;
use futures::future::ok;
use tokio::io::ErrorKind;

fn main() {
    test_actix();
}

fn test_actix() {
    let runner = System::new("Example");
    let actor_two = ActorTwo.start();
    let addr = ActorOne { actor_two: actor_two.clone() }.start();
    let result = addr.send(Ping);
    Arbiter::spawn(
        result.map(
            |res| {
                match res {
                    Ok(result) => println!("Ok Result {}", result),
                    Err(err) => println!("Error result {}", err)
                }
            })
            .map_err(|e| {
                println!("Actor died !!!")
            })
    );
    runner.run();
}


struct Ping;

impl Message for Ping {
    type Result = Result<bool, io::Error>;
}

struct Pong;

impl Message for Pong {
    type Result = Result<bool, io::Error>;
}


struct ActorOne {
    actor_two: Addr<ActorTwo>
}


impl Actor for ActorOne {
    type Context = Context<Self>;
}

impl Handler<Ping> for ActorOne {
    type Result = ResponseFuture<bool, io::Error>;

    fn handle(&mut self, msg: Ping, ctx: &mut Self::Context) -> Self::Result {
        println!("Msg Handled for ping ");

        let result = self.actor_two.send(Ping)
            .map_err(|e| Error::from(ErrorKind::InvalidInput))
            .and_then(|r| r)
            .and_then(|r| {
                // do whatever you want;
                println!("got from actor two");

                // Causing error !!!!
                self.test_self(Ping {});

                // Working fine
                ActorOne::test_associate(Ping {});


                Ok(r)
            });


        Box::new(result)
    }
}

impl ActorOne {
    fn test_self(&self, v: Ping) {
        println!("test 1")
    }

    fn test_associate(v: Ping) {
        println!("test 2")
    }
}


impl Handler<Pong> for ActorOne {
    type Result = Result<bool, io::Error>;

    fn handle(&mut self, msg: Pong, ctx: &mut Self::Context) -> Self::Result {
        println!("Msg Handled for pong ");
        Ok(true)
    }
}


struct ActorTwo;

impl Actor for ActorTwo {
    type Context = Context<Self>;
}

impl Handler<Ping> for ActorTwo {
    type Result = Result<bool, io::Error>;

    fn handle(&mut self, msg: Ping, ctx: &mut Self::Context) -> Self::Result {
        println!("Msg Handled for ping for Actor Two");
        Ok(true)
    }
}

Running this code is throwing following error due to self.test_self(Ping {});

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:66:23
   |
66 |               .and_then(|r| {
   |  _______________________^
67 | |                 // do whatever you want;
68 | |                 println!("got from actor two");
69 | |
...  |
77 | |                 Ok(r)
78 | |             });
   | |_____________^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 60:5...
  --> src/main.rs:60:5
   |
60 | /     fn handle(&mut self, msg: Ping, ctx: &mut Self::Context) -> Self::Result {
61 | |         println!("Msg Handled for ping ");
62 | |
63 | |         let result = self.actor_two.send(Ping)
...  |
81 | |         Box::new(result)
82 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &&mut ActorOne
              found &&mut ActorOne
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the expression is assignable:
           expected std::boxed::Box<(dyn futures::future::Future<Error=std::io::Error, Item=bool> + 'static)>
              found std::boxed::Box<dyn futures::future::Future<Error=std::io::Error, Item=bool>>

error: aborting due to previous error

Thanks in advance

0 Likes

#2

Seems “and_then” would return a future, which must take everything it uses within. It would later be boxed and returned as result of “handle()”. But there end some lifetimes, at least “&self” lifetime ends. And it is used by “test_self()”, to be run in future later. Cloning the referenced things and using these clones inside the future lambdas usually helps.

println!(…
let self1=self.clone();
let result=…
.map_err(…
.and_then(…
.and_then(move |r| …

self1.test_self(…

0 Likes