Какой самый идиоматичный способ объединить два типа ошибок? - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть тип Foo, методы которого могут "вызывать" ошибки связанного типа Foo::Err.

pub trait Foo {
    type Err;

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

У меня есть другая черта Bar с методом, предназначенным для обработки Foo.Bar может выдавать собственные ошибки (указанные ассоциированным типом Bar::Err), но также могут встречаться ошибки, генерируемые Foo, который он обрабатывает.

Я вижу два способа обработки, но я не знаю, какой из них наиболее идиоматичен для Rust.

Первый встраивает результат в результат:

pub trait Bar1 {
    type Err;

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

Второй объединяет два типа ошибокв специальное перечисление:

pub trait Bar2 {
    type Err;

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

Второй выглядит семантически чище, но создает некоторые препятствия для обработки дополнительного перечисления.

детская площадка

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Как правило, вы не выполняете «слияние», а вместо этого используете вложенные ошибки, например:

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)
    }
}
0 голосов
/ 21 сентября 2018

Вы должны использовать объект черты Error, и вы возвращаете первую ошибку, с которой вы столкнулись:

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

или реализуете свою черту следующим образом:

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

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

Если вы действительно хотите, чтобы у вас были две ошибки (но это странно, потому что одной ошибки достаточно, чтобы процесс не был в порядке), вы можете использовать ящик типа failure, чтобы создать ошибкуtrace ".

В качестве общего совета не следует забывать использовать черты из std, чтобы добавить больше семантики в ваш код.

...