Skip to content

Commit 858adfe

Browse files
Rollup merge of #52721 - cramertj:try-poll, r=aturon
std::ops::Try impl for std::task::Poll I originally left out the `Try` impl for `Poll` because I was curious if we needed it, and @MajorBreakfast and I had discussed the potential for it to introduce confusion about exactly what control-flow was happening at different points. However, after porting a pretty significant chunk of Fuchsia over to futures 0.3, I discovered that I was *constantly* having to do repetitive matching on `Poll<Result<...>>` or `Poll<Option<Result<...>>>` in order to propagate errors correctly. `try_poll` (propagate `Poll::Ready(Err(..))`s) helped in some places, but it was far more common to need some form of conversion between `Result`, `Poll<Result<...>>`, and `Poll<Option<Result<...>>>`. The `Try` trait conveniently provides all of these conversions in addition to a more concise syntax (`?`), so I'd like to experiment with using these instead. cc @seanmonstar r? @aturon Note: this change means that far more futures 0.1 code can work without significant changes since it papers over the fact that `Result` is no longer at the top-level when using `Stream` and `Future` (since it's now `Poll<Result<...>>` or `Poll<Option<Result<...>>>` instead of `Result<Poll<..>>` and `Result<Poll<Option<...>>>`).
2 parents 091a10e + bce8a91 commit 858adfe

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

src/libcore/task/poll.rs

+54
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
reason = "futures in libcore are unstable",
1313
issue = "50547")]
1414

15+
use ops::Try;
16+
use result::Result;
17+
1518
/// Indicates whether a value is available or if the current task has been
1619
/// scheduled to receive a wakeup instead.
1720
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
@@ -39,6 +42,7 @@ impl<T> Poll<T> {
3942
}
4043

4144
/// Returns whether this is `Poll::Ready`
45+
#[inline]
4246
pub fn is_ready(&self) -> bool {
4347
match *self {
4448
Poll::Ready(_) => true,
@@ -47,6 +51,7 @@ impl<T> Poll<T> {
4751
}
4852

4953
/// Returns whether this is `Poll::Pending`
54+
#[inline]
5055
pub fn is_pending(&self) -> bool {
5156
!self.is_ready()
5257
}
@@ -81,3 +86,52 @@ impl<T> From<T> for Poll<T> {
8186
Poll::Ready(t)
8287
}
8388
}
89+
90+
impl<T, E> Try for Poll<Result<T, E>> {
91+
type Ok = Poll<T>;
92+
type Error = E;
93+
94+
#[inline]
95+
fn into_result(self) -> Result<Self::Ok, Self::Error> {
96+
match self {
97+
Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
98+
Poll::Ready(Err(e)) => Err(e),
99+
Poll::Pending => Ok(Poll::Pending),
100+
}
101+
}
102+
103+
#[inline]
104+
fn from_error(e: Self::Error) -> Self {
105+
Poll::Ready(Err(e))
106+
}
107+
108+
#[inline]
109+
fn from_ok(x: Self::Ok) -> Self {
110+
x.map(Ok)
111+
}
112+
}
113+
114+
impl<T, E> Try for Poll<Option<Result<T, E>>> {
115+
type Ok = Poll<Option<T>>;
116+
type Error = E;
117+
118+
#[inline]
119+
fn into_result(self) -> Result<Self::Ok, Self::Error> {
120+
match self {
121+
Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
122+
Poll::Ready(Some(Err(e))) => Err(e),
123+
Poll::Ready(None) => Ok(Poll::Ready(None)),
124+
Poll::Pending => Ok(Poll::Pending),
125+
}
126+
}
127+
128+
#[inline]
129+
fn from_error(e: Self::Error) -> Self {
130+
Poll::Ready(Some(Err(e)))
131+
}
132+
133+
#[inline]
134+
fn from_ok(x: Self::Ok) -> Self {
135+
x.map(|x| x.map(Ok))
136+
}
137+
}

src/test/ui/try-poll.rs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-pass
12+
13+
#![allow(dead_code, unused)]
14+
#![feature(futures_api)]
15+
16+
use std::task::Poll;
17+
18+
struct K;
19+
struct E;
20+
21+
fn as_result() -> Result<(), E> {
22+
// From Result
23+
let K = Ok::<K, E>(K)?;
24+
25+
// From Poll<Result>
26+
let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
27+
28+
// From Poll<Option<Result>>
29+
let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
30+
31+
Ok(())
32+
}
33+
34+
fn as_poll_result() -> Poll<Result<(), E>> {
35+
// From Result
36+
let K = Ok::<K, E>(K)?;
37+
38+
// From Poll<Result>
39+
let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
40+
41+
// From Poll<Option<Result>>
42+
let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
43+
44+
Poll::Ready(Ok(()))
45+
}
46+
47+
fn as_poll_option_result() -> Poll<Option<Result<(), E>>> {
48+
// From Result
49+
let K = Ok::<K, E>(K)?;
50+
51+
// From Poll<Result>
52+
let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
53+
54+
// From Poll<Option<Result>>
55+
let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
56+
57+
Poll::Ready(Some(Ok(())))
58+
}
59+
60+
fn main() {
61+
}

0 commit comments

Comments
 (0)