The root cause of all Errors
chainerror
also has some helper methods:
fn is_chain<T: 'static + Display + Debug>(&self) -> bool
fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>>
fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>>
fn root_cause(&self) -> Option<&(dyn Error + 'static)>
fn find_cause<U: Error + 'static>(&self) -> Option<&U>
fn find_chain_cause<U: Error + 'static>(&self) -> Option<&ChainError<U>>
fn kind<'a>(&'a self) -> &'a T
Using downcast_chain_ref::<String>()
gives a ChainError<String>
, which can be used
to call .find_cause::<io::Error>()
.
if let Some(s) = e.downcast_chain_ref::<String>() {
if let Some(ioerror) = s.find_cause::<io::Error>() {
or to use .root_cause()
, which of course can be of any type implementing std::error::Error
.
if let Some(e) = s.root_cause() {
use chainerror::*; use std::error::Error; use std::io; use std::result::Result; fn do_some_io() -> Result<(), Box<Error + Send + Sync>> { Err(io::Error::from(io::ErrorKind::NotFound))?; Ok(()) } fn func2() -> Result<(), Box<Error + Send + Sync>> { let filename = "foo.txt"; do_some_io().map_err(mstrerr!("Error reading '{}'", filename))?; Ok(()) } fn func1() -> Result<(), Box<Error + Send + Sync>> { func2().map_err(mstrerr!("func1 error"))?; Ok(()) } fn main() -> Result<(), Box<Error + Send + Sync>> { if let Err(e) = func1() { eprintln!("Error: {}", e); if let Some(s) = e.downcast_chain_ref::<String>() { if let Some(ioerror) = s.find_cause::<io::Error>() { eprintln!("caused by: std::io::Error: {}", ioerror); match ioerror.kind() { io::ErrorKind::NotFound => eprintln!("of kind: std::io::ErrorKind::NotFound"), _ => {} } } if let Some(e) = s.root_cause() { let ioerror = e.downcast_ref::<io::Error>().unwrap(); eprintln!("The root cause was: std::io::Error: {:#?}", ioerror); } } } Ok(()) } #[allow(dead_code)] mod chainerror { {{#includecomment ../src/lib.rs}} }