我尝试将错误类型SqlxError
转换为 并将anyhow::Error
其装箱为 ,然后恢复原始错误类型Box<dyn std::error::Error + Send + Sync + 'static>
。但是,类型信息似乎被删除了,向下转型失败了。
use std::error::Error as StdError;
use std::fmt;
#[derive(Debug)]
struct SqlxError {
message: String,
}
impl fmt::Display for SqlxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SQLx Error: {}", self.message)
}
}
impl StdError for SqlxError {}
fn main() {
// Create sqlx::Error
let sqlx_error = SqlxError {
message: "Database connection failed".to_string(),
};
// Convert to anyhow::Error
let anyhow_error = anyhow::Error::new(sqlx_error);
// Convert to Box<dyn StdError>
let boxed_error: Box<dyn StdError + Send + Sync + 'static> = anyhow_error.into();
// Now try to recover
let recovered_error = anyhow::Error::from_boxed(boxed_error);
// work well! output: SqlxError { message: "Database connection failed"}
dbg!(&recovered_error);
if let Some(sqlx_err) = recovered_error.downcast_ref::<SqlxError>() {
println!("Successfully downcast to SqlxError: {:?}", sqlx_err);
println!("Error message: {}", sqlx_err);
} else {
println!("Failed to downcast to SqlxError");
println!("Actual error: {}", recovered_error);
}
}
如下面的输出所示dbg!
,数据仍然是SqlxError
,但是downcast_ref::<SqlxError>()
失败了。
[src/main.rs:31:5] &recovered_error = SqlxError {
message: "Database connection failed",
}
我的理解是,转换anyhow::Error into Box<dyn StdError>
会消除任何包装器以及以后通过恢复原始类型的能力anyhow::Error
。
SqlxError
转换后,有什么方法可以从盒装特征对象中恢复原始错误类型吗anyhow::Error
?
调用
from_boxed
并不会Error
从 中“恢复” anyhowBox<dyn Error>
,它只是将错误包装在另一个 anyhow 中Error
。因此,最终你会得到类似这样的结果:通过阅读文档,问题始于
anyhow_error.into()
,它相当于调用.into_boxed_dyn_error()
:因此您无法
SqlxError
使用此方法恢复;背后的实际类型Box<dyn Error>
无论如何都是内部类型,您无法具体访问。还有另一种方法,
.reallocate_into_boxed_dyn_error_without_backtrace()
称为:因此,如果您需要恢复原始错误,则需要使用后者。然后,您可以
SqlxError
通过标准直接向下转型为Box<dyn Error>
: