Result<Option<>,E> => CustomResult

Sometimes I end up doing this:

fn foo() -> Result<Option<Something>, Error> {
}

I realize there's nothing really wrong with this, but I still can't help shake the feeling that it adds an extra layer that doesn't need to be there. I would sometimes prefer to express it like this:

enum AnotherResult<D, E> {
  HaveData(D),
  NoData,
  Err<E>
}

This is fine, apart from that ? won't work. Is there some way to implement ? support on custom result types?

Not on the stable compiler, but there is an experimental Try trait available on nightly.

2 Likes

You can always replace Error, instead of replacing Result:

enum MyError {
    NoData,
    Inner(Error),
}

impl From<Error> for MyError {
    fn from(value: Error) -> Self {
        MyError::Inner(value)
    }
}

fn foo() -> Result<Option<Something>, Error> {
    todo!()
}

fn call_foo() -> Result<Something, MyError> {
    foo()?.ok_or(MyError::NoData)
}

With feature(try_trait) on nightly, you can even implement From<std::option::NoneError> and use ? twice to convert both layers:

use std::option::NoneError;
impl From<NoneError> for MyError {
    fn from(_value: NoneError) -> Self {
        MyError::NoData
    }
}

fn call_foo() -> Result<Something, MyError> {
    Ok(foo()??)
}

Playground.

Be aware that Option::transpose and Result::transpose exist.

2 Likes