Allow return more then one error type from function?


#1

From reddit topic: https://www.reddit.com/r/rust/comments/6qdkcx/what_is_in_rust_code/dkwm08v/

   fn sum(inputs: (Vec<f32> | f32)) -> u32 {
   // cut

Did you consider adding (or maybe it’s already possible in some way) option to return 2 or more error types? Woludn’t this imporove error handling? I mean… When you have function which returns two or more error types.

  • You need to wrap them with your custom error type and implement From trait to those errors

or


Representing closed trait objects as enums
Representing closed trait objects as enums
#2

Optimizing error handling ergonomics is a common subject here, so the literal answer to your question is probably “yes” as many things have been suggested which qualify as “returning more than one error type”. The strawman syntax that reddit comment used for “anonymous enums” has definitely come up multiple times, and is something I’d support, though afaik there’s no current RFC for it and by itself it’s only a very small improvement. At the moment I believe finishing/stabilizing impl Trait is more important since that’s the only way to allow changing one function’s error type without forcing the entire call stack to also change signatures, which I believe is a much bigger problem than writing the error types themselves.

That function signature confuses me though since it’s using the strawman anonymous enum syntax for its argument, not for its return value. So I’m not sure what you’re trying to suggest, or if you’re just asking what ideas have been thrown out in the past?


#3

Box<Error> is compatible with almost all error types (i.e. ones which implement std::error::Error)


#4

Box<Error> is challanging during handling errors. To do different things on different Box<Error>?


#5

This erases types, so you can’t do different things. If you need to preserve identity of errors then you need an enum.


#6
  • +100 for this

@Ixrec you’re right, example it’s not about returning… I completly missed that thing :slight_smile: The example maybe should have been more like this…

fn some_function() -> Result<(), (SomeIOError | SomeOtherError)>

So i was suggesting syntax? More idea, I think.


#7

Sounds like we’re on the same page then.

To complete my previous post, I believe all the ideas for making non-dynamically dispatched error types easier to deal with (since Box<Error> is already pretty easy if that’s what you want) fall into two categories: Generating concrete error types that can be named elsewhere, and generating anonymous error types which cannot.

I haven’t worked on any huge Rust codebases, but it seems like ergonomic generation of concrete error types is more less taken care of by macro magic libraries like error-chain. So the way to make these cases even better would be simply making macros better. And we’ve already got a pretty huge pile of macro improvements in the pipeline.

Generating anonymous error types is more interesting. The (X | Y) syntax has been frequently suggested for anonymous enums; presumably this would allow exhaustive matching in the caller despite the anonymity of the enum and its variants. The only other idea I’m aware of in this space is my “enum impl Trait” idea (see Unified Errors, a non-proliferation treaty, and extensible types) for when you don’t want/can’t have callers exhaustively matching on your error type. I believe both of these are best left until after impl Trait (at least in return position) is stable.


#8

So are You @Ixrec proposing to have 2 syntax?

  • The (X | Y): more typing but possible exhaustive matching because of explicit Errors
  • impl Error: less typing but impossible detailed matching

?

Anyway, I found out in this topic that one way or another returing-many-error-types-without-implementing-collecting-enum gonna be handled somehow, so thanks. :slight_smile:


#9

I’m saying those are the two feasible ideas I’m aware of. I haven’t personally decided yet whether I would want one or both of those syntaxes or something else entirely, since it seems premature to debate that in detail until impl Trait and macros and so on have made some more progress.