Error handling 将错误从“try_into()”强制转换为自定义错误

Error handling 将错误从“try_into()”强制转换为自定义错误,error-handling,rust,Error Handling,Rust,这是我作为库的一部分使用的一些锈迹代码的简化版本: 使用std::convert::TryInto; 使用std::result; 使用thisrerror::Error; 发布类型Result=Result::Result; #[导出(错误,调试)] pub enum MyError{ #[错误(透明)] 板条箱错误(#[来自]板条箱错误::错误), } pub fn my_function()->结果{ //可能会返回MyError::CrateXError 板条箱:做点什么?; //实际上

这是我作为库的一部分使用的一些锈迹代码的简化版本:

使用std::convert::TryInto;
使用std::result;
使用thisrerror::Error;
发布类型Result=Result::Result;
#[导出(错误,调试)]
pub enum MyError{
#[错误(透明)]
板条箱错误(#[来自]板条箱错误::错误),
}
pub fn my_function()->结果{
//可能会返回MyError::CrateXError
板条箱:做点什么?;
//实际上,从数据库中获取'x'
设x:Vec=Vec![1,2,3,4];
设x:[u8;4]=x.试着打开();
println!(“{:?}”,x);
好(())
}
这里我使用虚构的板条箱
cratex
进行演示,它实现了自己的
Error
类型。我正在
MyError
中使用
thisrerror
中的
Error
宏处理此问题

我的目标是将
try\u into().unwrap()
替换为
try\u into()?
,并将可能的错误作为
MyError
的一部分进行处理

我尝试了以下方法:

使用std::convert::TryFrom;
#[导出(错误,调试)]
pub enum MyError{
#[错误(透明)]
板条箱错误(#[来自]板条箱错误::错误),
#[错误(透明)]
TryIntoError(#[from]::Error),
}
但是,我得到了以下错误:()

error[E0119]:trait`std::convert::From`for type`的冲突实现错误`
我的问题是:

  • 这是处理
    try_into()
    中的错误的惯用方法,还是我应该以不同的方式来处理错误,例如,只是将其展开?在我的实际应用程序中,
    Vec
    应该是正确的长度,但如果它来自的数据库被最终用户损坏,则可能不是
  • 如果这是惯用的,那么使用
    thisrerror
    中的
    Error
    宏,我应该使用什么正确的语法来完成这项工作

  • 我不知道为什么会出现“冲突的实现”错误,也没有足够的信息来说明(因为您没有提供具体的可编译代码来进一步研究)

    也就是说,这有一个更深层次的问题:

    #[错误(透明)]
    TryIntoError(#[from]::Error),
    
    TryFrom
    的结果“error”类型就是向量本身。这样做的目的是,如果您希望从转换失败中恢复,那么向量没有被消耗,您可以用它做进一步的事情。如果您只是让faulure传播,那么您可能不想将四个字节的向量交给调用者。而且,
    #[error(transparent)]
    无法工作,因为
    Vec
    没有实现
    std::error::error

    因此,对于
    try\u-into
    失败的情况,您可能不应该将其实现为自动错误转换,而是使用
    map\u-err)
    明确选择解释:

    
    #[导出(错误,调试)]
    pub enum MyError{
    #[错误(透明)]
    板条箱错误(#[来自]板条箱错误::错误),
    #[错误(“损坏的数据库条目”)]
    腐败的数据,
    }
    ...
    设x:[u8;4]=x.尝试进入()
    .map_err(| | MyError::CorruptedData)?;
    
    这不仅使工作更容易:它还使代码的实现细节和它呈现给调用方的接口之间有了更好的抽象。您的呼叫者不关心您是否正在使用
    try_into
    :他们关心数据库中的数据出现问题的信息。在一个完全充实的实现中,
    CorruptedData
    可能有一个字段来存储标识哪个记录已损坏的信息,可能还有哪个字段,但最常用的信息是存在一个坏记录,从而指示恢复方法(例如,删除记录、跳过记录、从备份重新加载记录或告诉用户尝试修复记录)


    类似地,拥有一个
    CrateXError
    可能是一个好主意,也可能不是一个好主意,这取决于它使用的
    cratex
    是否是关于你的板条箱的保证API特性,以及
    cratex
    是否与你正在做的事情相关我的意思是,当您更改实现时,会对您的用户进行更多破坏性的更改。(另一方面,如果您正在编写一个二进制文件或库供自己使用,那么您不必担心类型的稳定性,只需设计任何便于错误处理的内容即可。)

    我不确定您为什么会得到一个“冲突实现”错误,并且没有足够的信息可以说明(因为您没有提供具体的可编译代码来进一步研究)

    也就是说,这有一个更深层次的问题:

    #[错误(透明)]
    TryIntoError(#[from]::Error),
    
    结果是“错误”输入from
    TryFrom
    就是向量本身。这样做的目的是,如果您希望从转换失败中恢复,那么向量没有被消耗,您可以用它做进一步的事情。如果您只是让faulure传播,您可能不想只将四个字节的向量交给调用者。并且,
    #[错误](透明)
    无法工作,因为
    Vec
    未实现
    std::error::error

    因此,对于
    try\u-into
    失败的情况,您可能不应该将其实现为自动错误转换,而是使用
    map\u-err)
    明确选择解释:

    
    #[导出(错误,调试)]
    pub enum MyError{
    #[错误(透明)]
    板条箱错误(#[来自]板条箱错误::错误),
    #[错误(“损坏的数据库条目”)]
    腐败的数据,
    }
    ...
    设x:[u8;4]=x.尝试进入()
    .map_err(| | MyError::CorruptedData)?;
    
    这不仅使工作更容易:它还使代码的实现细节和它呈现给调用方的接口之间有了更好的抽象
    error[E0119]: conflicting implementations of trait `std::convert::From<Error>` for type `Error`