use std::error::Error;
use std::fmt;
use ir_lang::ValidationError;
use pager_lang::PagerError;
#[derive(Debug)]
#[non_exhaustive]
pub enum JitError {
InvalidIr(ValidationError),
Unsupported(&'static str),
Codegen(String),
Memory(PagerError),
}
impl fmt::Display for JitError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JitError::InvalidIr(err) => write!(f, "the function is not well-formed: {err}"),
JitError::Unsupported(what) => write!(f, "unsupported: {what}"),
JitError::Codegen(msg) => write!(f, "code generation failed: {msg}"),
JitError::Memory(err) => write!(f, "executable memory unavailable: {err}"),
}
}
}
impl Error for JitError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
JitError::InvalidIr(err) => Some(err),
JitError::Memory(err) => Some(err),
JitError::Unsupported(_) | JitError::Codegen(_) => None,
}
}
}
impl From<ValidationError> for JitError {
fn from(err: ValidationError) -> Self {
JitError::InvalidIr(err)
}
}
impl From<PagerError> for JitError {
fn from(err: PagerError) -> Self {
JitError::Memory(err)
}
}
#[cfg(test)]
#[allow(
clippy::unwrap_used,
clippy::panic,
reason = "tests assert on specific variants; a wrong one should fail loudly"
)]
mod tests {
use super::JitError;
use ir_lang::{Builder, Type};
use std::error::Error;
#[test]
fn test_invalid_ir_reports_the_validation_reason_as_source() {
let func = Builder::new("f", &[], Type::Unit).finish(); let err: JitError = func.validate().unwrap_err().into();
assert!(matches!(err, JitError::InvalidIr(_)));
assert!(err.source().is_some());
assert!(err.to_string().contains("not well-formed"));
}
#[test]
fn test_unsupported_carries_its_message_and_has_no_source() {
let err = JitError::Unsupported("a parameter has type unit");
assert!(err.to_string().contains("unit"));
assert!(err.source().is_none());
}
#[test]
fn test_codegen_message_is_preserved() {
let err = JitError::Codegen("verifier error".to_string());
assert!(err.to_string().contains("verifier error"));
assert!(err.source().is_none());
}
}