Skip to content

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
Contributor

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
Collaborator

bors commented Jul 26, 2018

📌 Commit bce8a91 has been approved by aturon

@bors
Copy link
Collaborator

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