Open zkrising opened 1 month ago
I'd like to highlight a different alternative; using expect
or unwrap_or_else
with an appropriate panic for code that isn't prototyping.
That allows both short code and easy grepability (unwrap\(
) for the prototyping case.
For what it's worth: people writing a MVP with no regard for error handling are unlikely to go out of their way to add a dependency on an extension crate just to make the MVP a bit easier to maintain in the future, especially since the extension trait will need to be imported in every file.
I'd like to highlight a different alternative; using expect or unwrap_or_else with an appropriate panic for code that isn't prototyping. That allows both short code and easy grepability (unwrap() for the prototyping case.
what would you recommend for the unreachable case? i use unwrap
a lot in applications where i have a lot of "unreachable" cases that exist mainly because i don't want to dip into unsafe just to remove the unwrap
s from an algorithm.
what would you recommend for the unreachable case?
unwrap_or_else(||unreachable!())
or expect("unreachable")
. Those are a bit verbose, but it's not too bad IMO, especially in non-prototyping code.
I'd like to highlight a different alternative; using
expect
orunwrap_or_else
with an appropriate panic for code that isn't prototyping.That allows both short code and easy grepability (
unwrap\(
) for the prototyping case.
Just as a data point, I use .unwrap()
for TODOs and .expect("rationale")
for "cannot fail" and then turn on Clippy's unwrap_used
lint when prototyping is over.
Proposal
Problem statement
.unwrap()
is semantically overloaded in rust. It finds itself used for two significantly different reasons:None/Err
, our program is in a bad state and we want to exit (missing config files, missing resource files, some external invariant not upheld)None/Err
handling here yet (prototype code)Motivating examples or use cases
Users find themselves using
.unwrap()
for these different reasons, but the semantic reason why unwrapping was done is not stored in the source code. Some users write comments near unwraps to justify them, but this is easy to forget or fall out of sync with the codebase.In my experience, the
unwrap as todo!()
paradigm is much more common in application rust.This problem becomes more pronounced when one wants to go back over the code and fix all of those "todo unwraps". It's not easy to figure out whether the
.unwrap()
has a good reason for being there, or is simply a result of a hastily-written MVP.While in terms of actual program execution, nothing is different (the program will panic), the source code itself doesn't necessarily track the information why that panic was placed there.
This is also a benefit for documentation/writing code for others. A
.todo()
clearly indicates that error handling is an exercise for the reader, whereas.unwrap()
can be conflated with legitimate error handling/an assertion that this doesn't fail.Solution sketch
I imagine an implementation would look vaguely like this:
Alternatives
This could be done with ResultExt
Then everyone could import a crate that does this for them. However, I think there's value in standardising this, as its an extremely common use case. Plus, if standardised, IDEs and Rust-Analyzer could treat it better.
For example,
#[clippy::todo]
could highlight.todo()
s and so on.Other Method Names
We could call this method
.unwrap_todo()
instead, which might make it more obvious that this will panic. However, I'm conscious that these names are rather long, and having to write out.unwrap_todo()
in prototype code is unlikely to catch on as a result.I don't think there's any good reason to choose names other than
todo
, it already exists prominently in Rust.What about
.expect()
?We do already have
{Option, Result}::expect
which serves a similar-ish purpose of "unwrap with a reason".I argue that this doesn't necessarily map as nicely onto the semantics of
todo
.While this feature can be emulated with
.expect("todo")
, this is frustrating to type, easy to typo, harder to grep for and cannot be highlighted nicely by an IDE.Should this take an argument?
.expect()
takes an argument which allows more info to be strapped on about the panic.I don't think
.todo
taking an argument would be good as it makes the code harder to write, plus, I don't see what you'd ever write there.Links and related work
I initially proposed this as an RFC. I was informed that it made more sense to put this here.
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
Second, if there's a concrete solution: