In Rust, I believe the idiomatic way to deal with recoverable errors is to use Result. For example this function clearly is idiomatic:
fn do_work() -> Result<u64, WorkError> {...}
Of course, there are also functions that have a single, obvious, failure state, and therefore use the Option type instead. An idiomatic example would be this:
fn do_work() -> Option<u64>
This all is straightforwardly addressed in the documentation. However, I'm confused about the case where a function can fail, but has no meaningful value when successful. Compare the following two functions:
fn do_work() -> Option<WorkError>
// vs
fn do_work() -> Result<(), WorkError>
I'm just not sure which one of these is more idiomatic, or is used more often in real world Rust code. My go-to resource for questions like this is the Rust book, but I don't think this is addressed in its "Error Handling" section. I haven't had much luck with any other Rust documentation either.
Of course this seems pretty subjective, but I'm looking for authoritative sources that either state which form is idiomatic, or on why one form is superior (or inferior) to the other. (I'm also curious how the convention compares to other languages that heavily utilize "errors as values", like Go and Haskell.)
Use fn do_work() -> Result<(), WorkError>
.
Result<(), WorkError>
means you want the work to be done, but it may fail.
Option<WorkError>
means you want to get an error, but it may be absent.
You probably want the work to be done but not to get an error when you write do_work()
, so Result<(), WorkError>
is the better choice.
I would expect Option<WorkError>
only be used in cases like fn get_last_work_error() -> Option<WorkError>
.