0

I have a structure which receives some websocket events. Here is a method to receive an event from the structure:

struct Connection;
impl Connection {
    pub fn recv_event(&mut self) -> Result<Event> {
        // ...
    }
}

I have implemented Stream for it:

#[cfg(feature = "stream")]
impl Stream for Connection {
    type Item = Event;
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        match self.recv_event() {
            Ok(event) => Ok(Async::Ready(Some(event))),
            Err(e) => Err(e),
        }
    }
}

It looks that it works okay, but later I decided to return a reference to Self also for being able to modify the object's state in this code:

connection.by_ref().for_each(|c, e| {
    println!("Event: {:?}", e);
    self.handle_events(c, e.clone());
    self.handle_messages(e);
    Ok(())
}).wait();

I need to return a reference to the connection object from the fn poll:

#[cfg(feature = "stream")]
impl Stream for Connection {
    type Item = (&mut Self, Event);
    type Error = ::Error;

    fn poll<'a>(&'a mut self) -> Poll<Option<(&'a mut Self, Event)>, Self::Error> {
        match self.recv_event() {
            Ok(event) => Ok(Async::Ready(Some(self, event))),
            Err(e) => Err(e),
        }
    }
}

Unfortunately, this does not work:

error[E0106]: missing lifetime specifier
   --> src/connection.rs:410:18
    |
410 |     type Item = (&mut Self, Event);
    |                  ^ expected lifetime parameter

Yes, I forgot to add a lifetime here, in the type. Oops. How can I do that? I tried that and some other ways but nothing worked:

#[cfg(feature = "stream")]
impl<'a> Stream for Connection {
    type Item = (&'a mut Self, Event);
    type Error = ::Error;

    fn poll<'a>(&'a mut self) -> Poll<Option<(&'a mut Self, Event)>, Self::Error> {
        match self.recv_event() {
            Ok(event) => Ok(Async::Ready(Some(self, event))),
            Err(e) => Err(e),
        }
    }
}

Which gives the error:

error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
   --> src/connection.rs:409:6
    |
409 | impl<'a> Stream for Connection {
    |      ^^ unconstrained lifetime parameter

Then I tried:

pub struct ConnectionStream<'a>(&'a mut Connection);
#[cfg(feature = "stream")]
impl<'a> Stream for ConnectionStream<'a> {
    type Item = (&'a mut Connection, Event);
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let res = self.0.recv_event();
        match res {
            Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
            Err(e) => Err(e),
        }
    }
}

But still no luck:

error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
   --> src/connection.rs:417:42
    |
417 |             Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
    |                                          ^^^^^^^^^^^^^^^^^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 414:64...
   --> src/connection.rs:414:65
    |
414 |       fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
    |  _________________________________________________________________^ starting here...
415 | |         let res = self.0.recv_event();
416 | |         match res {
417 | |             Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
418 | |             Err(e) => Err(e),
419 | |         }
420 | |     }
    | |_____^ ...ending here
note: ...so that reference does not outlive borrowed content
   --> src/connection.rs:417:48
    |
417 |             Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
    |                                                ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 414:64...
   --> src/connection.rs:414:65
    |
414 |       fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
    |  _________________________________________________________________^ starting here...
415 | |         let res = self.0.recv_event();
416 | |         match res {
417 | |             Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
418 | |             Err(e) => Err(e),
419 | |         }
420 | |     }
    | |_____^ ...ending here
note: ...so that types are compatible (expected futures::Stream, found futures::Stream)
   --> src/connection.rs:414:65
    |
414 |       fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
    |  _________________________________________________________________^ starting here...
415 | |         let res = self.0.recv_event();
416 | |         match res {
417 | |             Ok(event) => Ok(Async::Ready(Some((self.0, event)))),
418 | |             Err(e) => Err(e),
419 | |         }
420 | |     }
    | |_____^ ...ending here

I gave up and I think it is impossible. Am I correct?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
VP.
  • 15,509
  • 17
  • 91
  • 161
  • You may wish to add the compiler's error message obtained from the last code snippet. At that point, the issue looks fairly similar to https://stackoverflow.com/questions/24574741/iterator-returning-items-by-reference-lifetime-issue – E_net4 Jun 08 '17 at 11:27
  • @E_net4 though I have some errors implementing this, I search for the answer on my question in general, not really in solving one particular error, however, this would be interesting too. – VP. Jun 08 '17 at 11:34
  • 1
    @VictorPolevoy: In short, yes what you want to do is impossible at the moment. You want HRBT: Higher-Ranked Bounded Types, ie the ability to declare `type Item<'a>;` and then `poll<'a>(&'a mut self) -> Item<'a>;` in the trait definition. However springing up a new lifetime like you did doesn't work. A possible work-around, depending on the usage, would be to implement `Stream` for `&'a mut Connection` or `&'a Connection`, but this may completely change how to use the type... (who owns it now?). – Matthieu M. Jun 08 '17 at 11:45
  • @MatthieuM. do you mean to do so as in my last attempt (I have updated the question)? – VP. Jun 08 '17 at 13:22

0 Answers0