Repository navigation
Tracking Issue for Result::flatten (result_flattening) #70142
Copy link
Copy link
Closed
Labels
A-result-optionArea: Result and Option combinatorsArea: Result and Option combinatorsB-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.Libs issues that are tracked on the team's radar.Libs-SmallLibs issues that are considered "small" or self-containedLibs issues that are considered "small" or self-containedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]
Description
This is a tracking issue for the Result::flatten API.
The feature gate for the issue is #![feature(result_flattening)].
impl<T, E> Result<Result<T, E>, E> {
pub fn flatten(self) -> Result<T, E>;
}About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also uses as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
- Implement
- Adjust documentation (see instructions on rustc-dev-guide)
- Stabilization PR (see instructions on rustc-dev-guide)
Unresolved Questions
Implementation history
- Implementation Add Result<Result<T, E>, E>::flatten -> Result<T, E> #70140
Reacted by Ken Reed, N.B., CJ, Jeremiah Senkpiel, chpio, Chayim Refael Friedman, Tim Hutt, Flux Xu, Jan Riemer, Marco Conte and 81 more
Reacted by Stanislav Tkach, Iohann Rabeson, Flavio Vilante, Timur Tugushev, Guilherme Salustiano, estk, ErrorNoInternet, Yikai Cai and Andrew Banchich
Metadata
Metadata
Assignees
Labels
A-result-optionArea: Result and Option combinatorsArea: Result and Option combinatorsB-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-libs-radarLibs issues that are tracked on the team's radar.Libs issues that are tracked on the team's radar.Libs-SmallLibs issues that are considered "small" or self-containedLibs issues that are considered "small" or self-containedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]
Activity
Rollup merge of rust-lang#70140 - Nemo157:result-flatten, r=Amanieu
josephlr commentedon Sep 12, 2020
With the stabilization of #49146, this function can now have a trivial
const fnimplementation using match. Should this function just be directly stabilized as aconst fn?Diggsey commentedon Sep 28, 2020
I think it would also be useful to have a
flatten_intomethod that would also allow conversion of the error type.de-vri-es commentedon Oct 7, 2020
It could also be
But: which error type do you convert into the other?
Keeping the inner error type seemed more logical to me, under the assumption that the inner thing is what you really want, and the outer result represents further processing.
An example where that occurs is using
tokio::time::timeoutto add a timeout to I/O operations. The result has anElapsederror that can be converted into anstd::io::Error, but not vice-versa.yoshuawuyts commentedon Oct 12, 2020
In #70140 (comment) @CryZe brought up:
This seems to touch on the same point as @Diggsey's and @de-vri-es's comments on converting error types. And it's easy to see why; the
?operator just works when one error can be converted into another, and it's not unreasonable to expect other methods that deal with converting error types to work much the same.The only argument against this so far has been #70140 (comment) which talks about monadic similarities between
OptionandResult. I don't find that argument particularly appealing, as it centers a subjective theoretical view on what I think is an ergonomics question. I think it's far preferable for Rust to feel internally consistent to over consistency with a monadic model.I think the implementation of @de-vri-es looks right. I intend to open a PR shortly to implement this
Nemo157 commentedon Oct 12, 2020
I don't know that
E1: From<E2>is the correct order, my instinct would have been the inverse. It seems like getting some examples of usecases would be good to see how each order affects it?(Though personally I don't think the base
.flatten()method should do conversion, and having a separate.flatten_into()might be a good approach).One example for when you have two incompatible error types, and you have to convert into a third error type:
For maximum ergonomics, with improved defaults and
?type inferencing it could even be something likewhich would allow converting two incompatible error types into a final error type that they are both compatible with
yoshuawuyts commentedon Oct 12, 2020
Oh yeah good one. I guess the one I had in mind was the one @de-vri-es mentioned with an async timeout method. For example in
async-stdthe API would be the following (ref):The return type here is
We'd want to convert from
future::Timeouttoio::Error, or convertE2intoE1-- which the implementation does. But I'd be curious to know if there are any practical counter-examples.I think you're asking an intriguing question: what if both errors could somehow converge into some third error type? You suggest using
flatten_intofor this; but that raises two questions:Result::flatten_intoforbidResult::flattenfrom having anIntobound? I would assume not?flattenandflatten_intooverlap? Assuming we can declare the default offn flatten_into<E = E1>, having both seems redundant?Diggsey commentedon Oct 12, 2020
FWIW, the specific case where I encountered this requires the full
flatten_intoversion where a 3rd error type is specified.That said, I think there is value in both, as
flatten_intowill usually require explicit type annotations, whereas the variations offlattenshould for the most part be able to infer their types, and so will be more ergonomic where it is possible to use them.de-vri-es commentedon Oct 12, 2020
Agreed.
The
E1vsE2issue might be enough reason to only support a single error type without conversion forflatten(). Or have aflatten_inner()andflatten_outer(), but maybe that is a bit overkill./edit: Also, you can't have defaults for generic type arguments for functions, right? So that won't be a solution (see also #36887).
22 remaining items
add ext trait and function to flatten nested VortexResult (#2360)
Rynibami commentedon May 15, 2025
I think this feature is neat to have on stable rust, but I haven't seen any clear progression on this topic except for @RalfJung's const fn pull request. Can I assume that the provided steps (see quote) describe all remaining work before it can be integrated with stable rust?
If that is all, then I would like to contribute by adjusting the documentation and setting up a stabilization PR. I might need some help though as I am new to the rust project.
RalfJung commentedon May 15, 2025
@Rynibami this is an ancient tracking issue so the template is a bit misleading, sorry for that.
The next step here would be to make a PR that stabilizes the feature. Make sure that the PR description contains a summary of what is being stabilized, in particular including the function signature. It also seems like the corresponding method on
Optionis already stable for a while which seems worth mentioning.Then we can nominate that PR for discussion by the relevant team.
Rynibami commentedon May 16, 2025
Thank you very much for elaborating on my comment @RalfJung.
I've looked into the implementation of both
Option::flattenandResult::flatten. They are identical except for the implications of theEerror type (Result<Result<T, E>, E>). So this looks like I do not have to write any new code, changing only compiler flags and create documentation.The
flattenfunction inoption.rsThe
flattenfunction inresult.rsI can make a new PR that highlights the already implemented
flattenfunction, update the compiler flags and documentation, and follow the book on stabilizing features. Is this the complete way and correct order to do this? Or am I missing something?RalfJung commentedon May 18, 2025
Yes that is correct. :)
Rollup merge of rust-lang#141072 - Rynibami:stabilize-const-result-fl…
Rollup merge of rust-lang#141072 - Rynibami:stabilize-const-result-fl…
Unrolled build for #141072
Rollup merge of #141072 - Rynibami:stabilize-const-result-flatten, r=…
Rollup merge of rust-lang#141072 - Rynibami:stabilize-const-result-fl…
Rollup merge of #141072 - Rynibami:stabilize-const-result-flatten, r=…
rursprung commentedon Jul 10, 2025
it seems that #141072 stabilized
Result::flattenin the upcoming 1.89 release. what i haven't read is what the goal is regarding theflatten_intodiscussion above? will this be split out into a new issue?i just ran into this when working with
postcard-rpc(an remote procedure call library for embedded systems) where you can end up withResult<T, Ebusiness>, Etransport>: you always get aResult<T, Etransport>whereEtransportis the error coming from the transport layer (e.g. an error during USB communication with the target device) andTis fully under your control. now it's quite likely that you might want to surface some (business) errors from the underlying device in the RPC call, so instead of, say, returning anu8you might returnResult<u8, MyError>, in which case you'll end up withResult<Result<u8, MyError>, HostErr<WireError>>.usually you wrap these calls in an own function to abstract away the RPC communication. in that case you'll probably implement an own error type to return there (e.g. you might return
Result<u8, MyLibraryError>) and add animpl From<MyError> for MyLibraryError(and the same for the other error type).the example has a custom
flattenimplementation: https://github.com/jamesmunns/postcard-rpc/blob/10a1f6a6697c556eb07d9dec6bfd804e14830c5b/example/workbook-host/src/client.rs#L30-L42i think it'd be great if we could also get
flatten_into(or similar) incoreRalfJung commentedon Jul 10, 2025
Good point, this should have been closed by #141072.
Regarding
flatten_into, that did not make it into this feature. It would be a completely new API; the process for proposing that is to file an ACP with the libs-api team.signal-desktop: build ringrtc with rust 1.89