如何为自定义错误类型实现From trait?

时间:2019-09-15 09:43:44

标签: error-handling rust

我当前正在尝试为CLI应用程序编写自定义错误类型。现在,我想编写一个From特征的实现,以便我的自定义错误类型可以包装所有可能发生的第三方库错误。

错误枚举:

#[derive(Debug)] // Allow the use of "{:?}" format specifier
pub enum CustomError {
    Git(git2::Error),
    Other
}

现在,我想为From库中的git2::Error实现git2特性,以在函数中使用?运算符。

impl From<(git2::Error)> for CustomError {
    fn from(cause: git2::Error) -> Self {
        CustomError::Git(cause)
    }
}

但是当我尝试使用自定义错误来映射这样的错误时:

let repo = Repository::open(path).map_err(|err| CustomError::Git)?;

我收到以下错误消息:

the trait `std::convert::From<fn(git2::error::Error) -> error::CustomError {error::CustomError::Git}>` is not implemented for `error::CustomError `

任何人都可以帮助我了解我为什么会收到此错误以及如何解决此问题吗?

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

您混合了很多概念;让我们看看我们是否可以一起解决所有问题,并希望将其全部澄清。

git2板条箱有其自己的错误类型,您无疑已经发现了它。您对自定义错误的定义也很好。

问题是双重的:

  1. 您对From<_>的实现

From<E>允许您通过提供翻译功能(from())将类型从一种类型转换为另一种类型。

您的实现如下:

impl From<(git2::Error)> for CustomError {
    fn from(cause: git2::Error) -> Self {
        CustomError::Git(cause)
    }
}

rust中的括号未添加到不应添加的位置,这正是这种情况之一。这样,您实际上定义了From<(T)>,而不是From<T>。那是错误#1。

正确的实现只需将括号括起来:

impl From<git2::Error> for CustomError {
    fn from(cause) -> Self {
        CustomError::Git(cause)
    }
}
  1. 您的实际转化

本质上不是错误,而是?运算符为您处理的完全不必要的操作。不需要map_err(),如果有的话,您将使用into()而不是硬调用该类型(该类型应该已经在您的函数中定义为类型)。

请记住,转换特征的全部要点是定义它们,因此您不必显式地调用它们

按工作顺序的代码的最终“演示”版本可能如下所示:

extern crate git2;
use git2::Repository;

#[derive(Debug)] // Allow the use of "{:?}" format specifier
pub enum CustomError {
    Git(git2::Error),
    Other
}
impl From<(git2::Error)> for CustomError {
    fn from(cause: git2::Error) -> Self {
        CustomError::Git(cause)
    }
}
fn test() -> Result<(), CustomError> {
    let path = "foo";
    let output = Repository::open(path)?;
    Ok(())
}
fn main() {
    println!("Hello, world!");
}