Repository: rust-lang-nursery/futures-rs (rust)

Issue:
Consider removing the `Self::Error: From<Fut::Error>` bound on `fold`
This bound means that the error type of the inner closure cannot be inferred when it is always `Ok`.

My fold return value must now be:

```rust
Ok::<_, tower_grpc::Error>((summary, Some(point)))
```

All combinators should probably be inspected for such issues.

Pull request description:
Remove error conversions
Fix #668

Patch:
diff --git a/src/future/join_all.rs b/src/future/join_all.rs
index e1cddd42..398a7a47 100644
--- a/src/future/join_all.rs
+++ b/src/future/join_all.rs
@@ -19,16 +19,18 @@ enum ElemState<T> where T: Future {
 ///
 /// This future is created with the `join_all` method.
 #[must_use = "futures do nothing unless polled"]
-pub struct JoinAll<Item>
-    where Item: IntoFuture,
+pub struct JoinAll<I>
+    where I: IntoIterator,
+          I::Item: IntoFuture,
 {
-    elems: Vec<ElemState<<Item as IntoFuture>::Future>>,
+    elems: Vec<ElemState<<I::Item as IntoFuture>::Future>>,
 }
 
 impl<I> fmt::Debug for JoinAll<I>
-    where I: IntoFuture,
-          <I as IntoFuture>::Future: fmt::Debug,
-          <I as IntoFuture>::Item: fmt::Debug,
+    where I: IntoIterator,
+          I::Item: IntoFuture,
+          <<I as IntoIterator>::Item as IntoFuture>::Future: fmt::Debug,
+          <<I as IntoIterator>::Item as IntoFuture>::Item: fmt::Debug,
 {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt.debug_struct("JoinAll")
@@ -71,7 +73,7 @@ impl<I> fmt::Debug for JoinAll<I>
 ///     x
 /// });
 /// ```
-pub fn join_all<I>(i: I) -> JoinAll<I::Item>
+pub fn join_all<I>(i: I) -> JoinAll<I>
     where I: IntoIterator,
           I::Item: IntoFuture,
 {
@@ -81,11 +83,12 @@ pub fn join_all<I>(i: I) -> JoinAll<I::Item>
     JoinAll { elems: elems }
 }
 
-impl<Item> Future for JoinAll<Item>
-    where Item: IntoFuture,
+impl<I> Future for JoinAll<I>
+    where I: IntoIterator,
+          I::Item: IntoFuture,
 {
-    type Item = Vec<<Item as IntoFuture>::Item>;
-    type Error = <Item as IntoFuture>::Error;
+    type Item = Vec<<I::Item as IntoFuture>::Item>;
+    type Error = <I::Item as IntoFuture>::Error;
 
 
     fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
diff --git a/src/future/mod.rs b/src/future/mod.rs
index bcab1518..47c3d761 100644
--- a/src/future/mod.rs
+++ b/src/future/mod.rs
@@ -748,9 +748,7 @@ pub trait Future {
     /// assert_eq!(future.wait(), Err(1));
     /// ```
     fn flatten(self) -> Flatten<Self>
-        where Self::Item: IntoFuture,
-        <<Self as Future>::Item as IntoFuture>::Error:
-            From<<Self as Future>::Error>,
+        where Self::Item: IntoFuture<Error = <Self as Future>::Error>,
         Self: Sized
     {
         let f = flatten::new(self);
diff --git a/src/stream/flatten.rs b/src/stream/flatten.rs
index 4baf9045..74f4e0c6 100644
--- a/src/stream/flatten.rs
+++ b/src/stream/flatten.rs
@@ -16,8 +16,7 @@ pub struct Flatten<S>
 
 pub fn new<S>(s: S) -> Flatten<S>
     where S: Stream,
-          S::Item: Stream,
-          <S::Item as Stream>::Error: From<S::Error>,
+          S::Item: Stream<Error = S::Error>,
 {
     Flatten {
         stream: s,
diff --git a/src/stream/fold.rs b/src/stream/fold.rs
index 7fa24b44..15a0a940 100644
--- a/src/stream/fold.rs
+++ b/src/stream/fold.rs
@@ -29,8 +29,7 @@ enum State<T, F> where F: Future {
 pub fn new<S, F, Fut, T>(s: S, f: F, t: T) -> Fold<S, F, Fut, T>
     where S: Stream,
           F: FnMut(T, S::Item) -> Fut,
-          Fut: IntoFuture<Item = T>,
-          S::Error: From<Fut::Error>,
+          Fut: IntoFuture<Item = T, Error = S::Error>,
 {
     Fold {
         stream: s,
@@ -42,8 +41,7 @@ pub fn new<S, F, Fut, T>(s: S, f: F, t: T) -> Fold<S, F, Fut, T>
 impl<S, F, Fut, T> Future for Fold<S, F, Fut, T>
     where S: Stream,
           F: FnMut(T, S::Item) -> Fut,
-          Fut: IntoFuture<Item = T>,
-          S::Error: From<Fut::Error>,
+          Fut: IntoFuture<Item = T, Error = S::Error>,
 {
     type Item = T;
     type Error = S::Error;
diff --git a/src/stream/mod.rs b/src/stream/mod.rs
index 3a53a12f..e82ef0a5 100644
--- a/src/stream/mod.rs
+++ b/src/stream/mod.rs
@@ -575,8 +575,7 @@ pub trait Stream {
     /// ```
     fn fold<F, T, Fut>(self, init: T, f: F) -> Fold<Self, F, Fut, T>
         where F: FnMut(T, Self::Item) -> Fut,
-              Fut: IntoFuture<Item = T>,
-              Self::Error: From<Fut::Error>,
+              Fut: IntoFuture<Item = T, Error = Self::Error>,
               Self: Sized
     {
         fold::new(self, f, init)
@@ -616,8 +615,7 @@ pub trait Stream {
     /// assert_eq!(result.wait(), Ok(vec![1, 2, 3, 4]));
     /// ```
     fn flatten(self) -> Flatten<Self>
-        where Self::Item: Stream,
-              <Self::Item as Stream>::Error: From<Self::Error>,
+        where Self::Item: Stream<Error = Self::Error>,
               Self: Sized
     {
         flatten::new(self)


Test patch:
diff --git a/tests/all.rs b/tests/all.rs
index 7c093b2b..ef3493bd 100644
--- a/tests/all.rs
+++ b/tests/all.rs
@@ -100,8 +100,7 @@ fn flatten() {
     assert_done(|| ok(ok(1)).flatten(), r_ok(1));
     assert_done(|| ok(err(1)).flatten(), r_err(1));
     assert_done(|| err(1u32).map(ok).flatten(), r_err(1));
-    assert_done(|| future::ok::<_, u8>(future::ok::<_, u32>(1))
-                           .flatten(), r_ok(1));
+    assert_done(|| future::ok(future::ok(1)).flatten(), r_ok(1));
     assert_empty(|| ok(empty::<i32, u32>()).flatten());
     assert_empty(|| empty::<i32, u32>().map(ok).flatten());
 }
@@ -251,18 +250,6 @@ fn collect_collects() {
     // TODO: needs more tests
 }
 
-#[test]
-fn join_all_iter_lifetime() {
-    // In futures-rs version 0.1, this function would fail to typecheck due to an overly
-    // conservative type parameterization of `JoinAll`.
-    fn sizes<'a>(bufs: Vec<&'a [u8]>) -> Box<Future<Item=Vec<usize>, Error=()> + 'static> {
-        let iter = bufs.into_iter().map(|b| future::ok::<usize, ()>(b.len()));
-        Box::new(join_all(iter))
-    }
-
-    assert_done(|| sizes(vec![&[1,2,3], &[], &[0]]), Ok(vec![3, 0, 1]));
-}
-
 #[test]
 fn select2() {
     fn d<T, U, E>(r: Result<(T, U), (E, U)>) -> Result<T, E> {
diff --git a/tests/bilock.rs b/tests/bilock.rs
index 78d87363..6e0c3442 100644
--- a/tests/bilock.rs
+++ b/tests/bilock.rs
@@ -59,7 +59,7 @@ fn concurrent() {
         a: Some(a),
         remaining: N,
     };
-    let b = stream::iter_ok::<_, ()>((0..N)).fold(b, |b, _n| {
+    let b = stream::iter_ok(0..N).fold(b, |b, _n| {
         b.lock().map(|mut b| {
             *b += 1;
             b.unlock()