Borrowed value does not live long enough even


#1

I’m trying to implement an iterator on the Connection struct

pub struct ConnectionIntoIterator<'a, T: 'a>
where
    &'a T: Read + Write,
{
    connection: &'a mut Connection<'a, T>,
}

impl<'a, T> IntoIterator for &'a mut Connection<'a, T>
where
    &'a T: Read + Write,
{
    type Item = Command;
    type IntoIter = ConnectionIntoIterator<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        ConnectionIntoIterator { connection: self }
    }
}

impl<'a, T> Iterator for ConnectionIntoIterator<'a, T>
where
    &'a T: Read + Write,
{
    type Item = Command;

    fn next(&mut self) -> Option<Self::Item> {
        match self.connection.reader.decode() {
            Ok(cmd) => {
                return cmd;
            }
            Err(err) => {
                error!("decoding error: {}", err);
            }
        }
        None
    }
}

but when I try to get the iterator by using into_iter I get an error

pub fn serve(self) -> Result<()> {
        info!("Listen on: {}", self.listener.local_addr().unwrap());
        for stream in self.listener.incoming() {
            match stream {
                Ok(stream) => {
                    info!("accepted connection; addr={}", stream.peer_addr()?);
                    let mut conn = Connection::new(&stream);
                    let cmds = conn.into_iter();
                    info!("closing connection; addr={}", stream.peer_addr()?);
                }
                Err(e) => {
                    error!("accept error = {:?}", e);
                }
            }
        }
        Ok(())
    }
error[E0597]: `conn` does not live long enough
  --> src/server/mod.rs:49:32
   |
49 |                     let cmds = conn.into_iter();
   |                                ^^^^ borrowed value does not live long enough
...
62 |                 }
   |                 - `conn` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.

what I understand from the error is conn is dropped before cmds, which doesn’t make sense at all since the conn is declared before cmds. I’m trying to figure out what’s going for an hour but hit the wall.


#3

&'a mut Connection<'a, T> is a reference to the Connection that borrows it for as long as the borrow that it contains is valid ('a), which must be longer than the scope of the Connection itself. This means that the Connection must still be borrowed when it goes out of scope, but then its destructor can’t run. (drop needs an exclusive &mut self reference, so it can’t run while other references exist.)

Try separating these two lifetimes:

pub struct ConnectionIntoIterator<'a, 'b, T: 'a>
where
    &'a T: Read + Write,
    'a: 'b,
{
    connection: &'b mut Connection<'a, T>,
}

impl<'a, 'b, T> IntoIterator for &'b mut Connection<'a, T>
where
    &'a T: Read + Write,
    'a: 'b
{
    type Item = Command;
    type IntoIter = ConnectionIntoIterator<'a, 'b, T>;

    fn into_iter(self) -> Self::IntoIter {
        ConnectionIntoIterator { connection: self }
    }
}

(Note: This is necessary because &mut T references are invariant on T, so the compiler can’t just find a smaller scope where both lifetimes are valid and coerce them both to that shorter lifetime.)