我有一个类型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>>;
}
第二个在语义上看起来更简洁,但为处理其他枚举创建了一些障碍。
答案 0 :(得分:2)
您应该使用特征对象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
之类的条板箱来创建“错误跟踪”。
作为一般建议,您不应忘记使用std
中的特征为代码添加更多语义。
答案 1 :(得分:1)
通常,您不执行“合并”,而是使用嵌套错误,例如。
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)
}
}