From 9df248effff8b098cb786b778b338ec8069751ce Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 24 Aug 2016 23:25:42 -0700 Subject: [PATCH 1/4] Add feature-gated Never future --- Cargo.toml | 1 + src/lib.rs | 5 +++++ src/never.rs | 25 +++++++++++++++++++++++++ tests/all.rs | 21 +++++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 src/never.rs diff --git a/Cargo.toml b/Cargo.toml index a20fd94a2b..97b76b0eb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,5 @@ log = { version = "0.3", default-features = false } [features] use_std = [] +never = [] default = ["use_std"] diff --git a/src/lib.rs b/src/lib.rs index eec24c8719..202523d5fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,6 +151,7 @@ #![no_std] #![deny(missing_docs)] +#![cfg_attr(feature = "never", feature(never_type, conservative_impl_trait))] #[macro_use] #[cfg(feature = "use_std")] @@ -176,11 +177,15 @@ mod empty; mod failed; mod finished; mod lazy; +#[cfg(feature = "never")] +mod never; pub use done::{done, Done}; pub use empty::{empty, Empty}; pub use failed::{failed, Failed}; pub use finished::{finished, Finished}; pub use lazy::{lazy, Lazy}; +#[cfg(feature = "never")] +pub use never::{never, Never}; // combinators mod and_then; diff --git a/src/never.rs b/src/never.rs new file mode 100644 index 0000000000..ef73dfd781 --- /dev/null +++ b/src/never.rs @@ -0,0 +1,25 @@ +use {Future, Poll}; + +/// A future which is never resolved. +/// +/// This future can be created with the `empty` function. +pub struct Never {} + +/// Creates a future which never resolves, representing a computation that never +/// finishes. +/// +/// The returned future will never resolve with a success but is still +/// susceptible to cancellation. That is, if a callback is scheduled on the +/// returned future, it is only run once the future is dropped (canceled). +pub fn never() -> impl Future + Send + 'static { + (Never {}).map(|x| x).map_err(|x| x) +} + +impl Future for Never { + type Item = !; + type Error = !; + + fn poll(&mut self) -> Poll { + Poll::NotReady + } +} diff --git a/tests/all.rs b/tests/all.rs index 405b9fd4c7..ac78647e52 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "never", feature(conservative_impl_trait))] + extern crate futures; use std::sync::mpsc::{channel, TryRecvError}; @@ -79,6 +81,25 @@ fn test_empty() { assert_empty(|| empty().then(|a| a)); } +#[cfg(feature = "never")] +#[test] +fn test_never() { + fn never() -> impl Future { futures::never() } + + assert_empty(|| never()); + assert_empty(|| never().select(never())); + assert_empty(|| never().join(never())); + assert_empty(|| never().join(f_ok(1))); + assert_empty(|| f_ok(1).join(never())); + assert_empty(|| never().or_else(move |_| never())); + assert_empty(|| never().and_then(move |_| never())); + assert_empty(|| f_err(1).or_else(move |_| never())); + assert_empty(|| f_ok(1).and_then(move |_| never())); + assert_empty(|| never().map(|a| a + 1)); + assert_empty(|| never().map_err(|a| a + 1)); + assert_empty(|| never().then(|a| a)); +} + #[test] fn test_finished() { assert_done(|| finished(1), ok(1)); From 6e2ed7612750a007d537be97274c8f0c62ac172a Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Wed, 24 Aug 2016 23:46:23 -0700 Subject: [PATCH 2/4] Add Never type versions of Finished and Failed --- src/lib.rs | 6 ++++- src/never.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/all.rs | 20 ++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 202523d5fe..1e843c0ea1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -174,18 +174,22 @@ pub use poll::{Poll, Async}; // Primitive futures mod done; mod empty; +#[cfg(not(feature = "never"))] mod failed; +#[cfg(not(feature = "never"))] mod finished; mod lazy; #[cfg(feature = "never")] mod never; pub use done::{done, Done}; pub use empty::{empty, Empty}; +#[cfg(not(feature = "never"))] pub use failed::{failed, Failed}; +#[cfg(not(feature = "never"))] pub use finished::{finished, Finished}; pub use lazy::{lazy, Lazy}; #[cfg(feature = "never")] -pub use never::{never, Never}; +pub use never::{never, Never, failed, Failed, finished, Finished}; // combinators mod and_then; diff --git a/src/never.rs b/src/never.rs index ef73dfd781..dfcb665e96 100644 --- a/src/never.rs +++ b/src/never.rs @@ -3,6 +3,7 @@ use {Future, Poll}; /// A future which is never resolved. /// /// This future can be created with the `empty` function. +#[derive(Copy, Clone)] pub struct Never {} /// Creates a future which never resolves, representing a computation that never @@ -23,3 +24,68 @@ impl Future for Never { Poll::NotReady } } + +/// A future representing a finished but erroneous computation. +/// +/// Created by the `failed` function. +pub struct Failed { + e: Option, +} + +/// Creates a "leaf future" from an immediate value of a failed computation. +/// +/// The returned future is similar to `done` where it will immediately run a +/// scheduled callback with the provided value. +/// +/// # Examples +/// +/// ``` +/// use futures::*; +/// +/// let future_of_err_1 = failed::(1); +/// ``` +pub fn failed(e: E) -> impl Future { + Failed { e: Some(e) }.map(|x| x) +} + +impl Future for Failed { + type Item = !; + type Error = E; + + fn poll(&mut self) -> Poll { + Poll::Err(self.e.take().expect("cannot poll Failed twice")) + } +} + +/// A future representing a finished successful computation. +/// +/// Created by the `finished` function. +pub struct Finished { + t: Option, +} + +/// Creates a "leaf future" from an immediate value of a finished and +/// successful computation. +/// +/// The returned future is similar to `done` where it will immediately run a +/// scheduled callback with the provided value. +/// +/// # Examples +/// +/// ``` +/// use futures::*; +/// +/// let future_of_1 = finished::(1); +/// ``` +pub fn finished(t: T) -> impl Future { + Finished { t: Some(t) }.map_err(|x| x) +} + +impl Future for Finished { + type Item = T; + type Error = !; + + fn poll(&mut self) -> Poll { + Poll::Ok(self.t.take().expect("cannot poll Finished twice")) + } +} diff --git a/tests/all.rs b/tests/all.rs index ac78647e52..5f09046428 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -106,6 +106,7 @@ fn test_finished() { assert_done(|| failed(1), err(1)); } +#[cfg(not(feature = "never"))] #[test] fn flatten() { fn finished(a: T) -> Finished { @@ -124,6 +125,25 @@ fn flatten() { assert_empty(|| empty::().map(finished).flatten()); } +#[cfg(feature = "never")] +#[test] +fn flatten() { + fn finished(a: T) -> impl Future { + futures::finished(a) + } + fn failed(b: E) -> impl Future { + futures::failed(b) + } + + assert_done(|| finished(finished(1)).flatten(), ok(1)); + assert_done(|| finished(failed(1)).flatten(), err(1)); + assert_done(|| failed(1u32).map(finished).flatten(), err(1)); + assert_done(|| futures::finished::<_, u8>(futures::finished::<_, u32>(1)) + .flatten(), ok(1)); + assert_empty(|| finished(empty::()).flatten()); + assert_empty(|| empty::().map(finished).flatten()); +} + #[test] fn smoke_oneshot() { assert_done(|| { From 6ac6fcbf1a29b25175c541619142dfebe84c306a Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Sat, 3 Sep 2016 08:40:10 -0700 Subject: [PATCH 3/4] Add full type params with defaults to Never types --- src/lib.rs | 2 +- src/never.rs | 42 ++++++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1e843c0ea1..27bddb1095 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,7 +151,7 @@ #![no_std] #![deny(missing_docs)] -#![cfg_attr(feature = "never", feature(never_type, conservative_impl_trait))] +#![cfg_attr(feature = "never", feature(never_type, conservative_impl_trait, default_type_parameter_fallback))] #[macro_use] #[cfg(feature = "use_std")] diff --git a/src/never.rs b/src/never.rs index dfcb665e96..bf625cd405 100644 --- a/src/never.rs +++ b/src/never.rs @@ -1,10 +1,14 @@ +use core::marker; + use {Future, Poll}; /// A future which is never resolved. /// -/// This future can be created with the `empty` function. +/// This future can be created with the `never` function. #[derive(Copy, Clone)] -pub struct Never {} +pub struct Never { + _data: marker::PhantomData<(T, E)>, +} /// Creates a future which never resolves, representing a computation that never /// finishes. @@ -12,13 +16,13 @@ pub struct Never {} /// The returned future will never resolve with a success but is still /// susceptible to cancellation. That is, if a callback is scheduled on the /// returned future, it is only run once the future is dropped (canceled). -pub fn never() -> impl Future + Send + 'static { - (Never {}).map(|x| x).map_err(|x| x) +pub fn never() -> Never { + Never { _data: marker::PhantomData } } -impl Future for Never { - type Item = !; - type Error = !; +impl Future for Never { + type Item = T; + type Error = E; fn poll(&mut self) -> Poll { Poll::NotReady @@ -28,7 +32,8 @@ impl Future for Never { /// A future representing a finished but erroneous computation. /// /// Created by the `failed` function. -pub struct Failed { +pub struct Failed { + _t: marker::PhantomData, e: Option, } @@ -44,12 +49,12 @@ pub struct Failed { /// /// let future_of_err_1 = failed::(1); /// ``` -pub fn failed(e: E) -> impl Future { - Failed { e: Some(e) }.map(|x| x) +pub fn failed(e: E) -> Failed { + Failed { t: marker::PhantomData, e: Some(e) } } -impl Future for Failed { - type Item = !; +impl Future for Failed { + type Item = T; type Error = E; fn poll(&mut self) -> Poll { @@ -60,8 +65,9 @@ impl Future for Failed { /// A future representing a finished successful computation. /// /// Created by the `finished` function. -pub struct Finished { +pub struct Finished { t: Option, + _e: marker::PhantomData, } /// Creates a "leaf future" from an immediate value of a finished and @@ -77,15 +83,15 @@ pub struct Finished { /// /// let future_of_1 = finished::(1); /// ``` -pub fn finished(t: T) -> impl Future { - Finished { t: Some(t) }.map_err(|x| x) +pub fn finished(t: T) -> Finished { + Finished { t: Some(t), _e: marker::PhantomData } } -impl Future for Finished { +impl Future for Finished { type Item = T; - type Error = !; + type Error = E; - fn poll(&mut self) -> Poll { + fn poll(&mut self) -> Poll { Poll::Ok(self.t.take().expect("cannot poll Finished twice")) } } From 7a2bd587b01ba39bf4e24b18c2f1191ad0ad2f81 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Sun, 4 Sep 2016 09:42:47 -0700 Subject: [PATCH 4/4] Give alternate names to Never types --- src/lib.rs | 12 ++++++------ src/never.rs | 38 ++++++++++++++++++++------------------ tests/all.rs | 33 ++++++++++++--------------------- 3 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 27bddb1095..c0ff2c7199 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,7 +151,7 @@ #![no_std] #![deny(missing_docs)] -#![cfg_attr(feature = "never", feature(never_type, conservative_impl_trait, default_type_parameter_fallback))] +#![cfg_attr(feature = "never", feature(never_type, default_type_parameter_fallback))] #[macro_use] #[cfg(feature = "use_std")] @@ -174,22 +174,22 @@ pub use poll::{Poll, Async}; // Primitive futures mod done; mod empty; -#[cfg(not(feature = "never"))] mod failed; -#[cfg(not(feature = "never"))] mod finished; mod lazy; #[cfg(feature = "never")] mod never; pub use done::{done, Done}; pub use empty::{empty, Empty}; -#[cfg(not(feature = "never"))] pub use failed::{failed, Failed}; -#[cfg(not(feature = "never"))] pub use finished::{finished, Finished}; pub use lazy::{lazy, Lazy}; #[cfg(feature = "never")] -pub use never::{never, Never, failed, Failed, finished, Finished}; +pub use never::{ + never, Never, + always_failed, AlwaysFailed, + always_finished, AlwaysFinished +}; // combinators mod and_then; diff --git a/src/never.rs b/src/never.rs index bf625cd405..199b4a32b5 100644 --- a/src/never.rs +++ b/src/never.rs @@ -1,6 +1,6 @@ use core::marker; -use {Future, Poll}; +use {Future, Poll, Async}; /// A future which is never resolved. /// @@ -24,15 +24,15 @@ impl Future for Never { type Item = T; type Error = E; - fn poll(&mut self) -> Poll { - Poll::NotReady + fn poll(&mut self) -> Poll { + Ok(Async::NotReady) } } /// A future representing a finished but erroneous computation. /// -/// Created by the `failed` function. -pub struct Failed { +/// Created by the `always_failed` function. +pub struct AlwaysFailed { _t: marker::PhantomData, e: Option, } @@ -45,27 +45,28 @@ pub struct Failed { /// # Examples /// /// ``` +///#![feature(default_type_parameter_fallback)] /// use futures::*; /// -/// let future_of_err_1 = failed::(1); +/// let future_of_err_1 = always_failed(1); /// ``` -pub fn failed(e: E) -> Failed { - Failed { t: marker::PhantomData, e: Some(e) } +pub fn always_failed(e: E) -> AlwaysFailed { + AlwaysFailed { _t: marker::PhantomData, e: Some(e) } } -impl Future for Failed { +impl Future for AlwaysFailed { type Item = T; type Error = E; - fn poll(&mut self) -> Poll { - Poll::Err(self.e.take().expect("cannot poll Failed twice")) + fn poll(&mut self) -> Poll { + Err(self.e.take().expect("cannot poll AlwaysFailed twice")) } } /// A future representing a finished successful computation. /// -/// Created by the `finished` function. -pub struct Finished { +/// Created by the `always_finished` function. +pub struct AlwaysFinished { t: Option, _e: marker::PhantomData, } @@ -79,19 +80,20 @@ pub struct Finished { /// # Examples /// /// ``` +///#![feature(default_type_parameter_fallback)] /// use futures::*; /// -/// let future_of_1 = finished::(1); +/// let future_of_1 = always_finished(1); /// ``` -pub fn finished(t: T) -> Finished { - Finished { t: Some(t), _e: marker::PhantomData } +pub fn always_finished(t: T) -> AlwaysFinished { + AlwaysFinished { t: Some(t), _e: marker::PhantomData } } -impl Future for Finished { +impl Future for AlwaysFinished { type Item = T; type Error = E; fn poll(&mut self) -> Poll { - Poll::Ok(self.t.take().expect("cannot poll Finished twice")) + Ok(Async::Ready(self.t.take().expect("cannot poll AlwaysFinished twice"))) } } diff --git a/tests/all.rs b/tests/all.rs index 5f09046428..a6e1b2eb52 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -1,4 +1,4 @@ -#![cfg_attr(feature = "never", feature(conservative_impl_trait))] +#![cfg_attr(feature = "never", feature(never_type, default_type_parameter_fallback))] extern crate futures; @@ -84,8 +84,6 @@ fn test_empty() { #[cfg(feature = "never")] #[test] fn test_never() { - fn never() -> impl Future { futures::never() } - assert_empty(|| never()); assert_empty(|| never().select(never())); assert_empty(|| never().join(never())); @@ -95,8 +93,9 @@ fn test_never() { assert_empty(|| never().and_then(move |_| never())); assert_empty(|| f_err(1).or_else(move |_| never())); assert_empty(|| f_ok(1).and_then(move |_| never())); - assert_empty(|| never().map(|a| a + 1)); - assert_empty(|| never().map_err(|a| a + 1)); + // TODO: Remove when `!` implements `std::ops::Add`` + assert_empty(|| never::().map(|a| a + 1)); + assert_empty(|| never::().map_err(|a| a + 1)); assert_empty(|| never().then(|a| a)); } @@ -106,7 +105,6 @@ fn test_finished() { assert_done(|| failed(1), err(1)); } -#[cfg(not(feature = "never"))] #[test] fn flatten() { fn finished(a: T) -> Finished { @@ -127,21 +125,14 @@ fn flatten() { #[cfg(feature = "never")] #[test] -fn flatten() { - fn finished(a: T) -> impl Future { - futures::finished(a) - } - fn failed(b: E) -> impl Future { - futures::failed(b) - } - - assert_done(|| finished(finished(1)).flatten(), ok(1)); - assert_done(|| finished(failed(1)).flatten(), err(1)); - assert_done(|| failed(1u32).map(finished).flatten(), err(1)); - assert_done(|| futures::finished::<_, u8>(futures::finished::<_, u32>(1)) - .flatten(), ok(1)); - assert_empty(|| finished(empty::()).flatten()); - assert_empty(|| empty::().map(finished).flatten()); +fn flatten_never() { + // TODO: Uncomment when `std::convert::From` is implemented for `i32` + //assert_done(|| always_finished(always_finished(1)).flatten(), ok(1)); + //assert_done(|| always_finished(always_failed(1)).flatten(), err(1)); + //assert_done(|| always_failed(1u32).map(always_finished).flatten(), err(1)); + //assert_done(|| always_finished(always_finished(1)).flatten(), ok(1)); + assert_empty(|| always_finished(never()).flatten()); + assert_empty(|| never().map(always_finished::).flatten()); } #[test]