Last active
March 5, 2017 00:11
-
-
Save jimmycuadra/452aa08eb98bebedefd5e12cf3e33bbb to your computer and use it in GitHub Desktop.
Lifetime issue with futures
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements | |
--> src/main.rs:39:37 | |
| | |
39 | for item in self.collection.iter() { | |
| ^^^^ | |
| | |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 36:90... | |
--> src/main.rs:36:91 | |
| | |
36 | fn dispatch(&self, input: &'static str) -> Box<Stream<Item = Success, Error = Error>> { | |
| ^ | |
note: ...so that reference does not outlive borrowed content | |
--> src/main.rs:39:21 | |
| | |
39 | for item in self.collection.iter() { | |
| ^^^^^^^^^^^^^^^ | |
= note: but, the lifetime must be valid for the static lifetime... | |
note: ...so that the declared lifetime parameter bounds are satisfied | |
--> src/main.rs:49:9 | |
| | |
49 | Box::new(rx.then(|result| { | |
| _________^ starting here... | |
50 | | result.expect("receivers cannot produce errors") | |
51 | | })) as Box<Stream<Item = Success, Error = Error>> | |
| |_________________________________________________________^ ...ending here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate futures; | |
use futures::future::ok; | |
use futures::stream::iter; | |
use futures::sync::mpsc::channel; | |
use futures::{Future, Sink, Stream}; | |
struct App<T> where T: 'static { | |
collection: Vec<T>, | |
} | |
// Unit types would work as the associated types, too. These two types are just to help distinguish | |
// the associated types from the unit returned by `Stream::for_each` in compiler errors. | |
struct Success; | |
struct Error; | |
impl<T> App<T> where T: 'static { | |
pub fn run(self) -> Box<Future<Item = (), Error = Error>> { | |
// In the real program, these input messages come from an external source, like a socket. | |
let inputs = vec!["hello world", "rust is cool", "async is hard"]; | |
// Dispatch each input. I don't know if there's a simpler way to create a stream out of | |
// these inputs than using `futures::stream::iter`. | |
let input_stream = iter(inputs.into_iter().map(|input| Ok(input))); | |
let future = input_stream.for_each(move |input| { | |
self.dispatch(input).for_each(|_| { | |
Ok(()) | |
}) | |
}); | |
Box::new(future) | |
} | |
// Calls each registered callback with the input and sends the result of the callback into the | |
// sink. | |
fn dispatch(&self, input: &'static str) -> Box<Stream<Item = Success, Error = Error>> { | |
let (tx, rx) = channel::<Box<Future<Item = Success, Error = Error>>>(1); | |
for item in self.collection.iter() { | |
// Do some asynchronous work with `item` and produce a future for the result. | |
// In the real code, it's actully doing `item(input)`, but I think all that matters | |
// here for the example is that a future is being created. | |
let future = Box::new(ok(item).map(|_| Success)); | |
// Send the future into the sink. | |
tx.clone().send(future); | |
} | |
Box::new(rx.then(|result| { | |
result.expect("receivers cannot produce errors") | |
})) as Box<Stream<Item = Success, Error = Error>> | |
} | |
} | |
fn main() { | |
let app = App { | |
// In the real code, this is a collection of registered callbacks that will process | |
// external input. | |
collection: vec![1, 2, 3], | |
}; | |
// In this particular case, I'm just `wait()`ing to keep the example simple. | |
app.run().wait(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment