Trait Error

Source
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.

Required Methods§

Source

fn get_span(&self) -> Span

Source

fn write_msg(&self, out: &mut dyn Write) -> Result

Implementors§