什么是允许失败的机制::错误代表所有错误?

问题描述 投票:3回答:2

例如:

extern crate failure;

use std::fs::File;

fn f() -> std::result::Result<(), failure::Error> 
    let _ = File::open("test")?;
    "123".parse::<u32>()?;
    Ok(())
}

什么是允许failure::Error能够表示std::io::Error,解析错误和任何其他自定义错误类型的技术?重新创建此功能的最小实现是什么?

rust
2个回答
2
投票

这里有两种机制。

第一个机制是问号运算符,returns Err(From::from(e)) when it encounters an Err(e)。如果函数返回类型是Result<T, E>,这允许我们返回F实现E的任何错误类型From<F>

failure::Error类型的文档,我们可以看到有一个generic From implementation for all types implementing the failure::Fail trait,并有一个generic implementation of Fail for all types implementing std::error::Error(只要它们也是Send + Sync + 'static)。结合起来,这允许我们返回任何实现failure::Fail特征或std::error::Error特征的类型。标准库中的所有错误类型都实现了Error特征,包括std::io::Errorstd::num::ParseIntError

这已经解释了代码编译的原因,但它没有解释转换如何在内部工作。这可以通过游戏中的第二种机制 - 特征对象来解释。 Error箱中failure类型的(略微编辑)定义如下:

struct Error {
    imp: ErrorImpl,
}

struct ErrorImpl {
    inner: Box<Inner<dyn Fail>>,
}

struct Inner<F: ?Sized + Fail> {
    backtrace: Backtrace,
    failure: F,
}

Inner类型将错误存储为使用动态调度进行方法调用的特征对象。


1
投票

failure::Error::from_boxed_compat构造函数用于将任何错误转换为failure::Error

pub fn from_boxed_compat(err: Box<dyn StdError + Sync + Send + 'static>) -> Error

这个函数接受任何将错误作为输入的结构并构造一个failure::Error https://docs.rs/failure/0.1.5/failure/struct.Error.html#impl

failure::Error在其中包含一个堆存储的trait对象,它可以存储实现Error对象的结构。

struct ErrorImpl {
    inner: Box<Inner<Fail>>,
}

此外,看起来Fail trait实现了许多错误。 ?运算符将添加一个into方法,将错误转换为failure::Error

© www.soinside.com 2019 - 2024. All rights reserved.