Skip to content

Commit 6b94ad3

Browse files
Nemo157cramertj
authored andcommitted
Add never_error combinator
1 parent 8efde61 commit 6b94ad3

File tree

6 files changed

+62
-0
lines changed

6 files changed

+62
-0
lines changed

futures-util/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ io-compat = ["compat", "tokio-io"]
2222
bench = []
2323
nightly = ["futures-core-preview/nightly", "futures-sink-preview/nightly"]
2424
cfg-target-has-atomic = ["futures-core-preview/cfg-target-has-atomic"]
25+
never-type = []
2526
alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc"]
2627

2728
[dependencies]

futures-util/src/future/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ pub use self::inspect::Inspect;
7070
mod unit_error;
7171
pub use self::unit_error::UnitError;
7272

73+
#[cfg(feature = "never-type")]
74+
mod never_error;
75+
#[cfg(feature = "never-type")]
76+
pub use self::never_error::NeverError;
77+
7378
// Implementation details
7479
mod chain;
7580
pub(crate) use self::chain::Chain;
@@ -537,6 +542,15 @@ pub trait FutureExt: Future {
537542
UnitError::new(self)
538543
}
539544

545+
#[cfg(feature = "never-type")]
546+
/// Turns a [`Future<Output = T>`](Future) into a
547+
/// [`TryFuture<Ok = T, Error = !`>](futures_core::future::TryFuture).
548+
fn never_error(self) -> NeverError<Self>
549+
where Self: Sized
550+
{
551+
NeverError::new(self)
552+
}
553+
540554
/// A convenience for calling `Future::poll` on `Unpin` future types.
541555
fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
542556
where Self: Unpin + Sized
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use core::pin::Pin;
2+
use futures_core::future::{FusedFuture, Future};
3+
use futures_core::task::{self, Poll};
4+
use pin_utils::unsafe_pinned;
5+
6+
/// Future for the [`never_error`](super::FutureExt::never_error) combinator.
7+
#[derive(Debug)]
8+
#[must_use = "futures do nothing unless polled"]
9+
pub struct NeverError<Fut> {
10+
future: Fut,
11+
}
12+
13+
impl<Fut> NeverError<Fut> {
14+
unsafe_pinned!(future: Fut);
15+
16+
pub(super) fn new(future: Fut) -> NeverError<Fut> {
17+
NeverError { future }
18+
}
19+
}
20+
21+
impl<Fut: Unpin> Unpin for NeverError<Fut> {}
22+
23+
impl<Fut: FusedFuture> FusedFuture for NeverError<Fut> {
24+
fn is_terminated(&self) -> bool { self.future.is_terminated() }
25+
}
26+
27+
impl<Fut, T> Future for NeverError<Fut>
28+
where Fut: Future<Output = T>,
29+
{
30+
type Output = Result<T, !>;
31+
32+
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<T, !>> {
33+
self.future().poll(cx).map(Ok)
34+
}
35+
}

futures-util/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![cfg_attr(feature = "alloc", feature(box_into_pin))]
66
#![cfg_attr(feature = "std", feature(async_await, await_macro))]
77
#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]
8+
#![cfg_attr(feature = "never-type", feature(never_type))]
89

910
#![cfg_attr(not(feature = "std"), no_std)]
1011
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
@@ -14,6 +15,9 @@
1415
#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))]
1516
compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features");
1617

18+
#[cfg(all(feature = "never-type", not(feature = "nightly")))]
19+
compile_error!("The `never-type` feature requires the `nightly` feature as an explicit opt-in to unstable features");
20+
1721
#[cfg(feature = "alloc")]
1822
extern crate alloc;
1923

futures/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ default = ["std"]
4242
compat = ["std", "futures-util-preview/compat"]
4343
io-compat = ["compat", "futures-util-preview/io-compat"]
4444
cfg-target-has-atomic = ["futures-core-preview/cfg-target-has-atomic", "futures-util-preview/cfg-target-has-atomic"]
45+
never-type = ["futures-util-preview/never-type"]
4546
alloc = ["futures-core-preview/alloc", "futures-sink-preview/alloc", "futures-util-preview/alloc"]

futures/src/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
2424
#![feature(futures_api)]
2525
#![cfg_attr(feature = "cfg-target-has-atomic", feature(cfg_target_has_atomic))]
26+
#![cfg_attr(feature = "never-type", feature(never_type))]
2627

2728
#![cfg_attr(not(feature = "std"), no_std)]
2829

@@ -33,6 +34,9 @@
3334
#[cfg(all(feature = "cfg-target-has-atomic", not(feature = "nightly")))]
3435
compile_error!("The `cfg-target-has-atomic` feature requires the `nightly` feature as an explicit opt-in to unstable features");
3536

37+
#[cfg(all(feature = "never-type", not(feature = "nightly")))]
38+
compile_error!("The `never-type` feature requires the `nightly` feature as an explicit opt-in to unstable features");
39+
3640
#[doc(hidden)] pub use futures_util::core_reexport;
3741

3842
#[doc(hidden)] pub use futures_core::future::Future;
@@ -230,6 +234,9 @@ pub mod future {
230234
UnwrapOrElse,
231235
};
232236

237+
#[cfg(feature = "never-type")]
238+
pub use futures_util::future::NeverError;
239+
233240
#[cfg(feature = "alloc")]
234241
pub use futures_util::try_future::{
235242
try_join_all, TryJoinAll,

0 commit comments

Comments
 (0)