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<...>>>`).
This commit is contained in:
commit
858adfe21d
@ -12,6 +12,9 @@
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
|
||||
use ops::Try;
|
||||
use result::Result;
|
||||
|
||||
/// Indicates whether a value is available or if the current task has been
|
||||
/// scheduled to receive a wakeup instead.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
@ -39,6 +42,7 @@ impl<T> Poll<T> {
|
||||
}
|
||||
|
||||
/// Returns whether this is `Poll::Ready`
|
||||
#[inline]
|
||||
pub fn is_ready(&self) -> bool {
|
||||
match *self {
|
||||
Poll::Ready(_) => true,
|
||||
@ -47,6 +51,7 @@ impl<T> Poll<T> {
|
||||
}
|
||||
|
||||
/// Returns whether this is `Poll::Pending`
|
||||
#[inline]
|
||||
pub fn is_pending(&self) -> bool {
|
||||
!self.is_ready()
|
||||
}
|
||||
@ -81,3 +86,52 @@ impl<T> From<T> for Poll<T> {
|
||||
Poll::Ready(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Try for Poll<Result<T, E>> {
|
||||
type Ok = Poll<T>;
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error> {
|
||||
match self {
|
||||
Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
|
||||
Poll::Ready(Err(e)) => Err(e),
|
||||
Poll::Pending => Ok(Poll::Pending),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_error(e: Self::Error) -> Self {
|
||||
Poll::Ready(Err(e))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_ok(x: Self::Ok) -> Self {
|
||||
x.map(Ok)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Try for Poll<Option<Result<T, E>>> {
|
||||
type Ok = Poll<Option<T>>;
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error> {
|
||||
match self {
|
||||
Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
|
||||
Poll::Ready(Some(Err(e))) => Err(e),
|
||||
Poll::Ready(None) => Ok(Poll::Ready(None)),
|
||||
Poll::Pending => Ok(Poll::Pending),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_error(e: Self::Error) -> Self {
|
||||
Poll::Ready(Some(Err(e)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_ok(x: Self::Ok) -> Self {
|
||||
x.map(|x| x.map(Ok))
|
||||
}
|
||||
}
|
||||
|
61
src/test/ui/try-poll.rs
Normal file
61
src/test/ui/try-poll.rs
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![allow(dead_code, unused)]
|
||||
#![feature(futures_api)]
|
||||
|
||||
use std::task::Poll;
|
||||
|
||||
struct K;
|
||||
struct E;
|
||||
|
||||
fn as_result() -> Result<(), E> {
|
||||
// From Result
|
||||
let K = Ok::<K, E>(K)?;
|
||||
|
||||
// From Poll<Result>
|
||||
let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
|
||||
|
||||
// From Poll<Option<Result>>
|
||||
let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_poll_result() -> Poll<Result<(), E>> {
|
||||
// From Result
|
||||
let K = Ok::<K, E>(K)?;
|
||||
|
||||
// From Poll<Result>
|
||||
let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
|
||||
|
||||
// From Poll<Option<Result>>
|
||||
let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
|
||||
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn as_poll_option_result() -> Poll<Option<Result<(), E>>> {
|
||||
// From Result
|
||||
let K = Ok::<K, E>(K)?;
|
||||
|
||||
// From Poll<Result>
|
||||
let _: Poll<K> = Poll::Ready::<Result<K, E>>(Ok(K))?;
|
||||
|
||||
// From Poll<Option<Result>>
|
||||
let _: Poll<Option<K>> = Poll::Ready::<Option<Result<K, E>>>(None)?;
|
||||
|
||||
Poll::Ready(Some(Ok(())))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user