What is the most idiomatic way to merge two error types?

◇◆丶佛笑我妖孽 提交于 2020-01-16 05:35:06

问题


I have a type Foo whose methods may "raise" errors of an associated type Foo::Err.

pub trait Foo {
    type Err;

    fn foo(&mut self) -> Result<(), Self::Err>;
}

I have another trait Bar with a method intended to process a Foo. Bar may issue errors of its own (specified by an associated type Bar::Err), but it may also encounter errors generated by the Foo it is processing.

I can see two ways to do handle, but I don't know which one would be the most idiomatic to Rust.

The first one embeds a result in a result:

pub trait Bar1 {
    type Err;

    fn bar<F: Foo>(&mut self, foo: F) -> Result<Result<F, F::Err>, Self::Err>;
}

The second one merges the two error types into a dedicated enum:

pub trait Bar2 {
    type Err;

    fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Choice<F::Err, Self::Err>>;
}

The second one looks semantically cleaner, but creates some hurdle for handling the additional enum.

playground


回答1:


Typically you don't do a "merge", but instead use nested errors, like this.

enum IntError {
    Overflow,
    Underflow
}

enum StrError {
    TooLong,
    TooShort,
}

enum GenericError {
    Int(IntError),
    Str(StrError),
}

impl From<IntError> for GenericError {
    fn from(e: IntError) -> Self {
        GenericError::Int(e)
    }
}

impl From<StrError> for GenericError {
    fn from(e: StrError) -> Self {
        GenericError::Str(e)
    }
}



回答2:


You should use a trait object Error, and you return the first error that you encounter:

pub trait Bar {
    fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Box<dyn Error>>;
}

or implement your trait like this:

impl Bar for MyType {
    type Err = Box<dyn Error>;

    fn bar<F: Foo>(&mut self, foo: F) -> Result<F, Self::Err>;
}

If you really want to have your two errors (but this is strange because one error suffices to make the process not ok), you can use a crate like failure to create an "error trace".

As a general advice, you should not forget to use the traits from std to add more semantic to your code.



来源:https://stackoverflow.com/questions/52438988/what-is-the-most-idiomatic-way-to-merge-two-error-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!