Propagating (`?`) `Result` from function that returns `Option<Result>`

I think this is not possible, based on

One current restriction is that you cannot use ? for both in the same function, as the return type needs to match the type you use ? on. In the future, this restriction will be lifted.

But to be sure, I'm asking here...

I have a function that returns Option<Result<T, E>>. It is an implementation of Iterator, but that doesn't matter for now. It calls a function that might fail, and thus returns Result<T, E>. Something like:

fn helper() -> Result<T, E> {
    // ...

fn next() -> Option<Result<T, E>> {

Now, I want next() to fail with Some(Err(E)) if helper() returns Err(E). Of course I can do this the long way:

if let Err(e) = helper() {
    return Some(Err(e));

But I'd like to do this using the ? operator. But if I do this raw, the compiler complains (obviously):

error[E0277]: `?` couldn't convert the error to `std::option::NoneError`
 --> src/
8 | fn next() -> Option<Result<(), ()>> {
  |              ---------------------- expected `std::option::NoneError` because of this
9 |     helper()?;
  |             ^ the trait `std::convert::From<()>` is not implemented for `std::option::NoneError`
  = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
  = note: required by `std::convert::From::from`
help: consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`
9 |     helper().ok()?;
  |             ^^^^^

I can use .ok(), but then the error E is discarded:

helper().ok()?; // Err(e) becomes None instead of Some(Err(e))

I can also wrap it with Some(...), but then the ? operator applies to the Some(...) never returns from the function:

Some(helper())?; // The ? operator  sees Some(...) and never returns

I thought about implementing std::ops::Try, but:

  1. Couldn't figure out how to do this properly.
  2. I think it's not possible since it's cross-crate impl.

Is this possible (I'm not afraid of using nightly Rust)?

Thanks in advance.

You can make a helper function which returns Result<Option<T>, E> and .transpose() it into Option<Result<T, E>>.

Actually, I don't have to - I can just refactor the helper function to return Option<Result<T, E>>.

But how do I use the ? operator to return in case of an error?

To ? to reutrn on error you need to have Result as the outer type. That's why I've recommended to use .transpose().

1 Like

The problem is that as I already said it's an iterator, and the next()'s function signature is Option<T> (in fact, in the beginning I implemented it like you suggested).

Ok, I'll explain in more detail. You can write another helper function which returns Result<Option<T>, E>, write most logics in it, and within the fn next() call this helper function and .transpose() its result.


Hmm... Cool. Thanks.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.