Skip to main content

oxmera_core/
error.rs

1//! The error taxonomy.
2//!
3//! The design rule: invalid states are unrepresentable where the type
4//! system can afford it, and every representable failure is typed — no
5//! stringly errors on any seam.
6
7use crate::device::Device;
8use crate::dtype::DType;
9use crate::shape::Shape;
10
11/// Any failure an oxmera operation can report.
12#[derive(Debug, thiserror::Error)]
13#[non_exhaustive]
14pub enum Error {
15    /// Two shapes were required to match and did not.
16    #[error("shape mismatch: expected {expected:?}, got {got:?} in {op}")]
17    ShapeMismatch {
18        /// The shape the operation required.
19        expected: Shape,
20        /// The shape it received.
21        got: Shape,
22        /// The operation reporting the mismatch.
23        op: &'static str,
24    },
25
26    /// Two shapes cannot broadcast together.
27    #[error("cannot broadcast {lhs:?} with {rhs:?}")]
28    BroadcastIncompatible {
29        /// Left operand shape.
30        lhs: Shape,
31        /// Right operand shape.
32        rhs: Shape,
33    },
34
35    /// Two dtypes were required to match and did not.
36    #[error("dtype mismatch: expected {expected:?}, got {got:?} in {op}")]
37    DTypeMismatch {
38        /// The dtype the operation required.
39        expected: DType,
40        /// The dtype it received.
41        got: DType,
42        /// The operation reporting the mismatch.
43        op: &'static str,
44    },
45
46    /// An operation does not support a dtype at all.
47    #[error("dtype {dtype:?} is not supported by {op}")]
48    UnsupportedDType {
49        /// The offending dtype.
50        dtype: DType,
51        /// The operation that cannot carry it.
52        op: &'static str,
53    },
54
55    /// Operands live on different devices.
56    #[error("device mismatch: {lhs:?} vs {rhs:?} in {op}")]
57    DeviceMismatch {
58        /// Left operand device.
59        lhs: Device,
60        /// Right operand device.
61        rhs: Device,
62        /// The operation reporting the mismatch.
63        op: &'static str,
64    },
65
66    /// A logical index was outside a tensor's bounds.
67    #[error("index {index:?} out of bounds for shape {shape:?}")]
68    IndexOutOfBounds {
69        /// The offending index.
70        index: Vec<usize>,
71        /// The shape it was applied to.
72        shape: Shape,
73    },
74
75    /// An index had the wrong number of dimensions for the shape.
76    #[error("rank mismatch: index of rank {index_rank} against shape of rank {shape_rank}")]
77    RankMismatch {
78        /// Rank of the supplied index.
79        index_rank: usize,
80        /// Rank of the shape it was applied to.
81        shape_rank: usize,
82    },
83
84    /// No backend is registered for a device.
85    #[error("no backend available for device {device:?}")]
86    BackendUnavailable {
87        /// The device with no backend.
88        device: Device,
89    },
90
91    /// An argument was structurally invalid for the operation.
92    #[error("invalid argument to {op}: {detail}")]
93    InvalidArgument {
94        /// The operation.
95        op: &'static str,
96        /// What was wrong with the argument.
97        detail: String,
98    },
99
100    /// A backend failed internally (driver error, shader compilation, …).
101    #[error("backend failure in {op}: {detail}")]
102    Backend {
103        /// The operation.
104        op: &'static str,
105        /// The backend's own description of the failure.
106        detail: String,
107    },
108
109    /// An I/O failure while loading or saving tensors.
110    #[error("io failure in {op}: {detail}")]
111    Io {
112        /// The operation.
113        op: &'static str,
114        /// The underlying error, rendered.
115        detail: String,
116    },
117
118    /// The operation is not implemented for a combination of inputs.
119    #[error("{op} is not implemented for {detail}")]
120    NotImplemented {
121        /// The operation.
122        op: &'static str,
123        /// What combination is unsupported.
124        detail: String,
125    },
126}
127
128/// The result type every fallible oxmera API returns.
129pub type Result<T> = std::result::Result<T, Error>;