Skip to content

Instantly share code, notes, and snippets.

@jimmycuadra
Last active March 5, 2017 00:11
Show Gist options
  • Save jimmycuadra/452aa08eb98bebedefd5e12cf3e33bbb to your computer and use it in GitHub Desktop.
Save jimmycuadra/452aa08eb98bebedefd5e12cf3e33bbb to your computer and use it in GitHub Desktop.
Lifetime issue with futures
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
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