0

I have the following code. I'm using mio, and a server to accept connections. After it has accepted a client, it puts a reference of its s into the client, and puts the client into its own HashMap.

use std::sync::Arc;
use std::collections::HashMap;
use mio::EventLoop;
use mio::EventSet;
use mio::Token;
use mio::Handler;
use mio::tcp::TcpListener;
use mio::tcp::TcpStream;

const SERVER_TOKEN: Token = Token(0);

struct FunctionWrapper<'a> {
    f: Arc<Fn() -> () + 'a>,
}

struct Client<'a> {
    socket: TcpStream,
    s: &'a Vec<FunctionWrapper<'a>>,
}

struct Server<'a> {
    s: Vec<FunctionWrapper<'a>>,
    token_counter: usize,
    socket: TcpListener,
    clients: HashMap<Token, Client<'a>>,
}

impl<'a> Handler for Server<'a> {
    type Timeout = ();
    type Message = ();
    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, _: EventSet) {
        match token {
            SERVER_TOKEN => {
                let client_socket = match self.socket.accept() {
                    Ok(Some((sock, addr))) => sock,
                    Ok(None) => unreachable!(),
                    Err(_) => unreachable!(),
                };
                let new_token = Token(self.token_counter);
                self.token_counter += 1;
                let c = Client {
                    socket: client_socket,
                    s: &self.s,
                };
                self.clients.insert(new_token, c);
            },
            token => {
                // ...
            },
        }
    }
}

fn main() {
}

The compiler says:

main.rs:155:24: 155:31 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements [E0495]
main.rs:155                     s: &self.s,
                                   ^~~~~~~
main.rs:144:5: 163:6 help: consider using an explicit lifetime parameter as shown: fn ready(&'a mut self, event_loop: &mut EventLoop<Self>, token: Token,
         _: EventSet)
main.rs:144     fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, _: EventSet) {
main.rs:145         match token {
main.rs:146             SERVER_TOKEN => {
main.rs:147                 let client_socket = match self.socket.accept() {
main.rs:148                     Ok(Some((sock, addr))) => sock,
main.rs:149                     Ok(None) => unreachable!(),

Looks like the compiler is unable to figure out lifetimes between clients and servers. Since the clients are contained in a map in the server, they will never outlast the server. So I think that a reference to a field in server would be fine.

How do I fix this?

Hot.PxL
  • 1,902
  • 1
  • 17
  • 30
  • 1
    You're trying to store `&self.s` inside `self` which is not allowed, despite that it is indirect in this case. – Vladimir Matveev May 24 '16 at 12:49
  • @VladimirMatveev Thanks. It all makes sense now. I should really take reference as raw pointers in C and wrap lifetime-complicated stuff in Arcs. – Hot.PxL May 25 '16 at 02:40

0 Answers0