gpt4 book ai didi

rust - 如何在 Rust 中为具体的错误类型和 Box 实现 From?

转载 作者:行者123 更新时间:2023-11-29 07:57:59 24 4
gpt4 key购买 nike

这是我的测试代码:

use std::error::Error;
use std::fmt;

struct Handler {
error: String
}

#[derive(Debug)]
struct SpecificError;

impl fmt::Display for SpecificError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SpecificError")
}
}

impl Error for SpecificError {}

impl<E: Error> From<E> for Handler {
fn from(e: E) -> Self {
Handler { error: format!("{}", e) }
}
}

fn fail1() -> Result<(), SpecificError> {
Err(SpecificError)
}

fn fail2() -> Result<(), Box<Error>> {
Err(Box::new(SpecificError))
}

fn handler() -> Result<(), Handler> {
fail1()?;
fail2()?;
Ok(())
}

调用fail1()很好,但是调用 fail2()不编译:

error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time
--> src/main.rs:35:5
|
35 | fail2()?;
| ^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn std::error::Error`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<dyn std::error::Error>`
= note: required because of the requirements on the impl of `std::convert::From<std::boxed::Box<dyn std::error::Error>>` for `Handler`
= note: required by `std::convert::From::from`

我同意编译器 dyn Error在编译时没有已知的大小,但我不明白为什么这是相关的,因为我试图转换的类型是 Box<dyn Error> ,它在编译时确实有一个已知的大小。

最佳答案

TL;DR:我很确定你不能以通用的方式。

I don't understand why that's relevant, since the type I'm attempting to convert from is a Box<dyn Error>, which does have a size known at compile time.

那不是它提示的地方。再看报错信息(稍微清理了一下):

the trait `Sized` is not implemented for `dyn Error`
required because of the requirements on the impl of `Error` for `Box<dyn Error>`
required because of the requirements on the impl of `From<Box<dyn Error>>` for `Handler`
required by `From::from`

第二行很重要。这是您问题的简单重现:

use std::error::Error;

fn example<E: Error>() {}

fn main() {
example::<Box<dyn Error>>();
}
error[E0277]: the size for values of type `dyn std::error::Error` cannot be known at compilation time
--> src/main.rs:6:5
|
6 | example::<Box<dyn Error>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn std::error::Error`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: required because of the requirements on the impl of `std::error::Error` for `std::boxed::Box<dyn std::error::Error>`
note: required by `example`
--> src/main.rs:3:1
|
3 | fn example<E: Error>() {}
| ^^^^^^^^^^^^^^^^^^^^^^

Error只有implemented for Box<T> when T is Sized 并实现 Error本身:

impl<T: Error> Error for Box<T> {
// ...
}

换句话说,Box<dyn Error> 不执行Error .

有人可能认为您可以添加 From 的第二个实现对于 Box<Error> ,但这是不允许的:

upstream crates may add new impl of trait `std::error::Error` for type
`std::boxed::Box<(dyn std::error::Error + 'static)>` in future versions

我必须提供的最佳替代方案是实现 From对于您需要支持的每个具体类型:

impl From<SpecificError> for Handler {
fn from(e: SpecificError) -> Self {
Handler { error: format!("{}", e) }
}
}

impl From<Box<dyn Error>> for Handler {
fn from(e: Box<dyn Error>) -> Self {
Handler { error: format!("{}", e) }
}
}

宏可以减少这里的样板文件。

关于rust - 如何在 Rust 中为具体的错误类型和 Box<Error> 实现 From?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55122541/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com