Skip to main content

aot_lang/
error.rs

1//! The failure type for an ahead-of-time compile.
2
3use codegen_lang::CodegenError;
4use core::fmt;
5use linker_lang::LinkError;
6
7/// The reason an ahead-of-time compile could not be completed.
8///
9/// A compile runs two stages — lower each function to object code, then link the
10/// objects into an image — and either stage can fail. The two variants keep the
11/// origin of a failure visible instead of flattening both into one opaque message,
12/// and each carries the underlying error so the exact cause can be inspected or
13/// reported without guesswork.
14///
15/// `AotError` implements [`Display`](fmt::Display) and
16/// [`core::error::Error`], with [`source`](core::error::Error::source) set to the
17/// wrapped error, and converts from both underlying errors so `?` propagates them
18/// directly. The enum is `#[non_exhaustive]`: a later stage that reports a new kind
19/// of failure is an additive change, so a `match` on it must keep a wildcard arm.
20///
21/// # Examples
22///
23/// A malformed function is rejected during lowering, before any linking happens:
24///
25/// ```
26/// use aot_lang::{compile, AotError};
27/// use ir_lang::{Builder, Type};
28///
29/// // Declares an int return but never returns a value.
30/// let func = Builder::new("bad", &[], Type::Int).finish();
31///
32/// assert!(matches!(compile(&func), Err(AotError::Codegen(_))));
33/// ```
34///
35/// Inspect the source through the [`Error`](core::error::Error) trait:
36///
37/// ```
38/// use aot_lang::compile;
39/// use core::error::Error;
40/// use ir_lang::{Builder, Type};
41///
42/// let func = Builder::new("bad", &[], Type::Int).finish();
43/// let err = compile(&func).unwrap_err();
44/// assert!(err.source().is_some());
45/// ```
46#[derive(Clone, PartialEq, Debug)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48#[non_exhaustive]
49pub enum AotError {
50    /// A function could not be lowered to object code. The wrapped
51    /// [`CodegenError`] names the offending block or value; the usual cause is IR
52    /// that does not pass `Function::validate`.
53    Codegen(CodegenError),
54    /// The objects could not be linked into an image. The wrapped [`LinkError`]
55    /// points at the symbol, section, or relocation involved — most often a
56    /// duplicate function name or an undefined entry point.
57    Link(LinkError),
58}
59
60impl fmt::Display for AotError {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        match self {
63            AotError::Codegen(err) => write!(f, "code generation failed: {err}"),
64            AotError::Link(err) => write!(f, "linking failed: {err}"),
65        }
66    }
67}
68
69impl core::error::Error for AotError {
70    fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
71        match self {
72            AotError::Codegen(err) => Some(err),
73            AotError::Link(err) => Some(err),
74        }
75    }
76}
77
78impl From<CodegenError> for AotError {
79    fn from(err: CodegenError) -> Self {
80        AotError::Codegen(err)
81    }
82}
83
84impl From<LinkError> for AotError {
85    fn from(err: LinkError) -> Self {
86        AotError::Link(err)
87    }
88}