use std::fmt; /// Shared object/bytecode/execution errors. The established VmError name is /// retained for embedders; defining it here avoids a dependency on the VM. #[derive(Debug, Clone, PartialEq, Eq)] pub enum VmError { ForeignHandle, InvalidHandle, IdentityExhausted, RefCountOverflow, NoOwnedReference, AttributeNotFound(String), UnsupportedOperation(&'static str), InvalidArgument(&'static str), ObjectKindMismatch(&'static str), TraitViolation { capability: String, method: String, reason: &'static str, }, OverrideViolation { definition: String, method: String, reason: &'static str, }, UnknownAnnotation(String), TypeMismatch { function: String, position: String, expected: String, actual: String, }, EmptyCell, InvalidBytecode { offset: usize, reason: &'static str, }, UnboundLocal(String), NameNotFound(String), ArgumentCount { name: String, required: usize, maximum: usize, provided: usize, }, ExecutionLimit(&'static str), } impl fmt::Display for VmError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::ForeignHandle => f.write_str("handle belongs to another VM"), Self::InvalidHandle => f.write_str("handle does not identify a live object"), Self::IdentityExhausted => f.write_str("process-local VM identities exhausted"), Self::RefCountOverflow => f.write_str("object reference count exhausted"), Self::NoOwnedReference => f.write_str("no external strong reference to release"), Self::AttributeNotFound(name) => write!(f, "attribute not found: {name}"), Self::UnsupportedOperation(operation) => { write!(f, "object does not support {operation}") } Self::InvalidArgument(message) => f.write_str(message), Self::ObjectKindMismatch(expected) => write!(f, "expected {expected} object"), Self::TraitViolation { capability, method, reason, } => write!(f, "trait {capability} method {method}: {reason}"), Self::UnknownAnnotation(name) => { write!(f, "unknown or invalid type annotation: {name}") } Self::OverrideViolation { definition, method, reason, } => write!(f, "override {definition}.{method}: {reason}"), Self::TypeMismatch { function, position, expected, actual, } => write!( f, "{function} {position} expects {expected}, received {actual}" ), Self::EmptyCell => f.write_str("cell is empty"), Self::InvalidBytecode { offset, reason } => { write!(f, "invalid bytecode at code unit {offset}: {reason}") } Self::UnboundLocal(name) => write!(f, "local variable is unbound: {name}"), Self::NameNotFound(name) => write!(f, "name not found: {name}"), Self::ArgumentCount { name, required, maximum, provided, } => write!( f, "{name} expects {required}..={maximum} positional arguments, received {provided}" ), Self::ExecutionLimit(limit) => write!(f, "execution limit reached: {limit}"), } } } impl std::error::Error for VmError {}