Can ? be used to auto-convert the Err variant of Result?

Hi. Given two types A and B that implement the same trait T, is it possible to rewrite the below snippet so that ? can be used (e.g. let x = r?;)?

fn test() -> impl T {
  let r: Result<A, B> = Err(B);
  let x = match r {
    Ok(x) => x,
    Err(e) => {
      return e.stuff();
    }
  };
  // ...
  x
}

(in the above example, T defines the function stuff()).

Thank you.

This doesn't seem to have anything to do with Result or ? – it looks like you want to return two different concrete types from a function returning an impl Trait. That is not possible for technical reasons – a function must have a single return type, but impl Trait in return position is not a type (like dyn Trait is). It is not magic: it is a placeholder for a specific type of which the identity is intentionally hidden from the programmer, but known to the compiler.

If you want to return one of many specific types, you have a couple of other options:

  • Return Box<dyn Trait>. This imposes dynamic dispatch and a heap allocation, and only works if your trait is object safe.
  • Return an enum implementing the trait. For example, you could just impl Trait for Result<A, B> directly if Trait is defined by your code.
2 Likes

Thank you for your response, @H2CO3 . In my code, I want to be able to call multiple functions that either return a response that allows me to continue processing or return an error that should be returned immediately. I can also change my code to return a Result that can then be processed. I just want to know whether it is possible to avoid this Result when both variants implement the same trait.

Sorry but I'm not sure what else you are asking, exactly. My previous answer confirms that it is not possible to return multiple different types from a function, and impl Trait is no exception. Whether or not you are extracting values from a Result, a function must have a single return type. You can still return an enum with several variants other than Result and implement the trait for it by forwarding to its wrapped types.

The early return you get from applying a ? to a Result is always a Result.

1 Like