pub trait Error: Any {
// Required methods
fn get_span(&self) -> Span;
fn write_msg(&self, out: &mut dyn Write) -> Result;
}Expand description
An error sent to the ErrorManager
§Rationale for Error: Any
ErrorManager stores errors on a Box<dyn Error>. This is
convenient, beacause we can pass arround the same ErrorManager to
multiple compilation stages, each one defining custom error types.
Since they all implement Error, they can be emitted to the same ErrorManager.
The problem comes when we need to get back the original Error type.
For example, if we’re testing the identification stage, we know it’ll send
IdentificationError to the ErrorManager.
If Error extends Any we can upcast the &dyn Error, to &dyn Any,
and use downcast_ref to get the concrete error type
§Example
use error_manager::{Error, ErrorManager, Span};
use core::any::Any;
use core::fmt;
struct MyError(Span);
impl Error for MyError {
fn get_span(&self) -> Span { self.0 }
fn write_msg(&self, out: &mut dyn fmt::Write) -> fmt::Result {
Ok(())
}
}
fn do_something(em: &mut ErrorManager) {
// Something goes wrong...
em.emit_error(MyError(Span { offset: 12, len: 6 }));
}
let mut em = ErrorManager::new();
do_something(&mut em);
// Now we test the collected errors
let mut errors = em.errors().iter().map(|err| {
let err: &dyn Any = &**err;
err.downcast_ref::<MyError>().unwrap()
});
let expected = errors.next().unwrap();
assert_eq!(expected.0, Span { offset: 12, len: 6 });This allows us to test errors more effectively.
Another option would be to write the error we get from the ErrorManager
into a String, and test that string.
But that would require memory allocations, and more virtual calls.