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}