Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std::ops::Try impl for std::task::Poll #52721

Merged
merged 1 commit into from
Jul 26, 2018
Merged

Conversation

cramertj
Copy link
Member

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<...>>>).

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 26, 2018
@seanmonstar
Copy link
Contributor

So that I understand these type signatures correctly, this is for converting Poll<Result>s into Polls? As in, it's not quite the same as the older try_ready!, which would give me T back, not wrapped in Poll::Ready(t), right?

@cramertj
Copy link
Member Author

@seanmonstar Right, this is just like if you were to use ? in the futures-0.1 world (propagates errors, not readiness). You can combine this with the ready! macro to propagate Poll::Pending. So 0.3 try_ready!(x) maps to 0.3 ready!(x?), and 0.1 x? maps to 0.3 `x?.

@aturon
Copy link
Member

aturon commented Jul 26, 2018

I like this factoring (of just handling the error conversions here, and leaving macros for readiness projection). And in any case, 👍 for trying it out and seeing how it feels!

@bors r+

@bors
Copy link
Contributor

bors commented Jul 26, 2018

📌 Commit bce8a91 has been approved by aturon

@bors
Copy link
Contributor

bors commented Jul 26, 2018

🌲 The tree is currently closed for pull requests below priority 99, this pull request will be tested once the tree is reopened

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 26, 2018
@MajorBreakfast
Copy link
Contributor

I think it's a good idea to try this out. However, it has to prove itself. In particular I would like to see some of our combinators converted to this new style.

BTW where is the difference between:

let x = ready!(future.poll()?);

let x = ready!(future.poll())?;

I see that it's different for poll_next() though. Seems complicated

So, let's try it, but I remain skeptical

@MajorBreakfast
Copy link
Contributor

Okay never mind. I understand the difference now: from_error returns Poll::Ready(Err(e))

Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this pull request Jul 26, 2018
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<...>>>`).
@cramertj
Copy link
Member Author

@MajorBreakfast

BTW where is the difference between:
let x = ready!(future.poll()?);
let x = ready!(future.poll())?;

The first one will first check for errors, return them if necessary, then check for Poll::Pending and return if necessary. The second will do the opposite order. There's no difference in the end result, since you can't have both Poll::Pending and Poll:Ready(Err(...))/Poll::Ready(Some(Err(...)))

@MajorBreakfast
Copy link
Contributor

@cramertj No I was wrong there. The second one won't actually work because ready! extracts the Result<T, E> from the Poll::Ready(_). Then, ? returns the E from the Err(_) variant which doesn't match the function's return type (Poll). Only the first one works.

@cramertj
Copy link
Member Author

cramertj commented Jul 26, 2018

@MajorBreakfast

No I was wrong there. The second one won't actually work because ready! extracts the Result<T, E> from the Poll::Ready(). Then, ? returns the E from the Err() variant which doesn't match the function's return type (Poll). Only the first one works.

When using ? on a value, that value's type doesn't have to match the return type. ready!(future.poll())?, if ready! succeeds, would be like doing ? on a Result<T, E>, which (after this PR) will work fine in a function which returns Poll<Result<T, E>> or Poll<Option<Result<T, E>>>.

bors added a commit that referenced this pull request Jul 26, 2018
Rollup of 16 pull requests

Successful merges:

 - #52558 (Add tests for ICEs which no longer repro)
 - #52610 (Clarify what a task is)
 - #52617 (Don't match on region kinds when reporting NLL errors)
 - #52635 (Fix #[linkage] propagation though generic functions)
 - #52647 (Suggest to take and ignore args while closure args count mismatching)
 - #52649 (Point spans to inner elements of format strings)
 - #52654 (Format linker args in a way that works for gcc and ld)
 - #52667 (update the stdsimd submodule)
 - #52674 (Impl Executor for Box<E: Executor>)
 - #52690 (ARM: expose `rclass` and `dsp` target features)
 - #52692 (Improve readability in a few sorts)
 - #52695 (Hide some lints which are not quite right the way they are reported to the user)
 - #52718 (State default capacity for BufReader/BufWriter)
 - #52721 (std::ops::Try impl for std::task::Poll)
 - #52723 (rustc: Register crates under their real names)
 - #52734 (sparc ABI issue - structure returning from function is returned in 64bit registers (with tests))

Failed merges:

 - #52678 ([NLL] Use better spans in some errors)

r? @ghost
@MajorBreakfast
Copy link
Contributor

@cramertj Ah I see. It seems that Try works slightly different to how I thought it would. Thx for the explainer!

@bors bors merged commit bce8a91 into rust-lang:master Jul 26, 2018
@cramertj cramertj deleted the try-poll branch July 26, 2018 22:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants