Future/tokio lifetime troubles


#1

I’m having error[E0495]: cannot infer an appropraite lifetime due to conflicting requirements. Can someone please help me understand what’s exactly wrong here or even how to fix it? I’m unable to comprehend the error.

I previously used just self and moved to &self now, since then I get this error.

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> /mnt/windows/code/oss/reqrs/src/lib.rs:122:51
    |
122 |           TcpStream::connect(&socket_addr).and_then(move |stream| {
    |  ___________________________________________________^
123 | |             tokio::io::write_all(stream, dst_vec)
124 | |                 .and_then(|(stream, _)| {
125 | |                     let initial_vec: Vec<u8> = vec![0; INITIAL_BUF_SIZE];
...   |
197 | |                 .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
198 | |         })
    | |_________^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 108:5...
   --> /mnt/windows/code/oss/reqrs/src/lib.rs:108:5
    |
108 | /     fn begin_read(
109 | |         &self,
110 | |         key: (Arc<String>, u16),
111 | |         dst_vec: Vec<u8>,
...   |
198 | |         })
199 | |     }
    | |_____^
    = note: ...so that the types are compatible:
            expected &Client
               found &Client
    = note: but, the lifetime must be valid for the static lifetime...
note: ...so that return value is valid for the call
   --> /mnt/windows/code/oss/reqrs/src/lib.rs:112:10
    |
112 |     ) -> impl Future<Item = ClientResponse, Error = io::Error> + Send {
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is my code:

Many thanks


#2

There’s a self.continue_read(...) method call at the bottom of that method - this causes self to be captured in that closure. The impl Future return type is implicitly 'static - it doesn’t capture anything from its environment. This is the conflict the compiler is reporting.

You can try indicating that the return type captures self via a signature change:

fn begin_read<'a>(&'a self, ...) -> impl Future<...> + 'a { ... }

I suspect this may not work, ultimately, because you’ll end up needing a 'static future to submit to whatever executor you’re using (eg tokio).

Given you probably don’t want to go back to consuming self in the methods, another option is to clone() self, which you should already be able to do since its internals are contained inside an Arc, and then move that clone and use it to call methods in the future continuation chains that you create.


#3

thanks a lot for your reply, I got it to work with cloning. I hope that’s a good way to do it in that context… i better understand as well, have to keep more eye on self.


#4

Yeah, it’s a fairly standard way to do it and relatively cheap when the internals are inside a single Arc.