Hi guys,
I'm facing a problem with lifetimes which I can't seem to find a way around. I have the following code:
struct X;
struct Y<'a> {
x: &'a mut X
}
struct Z<'a> {
x: &'a mut X
}
impl<'a> futures::Stream for Z<'a> {
type Item = Y<'a>;
type Error=();
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
Ok(Async::Ready(Some(Y { x: self.x })))
}
}
There are three structs X, Y and Z. Y and Z carry a mutable reference to X. Z implements Stream
from the futures
crate. In Stream::poll()
, Z is returning an instance of Y to which it's lending its own reference of X (see the expression x: self.x
).
The compiler is complaining that it's unable to figure out a lifetime for the outgoing Y instance:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src\main.rs:39:30
|
39 | Ok(Async::Ready(Some(Y { x: self.x })))
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 38:5...
--> src\main.rs:38:5
|
38 | / fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
39 | | Ok(Async::Ready(Some(Y { x: self.x })))
40 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:39:37
|
39 | Ok(Async::Ready(Some(Y { x: self.x })))
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 35:1...
--> src\main.rs:35:1
|
35 | / impl<'a> futures::Stream for Z<'a> {
36 | | type Item = Y<'a>;
37 | | type Error=();
38 | | fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
39 | | Ok(Async::Ready(Some(Y { x: self.x })))
40 | | }
41 | | }
| |_^
note: ...so that types are compatible (expected futures::Stream, found futures::Stream)
--> src\main.rs:38:65
|
38 | fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
| _________________________________________________________________^
39 | | Ok(Async::Ready(Some(Y { x: self.x })))
40 | | }
| |_____^
error: aborting due to previous error
My question is two fold:
- Why can't the compiler assign lifetime
'a
to theY
instance? It is clear from the code that whatever is the lifetime ofself
, it is gotta be longer than'a
. Why is the inference not happening then? Is it something to do with this being a mutable reference rather than immutable? - How do I annotate to help the compiler here? I tried the following (annotating
self
with'a
):
impl<'a> futures::Stream for Z<'a> {
type Item = Y<'a>;
type Error=();
fn poll(&'a mut self) -> Poll<Option<Self::Item>, Self::Error> {
Ok(Async::Ready(Some(Y { x: self.x })))
}
}
And the following (putting a bound of 'a'
over 'b
, the lifetime of self
):
impl<'a> futures::Stream for Z<'a> {
type Item = Y<'a>;
type Error=();
fn poll<'b: 'a>(&'b mut self) -> Poll<Option<Self::Item>, Self::Error> {
Ok(Async::Ready(Some(Y { x: self.x })))
}
}
But now the compiler complains about a mismatch with the trait declaration with the following errors respectively. This:
error[E0308]: method not compatible with trait
--> src\main.rs:38:5
|
38 | / fn poll(&'a mut self) -> Poll<Option<Self::Item>, Self::Error> {
39 | | Ok(Async::Ready(Some(Y { x: self.x })))
40 | | }
| |_____^ lifetime mismatch
|
= note: expected type `fn(&mut Z<'a>) -> std::result::Result<futures::Async<std::option::Option<Y<'_>>>, ()>`
found type `fn(&'a mut Z<'a>) -> std::result::Result<futures::Async<std::option::Option<Y<'_>>>, ()>`
and this:
error[E0195]: lifetime parameters or bounds on method `poll` do not match the trait declaration
--> src\main.rs:38:5
|
38 | / fn poll<'b: 'a>(&'b mut self) -> Poll<Option<Self::Item>, Self::Error> {
39 | | Ok(Async::Ready(Some(Y { x: self.x })))
40 | | }
| |_____^ lifetimes do not match trait
It seems really hard to annotate this without deviating from the trait declaration. Any help will be much appreciated