Estou tentando recuperar o tipo de erro original SqlxError
após convertê-lo anyhow::Error
e, em seguida, compactá-lo como Box<dyn std::error::Error + Send + Sync + 'static>
. No entanto, as informações de tipo parecem ser apagadas e o downcasting falha.
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);
}
}
Como visto na dbg!
saída abaixo, os dados ainda são um SqlxError
, mas downcast_ref::<SqlxError>()
falham.
[src/main.rs:31:5] &recovered_error = SqlxError {
message: "Database connection failed",
}
Meu entendimento é que a conversão anyhow::Error into Box<dyn StdError>
apaga o wrapper anyhow e qualquer capacidade de recuperar posteriormente o tipo original por meio de anyhow::Error
.
Existe alguma maneira de recuperar o tipo de erro original SqlxError
do objeto de característica em caixa após a conversão de anyhow::Error
?
A chamada
from_boxed
não "recupera" o anyhowError
doBox<dyn Error>
, apenas encapsula o erro em outro anyhowError
. Então, você terminaria com algo assim:Lendo a documentação, o problema começa com
anyhow_error.into()
, é equivalente a chamar.into_boxed_dyn_error()
o que diz:Então você não pode recuperar
SqlxError
usando esse método; o tipo real por trás doBox<dyn Error>
é um tipo interno que você não tem como acessar concretamente.Existe outro método chamado
.reallocate_into_boxed_dyn_error_without_backtrace()
que diz:Portanto, se você precisar recuperar o erro original, precisará usar este último. Depois, faça o downcast diretamente para
SqlxError
o padrãoBox<dyn Error>
: