diff --git a/Cargo.toml b/Cargo.toml
index 474371f..f041550 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,6 +19,7 @@ maintenance = { status = "experimental" }
 
 [dependencies]
 pin-utils = "=0.1.0-alpha.4"
+async-trait = "0.1.3"
 
 [dependencies.futures]
 version = "=0.3.0-alpha.18"
diff --git a/benches/future.rs b/benches/future.rs
index af82638..219ed35 100644
--- a/benches/future.rs
+++ b/benches/future.rs
@@ -63,7 +63,7 @@ fn bench_map(c: &mut Criterion) {
             b.iter(async move || {
                 use futures_async_combinators::future::*;
                 let fut = ready(40);
-                let fut = map(fut, |x| x + 2);
+                let fut = fut.map(|x| x + 2);
                 black_box(fut).await
             })
         });
diff --git a/examples/future.rs b/examples/future.rs
index bdffa09..69bb8f1 100644
--- a/examples/future.rs
+++ b/examples/future.rs
@@ -4,8 +4,8 @@ use futures_async_combinators::future::*;
 fn main() {
     executor::block_on(async {
         let future = ready(Ok::<i32, i32>(1));
-        let future = and_then(future, |x| ready(Ok::<i32, i32>(x + 3)));
-        let future = inspect(future, |x| {
+        let future = future.and_then(|x| ready(Ok::<i32, i32>(x + 3)));
+        let future = future.inspect(|x| {
             dbg!(x);
         });
         assert_eq!(future.await, Ok(4));
diff --git a/src/future.rs b/src/future.rs
index e5b53b8..d9f008d 100644
--- a/src/future.rs
+++ b/src/future.rs
@@ -1,6 +1,7 @@
-use futures::future::Future;
+use core::future::Future;
 use futures::stream::Stream;
 
+use async_trait::async_trait;
 use core::task::{Context, Poll};
 
 /// Create a future that is immediately ready with a value.
@@ -19,384 +20,406 @@ pub async fn ready<T>(value: T) -> T {
     value
 }
 
-/// Map this future's output to a different type, returning a new future of
-/// the resulting type.
-///
-/// This function is similar to the `Option::map` or `Iterator::map` where
-/// it will change the type of the underlying future. This is useful to
-/// chain along a computation once a future has been resolved.
-///
-/// Note that this function consumes the receiving future and returns a
-/// wrapped version of it, similar to the existing `map` methods in the
-/// standard library.
-///
-/// # Examples
-///
-/// ```
-/// # futures::executor::block_on(async {
-/// use futures_async_combinators::future::{ready, map};
-///
-/// let future = ready(1);
-/// let new_future = map(future, |x| x + 3);
-/// assert_eq!(new_future.await, 4);
-/// # });
-/// ```
-pub async fn map<Fut, U, F>(future: Fut, f: F) -> U
-where
-    F: FnOnce(Fut::Output) -> U,
-    Fut: Future,
-{
-    f(future.await)
-}
+impl<T: ?Sized> FutureExt for T where T: Future {}
+
+#[async_trait]
+pub trait FutureExt: Future {
+    /// Map this future's output to a different type, returning a new future of
+    /// the resulting type.
+    ///
+    /// This function is similar to the `Option::map` or `Iterator::map` where
+    /// it will change the type of the underlying future. This is useful to
+    /// chain along a computation once a future has been resolved.
+    ///
+    /// Note that this function consumes the receiving future and returns a
+    /// wrapped version of it, similar to the existing `map` methods in the
+    /// standard library.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # futures::executor::block_on(async {
+    /// use futures_async_combinators::future::{ready, FutureExt};
+    ///
+    /// let future = ready(1);
+    /// let new_future = future.map(|x| x + 3);
+    /// assert_eq!(new_future.await, 4);
+    /// # });
+    /// ```
+    async fn map<U, F>(self, f: F) -> U
+    where
+        F: FnOnce(Self::Output) -> U + Send,
+        Self: Sized,
+    {
+        f(self.await)
+    }
 
-/// Chain on a computation for when a future finished, passing the result of
-/// the future to the provided closure `f`.
-///
-/// The returned value of the closure must implement the `Future` trait
-/// and can represent some more work to be done before the composed future
-/// is finished.
-///
-/// The closure `f` is only run *after* successful completion of the `self`
-/// future.
-///
-/// Note that this function consumes the receiving future and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// # futures::executor::block_on(async {
-/// use futures_async_combinators::future::{ready, then};
-///
-/// let future_of_1 = ready(1);
-/// let future_of_4 = then(future_of_1, |x| ready(x + 3));
-/// assert_eq!(future_of_4.await, 4);
-/// # });
-/// ```
-pub async fn then<FutA, FutB, F>(future: FutA, f: F) -> FutB::Output
-where
-    F: FnOnce(FutA::Output) -> FutB,
-    FutA: Future,
-    FutB: Future,
-{
-    let new_future = f(future.await);
-    new_future.await
-}
+    /// Chain on a computation for when a future finished, passing the result of
+    /// the future to the provided closure `f`.
+    ///
+    /// The returned value of the closure must implement the `Future` trait
+    /// and can represent some more work to be done before the composed future
+    /// is finished.
+    ///
+    /// The closure `f` is only run *after* successful completion of the `self`
+    /// future.
+    ///
+    /// Note that this function consumes the receiving future and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # futures::executor::block_on(async {
+    /// use futures_async_combinators::future::{ready, FutureExt};
+    ///
+    /// let future_of_1 = ready(1);
+    /// let future_of_4 = future_of_1.then(|x| ready(x + 3));
+    /// assert_eq!(future_of_4.await, 4);
+    /// # });
+    /// ```
+    async fn then<Fut, F>(self, f: F) -> Fut::Output
+    where
+        F: FnOnce(Self::Output) -> Fut + Send,
+        Fut: Future + Send,
+        Self: Sized,
+    {
+        let new_future = f(self.await);
+        new_future.await
+    }
 
-/// Executes another future after this one resolves successfully. The
-/// success value is passed to a closure to create this subsequent future.
-///
-/// The provided closure `f` will only be called if this future is resolved
-/// to an [`Ok`]. If this future resolves to an [`Err`], panics, or is
-/// dropped, then the provided closure will never be invoked. The
-/// `Error` type of this future and the future
-/// returned by `f` have to match.
-///
-/// Note that this method consumes the future it is called on and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// use futures_async_combinators::future::{ready, and_then};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Ok::<i32, i32>(1));
-/// let future = and_then(future, |x| ready(Ok::<i32, i32>(x + 3)));
-/// assert_eq!(future.await, Ok(4));
-/// # });
-/// ```
-///
-/// Calling [`and_then`] on an errored future has no
-/// effect:
-///
-/// ```
-/// use futures_async_combinators::future::{ready, and_then};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Err::<i32, i32>(1));
-/// let future = and_then(future, |x| ready(Err::<i32, i32>(x + 3)));
-/// assert_eq!(future.await, Err(1));
-/// # });
-/// ```
-pub async fn and_then<FutA, FutB, F, T, U, E>(future: FutA, f: F) -> Result<U, E>
-where
-    F: FnOnce(T) -> FutB,
-    FutA: Future<Output = Result<T, E>>,
-    FutB: Future<Output = Result<U, E>>,
-{
-    match future.await {
-        Ok(ok) => {
-            let new_future = f(ok);
-            new_future.await
-        }
-        Err(err) => Err(err),
+    /// Flatten the execution of this future when the successful result of this
+    /// future is itself another future.
+    ///
+    /// This can be useful when combining futures together to flatten the
+    /// computation out the final result. This method can only be called
+    /// when the successful result of this future itself implements the
+    /// `IntoFuture` trait and the error can be created from this future's error
+    /// type.
+    ///
+    /// This method is roughly equivalent to `future.and_then(|x| x)`.
+    ///
+    /// Note that this function consumes the receiving future and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # futures::executor::block_on(async {
+    /// use futures_async_combinators::future::{ready, FutureExt};
+    ///
+    /// let nested_future = ready(ready(1));
+    /// let future = nested_future.flatten();
+    /// assert_eq!(future.await, 1);
+    /// # });
+    /// ```
+    async fn flatten(self) -> <Self::Output as Future>::Output
+    where
+        Self::Output: Future + Send,
+        Self: Sized,
+    {
+        let nested_future = self.await;
+        nested_future.await
     }
-}
 
-/// Executes another future if this one resolves to an error. The
-/// error value is passed to a closure to create this subsequent future.
-///
-/// The provided closure `f` will only be called if this future is resolved
-/// to an [`Err`]. If this future resolves to an [`Ok`], panics, or is
-/// dropped, then the provided closure will never be invoked. The
-/// `Ok` type of this future and the future returned by `f`
-/// have to match.
-///
-/// Note that this method consumes the future it is called on and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// use futures_async_combinators::future::{ready, or_else};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Err::<i32, i32>(1));
-/// let future = or_else(future, |x| ready(Err::<i32, i32>(x + 3)));
-/// assert_eq!(future.await, Err(4));
-/// # });
-/// ```
-///
-/// Calling [`or_else`] on a successful future has
-/// no effect:
-///
-/// ```
-/// use futures_async_combinators::future::{ready, or_else};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Ok::<i32, i32>(1));
-/// let future = or_else(future, |x| ready(Ok::<i32, i32>(x + 3)));
-/// assert_eq!(future.await, Ok(1));
-/// # });
-/// ```
-pub async fn or_else<FutA, FutB, F, T, E, U>(future: FutA, f: F) -> Result<T, U>
-where
-    F: FnOnce(E) -> FutB,
-    FutA: Future<Output = Result<T, E>>,
-    FutB: Future<Output = Result<T, U>>,
-{
-    match future.await {
-        Ok(ok) => Ok(ok),
-        Err(err) => {
-            let new_future = f(err);
-            new_future.await
-        }
+    /// Do something with the output of a future before passing it on.
+    ///
+    /// When using futures, you'll often chain several of them together.  While
+    /// working on such code, you might want to check out what's happening at
+    /// various parts in the pipeline, without consuming the intermediate
+    /// value. To do that, insert a call to `inspect`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # futures::executor::block_on(async {
+    /// use futures_async_combinators::future::{ready, FutureExt};
+    ///
+    /// let future = ready(1);
+    /// let new_future = future.inspect(|&x| println!("about to resolve: {}", x));
+    /// assert_eq!(new_future.await, 1);
+    /// # });
+    /// ```
+    async fn inspect<F>(self, f: F) -> Self::Output
+    where
+        F: FnOnce(&Self::Output) + Send,
+        Self: Sized,
+    {
+        let future_result = self.await;
+        f(&future_result);
+        future_result
     }
 }
 
-/// Maps this future's success value to a different value.
-///
-/// This method can be used to change the `Ok` type of the
-/// future into a different type. It is similar to the [`Result::map`]
-/// method. You can use this method to chain along a computation once the
-/// future has been resolved.
-///
-/// The provided closure `f` will only be called if this future is resolved
-/// to an `Ok`. If it resolves to an `Err`, panics, or is dropped, then
-/// the provided closure will never be invoked.
-///
-/// Note that this method consumes the future it is called on and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// use futures_async_combinators::future::{ready, map_ok};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Ok::<i32, i32>(1));
-/// let future = map_ok(future, |x| x + 3);
-/// assert_eq!(future.await, Ok(4));
-/// # });
-/// ```
-///
-/// Calling [`map_ok`] on an errored future has no
-/// effect:
-///
-/// ```
-/// use futures_async_combinators::future::{ready, map_ok};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Err::<i32, i32>(1));
-/// let future = map_ok(future, |x| x + 3);
-/// assert_eq!(future.await, Err(1));
-/// # });
-/// ```
-pub async fn map_ok<Fut, F, T, U, E>(future: Fut, f: F) -> Result<U, E>
-where
-    F: FnOnce(T) -> U,
-    Fut: Future<Output = Result<T, E>>,
-{
-    future.await.map(f)
-}
+impl<T, E, Fut: ?Sized> TryFutureExt<T, E> for Fut where Fut: Future<Output = Result<T, E>> {}
+
+#[async_trait]
+pub trait TryFutureExt<T, E>: Future<Output = Result<T, E>> {
+    /// Executes another future after this one resolves successfully. The
+    /// success value is passed to a closure to create this subsequent future.
+    ///
+    /// The provided closure `f` will only be called if this future is resolved
+    /// to an [`Ok`]. If this future resolves to an [`Err`], panics, or is
+    /// dropped, then the provided closure will never be invoked. The
+    /// `Error` type of this future and the future
+    /// returned by `f` have to match.
+    ///
+    /// Note that this method consumes the future it is called on and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Ok::<i32, i32>(1));
+    /// let future = future.and_then(|x| ready(Ok::<i32, i32>(x + 3)));
+    /// assert_eq!(future.await, Ok(4));
+    /// # });
+    /// ```
+    ///
+    /// Calling [`TryFutureExt::and_then`] on an errored future has no
+    /// effect:
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Err::<i32, i32>(1));
+    /// let future = future.and_then(|x| ready(Err::<i32, i32>(x + 3)));
+    /// assert_eq!(future.await, Err(1));
+    /// # });
+    /// ```
+    async fn and_then<U, F, FutB>(self, f: F) -> Result<U, E>
+    where
+        F: FnOnce(T) -> FutB + Send,
+        FutB: Future<Output = Result<U, E>> + Send,
+        Self: Sized,
+        T: Send + 'async_trait,
+        E: Send + 'async_trait,
+    {
+        match self.await {
+            Ok(ok) => {
+                let new_future = f(ok);
+                new_future.await
+            }
+            Err(err) => Err(err),
+        }
+    }
 
-/// Maps this future's error value to a different value.
-///
-/// This method can be used to change the `Error` type
-/// of the future into a different type. It is similar to the
-/// [`Result::map_err`] method. You can use this method for example to
-/// ensure that futures have the same `Error` type when
-/// using `select!` or `join!`.
-///
-/// The provided closure `f` will only be called if this future is resolved
-/// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then
-/// the provided closure will never be invoked.
-///
-/// Note that this method consumes the future it is called on and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// use futures_async_combinators::future::{ready, map_err};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Err::<i32, i32>(1));
-/// let future = map_err(future, |x| x + 3);
-/// assert_eq!(future.await, Err(4));
-/// # });
-/// ```
-///
-/// Calling [`map_err`] on a successful future has
-/// no effect:
-///
-/// ```
-/// use futures_async_combinators::future::{ready, map_err};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Ok::<i32, i32>(1));
-/// let future = map_err(future, |x| x + 3);
-/// assert_eq!(future.await, Ok(1));
-/// # });
-/// ```
-pub async fn map_err<Fut, F, T, E, U>(future: Fut, f: F) -> Result<T, U>
-where
-    F: FnOnce(E) -> U,
-    Fut: Future<Output = Result<T, E>>,
-{
-    future.await.map_err(f)
-}
+    /// Executes another future if this one resolves to an error. The
+    /// error value is passed to a closure to create this subsequent future.
+    ///
+    /// The provided closure `f` will only be called if this future is resolved
+    /// to an [`Err`]. If this future resolves to an [`Ok`], panics, or is
+    /// dropped, then the provided closure will never be invoked. The
+    /// `Ok` type of this future and the future returned by `f`
+    /// have to match.
+    ///
+    /// Note that this method consumes the future it is called on and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Err::<i32, i32>(1));
+    /// let future = future.or_else(|x| ready(Err::<i32, i32>(x + 3)));
+    /// assert_eq!(future.await, Err(4));
+    /// # });
+    /// ```
+    ///
+    /// Calling [`TryFutureExt::or_else`] on a successful future has
+    /// no effect:
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Ok::<i32, i32>(1));
+    /// let future = future.or_else(|x| ready(Ok::<i32, i32>(x + 3)));
+    /// assert_eq!(future.await, Ok(1));
+    /// # });
+    /// ```
+    async fn or_else<U, F, FutB>(self, f: F) -> Result<T, U>
+    where
+        F: FnOnce(E) -> FutB + Send,
+        FutB: Future<Output = Result<T, U>> + Send,
+        Self: Sized,
+        T: Send + 'async_trait,
+        E: Send + 'async_trait,
+    {
+        match self.await {
+            Ok(ok) => Ok(ok),
+            Err(err) => {
+                let new_future = f(err);
+                new_future.await
+            }
+        }
+    }
 
-/// Flatten the execution of this future when the successful result of this
-/// future is itself another future.
-///
-/// This can be useful when combining futures together to flatten the
-/// computation out the final result. This method can only be called
-/// when the successful result of this future itself implements the
-/// `IntoFuture` trait and the error can be created from this future's error
-/// type.
-///
-/// This method is roughly equivalent to `and_then(self, |x| x)`.
-///
-/// Note that this function consumes the receiving future and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// # futures::executor::block_on(async {
-/// use futures_async_combinators::future::{ready, flatten};
-///
-/// let nested_future = ready(ready(1));
-/// let future = flatten(nested_future);
-/// assert_eq!(future.await, 1);
-/// # });
-/// ```
-pub async fn flatten<FutA, FutB>(future: FutA) -> FutB::Output
-where
-    FutA: Future<Output = FutB>,
-    FutB: Future,
-{
-    let nested_future = future.await;
-    nested_future.await
-}
+    /// Maps this future's success value to a different value.
+    ///
+    /// This method can be used to change the `Ok` type of the
+    /// future into a different type. It is similar to the [`Result::map`]
+    /// method. You can use this method to chain along a computation once the
+    /// future has been resolved.
+    ///
+    /// The provided closure `f` will only be called if this future is resolved
+    /// to an `Ok`. If it resolves to an `Err`, panics, or is dropped, then
+    /// the provided closure will never be invoked.
+    ///
+    /// Note that this method consumes the future it is called on and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Ok::<i32, i32>(1));
+    /// let future = future.map_ok(|x| x + 3);
+    /// assert_eq!(future.await, Ok(4));
+    /// # });
+    /// ```
+    ///
+    /// Calling [`TryFutureExt::map_ok`] on an errored future has no
+    /// effect:
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Err::<i32, i32>(1));
+    /// let future = future.map_ok(|x| x + 3);
+    /// assert_eq!(future.await, Err(1));
+    /// # });
+    /// ```
+    async fn map_ok<U, F>(self, f: F) -> Result<U, E>
+    where
+        F: FnOnce(T) -> U + Send,
+        Self: Sized,
+        T: Send + 'async_trait,
+        E: Send + 'async_trait,
+    {
+        self.await.map(f)
+    }
 
-/// Do something with the output of a future before passing it on.
-///
-/// When using futures, you'll often chain several of them together.  While
-/// working on such code, you might want to check out what's happening at
-/// various parts in the pipeline, without consuming the intermediate
-/// value. To do that, insert a call to `inspect`.
-///
-/// # Examples
-///
-/// ```
-/// # futures::executor::block_on(async {
-/// use futures_async_combinators::future::{ready, inspect};
-///
-/// let future = ready(1);
-/// let new_future = inspect(future, |&x| println!("about to resolve: {}", x));
-/// assert_eq!(new_future.await, 1);
-/// # });
-/// ```
-pub async fn inspect<Fut, F>(future: Fut, f: F) -> Fut::Output
-where
-    Fut: Future,
-    F: FnOnce(&Fut::Output),
-{
-    let future_result = future.await;
-    f(&future_result);
-    future_result
-}
+    /// Maps this future's error value to a different value.
+    ///
+    /// This method can be used to change the `Error` type
+    /// of the future into a different type. It is similar to the
+    /// [`Result::map_err`] method. You can use this method for example to
+    /// ensure that futures have the same `Error` type when
+    /// using `select!` or `join!`.
+    ///
+    /// The provided closure `f` will only be called if this future is resolved
+    /// to an [`Err`]. If it resolves to an [`Ok`], panics, or is dropped, then
+    /// the provided closure will never be invoked.
+    ///
+    /// Note that this method consumes the future it is called on and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Err::<i32, i32>(1));
+    /// let future = future.map_err(|x| x + 3);
+    /// assert_eq!(future.await, Err(4));
+    /// # });
+    /// ```
+    ///
+    /// Calling [`TryFutureExt::map_err`] on a successful future has
+    /// no effect:
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Ok::<i32, i32>(1));
+    /// let future = future.map_err(|x| x + 3);
+    /// assert_eq!(future.await, Ok(1));
+    /// # });
+    /// ```
+    async fn map_err<U, F>(self, f: F) -> Result<T, U>
+    where
+        F: FnOnce(E) -> U + Send,
+        Self: Sized,
+        T: Send + 'async_trait,
+        E: Send + 'async_trait,
+    {
+        self.await.map_err(f)
+    }
 
-/// Maps this future's `Error` to a new error type
-/// using the [`Into`](std::convert::Into) trait.
-///
-/// This method does for futures what the `?`-operator does for
-/// [`Result`]: It lets the compiler infer the type of the resulting
-/// error. Just as [`map_err`](map_err), this is useful for
-/// example to ensure that futures have the same `Error`
-/// type when using `select!` or `join!`.
-///
-/// Note that this method consumes the future it is called on and returns a
-/// wrapped version of it.
-///
-/// # Examples
-///
-/// ```
-/// use futures_async_combinators::future::{ready, err_into};
-///
-/// # futures::executor::block_on(async {
-/// let future_err_u8 = ready(Err::<(), u8>(1));
-/// let future_err_i32 = err_into::<i32, _, _, _>(future_err_u8);
-/// # });
-/// ```
-pub async fn err_into<U, Fut, T, E>(future: Fut) -> Result<T, U>
-where
-    Fut: Future<Output = Result<T, E>>,
-    E: Into<U>,
-{
-    future.await.map_err(Into::into)
-}
+    /// Maps this future's `Error` to a new error type
+    /// using the [`Into`](std::convert::Into) trait.
+    ///
+    /// This method does for futures what the `?`-operator does for
+    /// [`Result`]: It lets the compiler infer the type of the resulting
+    /// error. Just as [`TryFutureExt::map_err`], this is useful for
+    /// example to ensure that futures have the same `Error`
+    /// type when using `select!` or `join!`.
+    ///
+    /// Note that this method consumes the future it is called on and returns a
+    /// wrapped version of it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future_err_u8 = ready(Err::<(), u8>(1));
+    /// let future_err_i32 = future_err_u8.err_into::<i32>();
+    /// # });
+    /// ```
+    async fn err_into<U>(self) -> Result<T, U>
+    where
+        E: Into<U>,
+        Self: Sized,
+        T: Send + 'async_trait,
+        E: Send + 'async_trait,
+    {
+        self.await.map_err(Into::into)
+    }
 
-/// Unwraps this future's ouput, producing a future with this future's
-/// `Ok` type as its [`Output`](std::future::Future::Output) type.
-///
-/// If this future is resolved successfully, the returned future will
-/// contain the original future's success value as output. Otherwise, the
-/// closure `f` is called with the error value to produce an alternate
-/// success value.
-///
-/// This method is similar to the [`Result::unwrap_or_else`] method.
-///
-/// # Examples
-///
-/// ```
-/// use futures_async_combinators::future::{ready, unwrap_or_else};
-///
-/// # futures::executor::block_on(async {
-/// let future = ready(Err::<(), &str>("Boom!"));
-/// let future = unwrap_or_else(future, |_| ());
-/// assert_eq!(future.await, ());
-/// # });
-/// ```
-pub async fn unwrap_or_else<Fut, T, E, F>(future: Fut, f: F) -> T
-where
-    Fut: Future<Output = Result<T, E>>,
-    F: FnOnce(E) -> T,
-{
-    future.await.unwrap_or_else(f)
+    /// Unwraps this future's ouput, producing a future with this future's
+    /// `Ok` type as its [`Output`](std::future::Future::Output) type.
+    ///
+    /// If this future is resolved successfully, the returned future will
+    /// contain the original future's success value as output. Otherwise, the
+    /// closure `f` is called with the error value to produce an alternate
+    /// success value.
+    ///
+    /// This method is similar to the [`Result::unwrap_or_else`] method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use futures_async_combinators::future::{ready, TryFutureExt};
+    ///
+    /// # futures::executor::block_on(async {
+    /// let future = ready(Err::<(), &str>("Boom!"));
+    /// let future = future.unwrap_or_else(|_| ());
+    /// assert_eq!(future.await, ());
+    /// # });
+    /// ```
+    async fn unwrap_or_else<F>(self, f: F) -> T
+    where
+        F: FnOnce(E) -> T + Send,
+        Self: Sized,
+        T: Send + 'async_trait,
+        E: Send + 'async_trait,
+    {
+        self.await.unwrap_or_else(f)
+    }
 }
 
 /// Flatten the execution of this future when the successful result of this
@@ -533,7 +556,7 @@ mod tests {
     fn test_map() {
         executor::block_on(async {
             let future = ready(1);
-            let new_future = map(future, |x| x + 3);
+            let new_future = future.map(|x| x + 3);
             assert_eq!(new_future.await, 4);
         });
     }
@@ -542,7 +565,7 @@ mod tests {
     fn test_then() {
         executor::block_on(async {
             let future = ready(1);
-            let new_future = then(future, |x| ready(x + 3));
+            let new_future = future.then(|x| ready(x + 3));
             assert_eq!(new_future.await, 4);
         });
     }
@@ -551,7 +574,7 @@ mod tests {
     fn test_and_then_ok() {
         executor::block_on(async {
             let future = ready(Ok::<i32, i32>(1));
-            let new_future = and_then(future, |x| ready(Ok::<i32, i32>(x + 3)));
+            let new_future = future.and_then(|x| ready(Ok::<i32, i32>(x + 3)));
             assert_eq!(new_future.await, Ok(4));
         });
     }
@@ -560,7 +583,7 @@ mod tests {
     fn test_and_then_err() {
         executor::block_on(async {
             let future = ready(Err::<i32, i32>(1));
-            let new_future = and_then(future, |x| ready(Ok::<i32, i32>(x + 3)));
+            let new_future = future.and_then(|x| ready(Ok(x + 3)));
             assert_eq!(new_future.await, Err(1));
         });
     }
@@ -569,7 +592,7 @@ mod tests {
     fn test_or_else() {
         executor::block_on(async {
             let future = ready(Err::<i32, i32>(1));
-            let new_future = or_else(future, |x| ready(Err::<i32, i32>(x + 3)));
+            let new_future = future.or_else(|x| ready(Err(x + 3)));
             assert_eq!(new_future.await, Err(4));
         });
     }
@@ -578,7 +601,7 @@ mod tests {
     fn test_map_ok() {
         executor::block_on(async {
             let future = ready(Ok::<i32, i32>(1));
-            let new_future = map_ok(future, |x| x + 3);
+            let new_future = future.map_ok(|x| x + 3);
             assert_eq!(new_future.await, Ok(4));
         });
     }
@@ -587,7 +610,7 @@ mod tests {
     fn test_map_err() {
         executor::block_on(async {
             let future = ready(Err::<i32, i32>(1));
-            let new_future = map_err(future, |x| x + 3);
+            let new_future = future.map_err(|x| x + 3);
             assert_eq!(new_future.await, Err(4));
         });
     }
@@ -596,7 +619,7 @@ mod tests {
     fn test_flatten() {
         executor::block_on(async {
             let nested_future = ready(ready(1));
-            let future = flatten(nested_future);
+            let future = nested_future.flatten();
             assert_eq!(future.await, 1);
         });
     }
@@ -605,7 +628,7 @@ mod tests {
     fn test_inspect() {
         executor::block_on(async {
             let future = ready(1);
-            let new_future = inspect(future, |&x| assert_eq!(x, 1));
+            let new_future = future.inspect(|&x| assert_eq!(x, 1));
             assert_eq!(new_future.await, 1);
         });
     }
@@ -614,7 +637,7 @@ mod tests {
     fn test_err_into() {
         executor::block_on(async {
             let future_err_u8 = ready(Err::<(), u8>(1));
-            let future_err_i32 = err_into::<i32, _, _, _>(future_err_u8);
+            let future_err_i32 = future_err_u8.err_into();
 
             assert_eq!(future_err_i32.await, Err::<(), i32>(1));
         });
@@ -624,7 +647,7 @@ mod tests {
     fn test_unwrap_or_else() {
         executor::block_on(async {
             let future = ready(Err::<(), &str>("Boom!"));
-            let new_future = unwrap_or_else(future, |_| ());
+            let new_future = future.unwrap_or_else(|_| ());
             assert_eq!(new_future.await, ());
         });
     }