简体   繁体   English

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

[英]How to implement From trait for custom error types?

I am currently trying to write a custom error type for my CLI application. 我目前正在尝试为CLI应用程序编写自定义错误类型。 Now I want to write an implementation of the From trait so my custom error type can wrap all third party library errors that can occur. 现在,我想编写From特性的实现,以便我的自定义错误类型可以包装可能发生的所有第三方库错误。

The error enum: 错误枚举:

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

Now I want to implement the From Trait for the git2::Error from the git2 library to use the ? 现在我想为git2库中的git2::Error实现From Trait以使用? operator in my functions. 操作员在我的职能。

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

But when I try to use my custom error to map an error like this: 但是,当我尝试使用自定义错误来映射这样的错误时:

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

I am getting the following error message: 我收到以下错误消息:

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

Can anyone help me to understand why I am getting this error and how to solve this problem ? 谁能帮助我了解为什么会出现此错误以及如何解决此问题?

Any help is appreciated 任何帮助表示赞赏

You've mixed up a whole bunch of concepts; 您混合了很多概念; let's see if we can walk through this together and hopefully clarify all of it. 让我们看看我们是否可以一起解决所有问题,并希望将其全部澄清。

The git2 crate has its own error type, that you no doubt have discovered. git2板条箱有自己的错误类型,您无疑已经发现了。 Your definition of custom errors is fine as well. 您对自定义错误的定义也很好。

The issue is twofold: 问题是双重的:

  1. Your implementation of From<_> 您对From<_>

From<E> allows you to transform a type from one type to another by providing the translation function ( from() ). From<E>允许您通过提供翻译功能( from() )将类型从一种类型转换为另一种类型。

Your implementation of this was the following: 您对此的实现如下:

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

Brackets in rust aren't added where they should not be, and this is precisely one of the cases where this is the case. 不会在不应有的地方添加rust支架,这正是这种情况的一种。 By doing this, you've actually defined From<(T)> , not From<T> . 这样,您实际上定义了From<(T)>而不是From<T> That's mistake #1. 这是错误的#1。

The correct implementation simply drops the brackets: 正确的实现只是将方括号括起来:

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

Not an error per se, but a completely unnecessary operation as the ? 本质上不是错误,而是作为?完全不必要的操作? operator handles it for you. 操作员会为您处理。 There is no need for the map_err() , and if there was you'd be using into() rather than hard-calling the type (which should already be defined as a type in your function). 不需要map_err() ,如果有的话,您将使用into()而不是硬调用类型(该类型应该已经在您的函数中定义为类型)。

Remember, the whole point of conversion traits is to define them so you don't have to explicitly call them . 请记住,转换特性的全部要点是定义它们, 因此您不必显式调用它们

A final "demo" version of the code in working order could look like this: 工作顺序的最终“演示”版本代码如下所示:

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!");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM