Skip to main content

tenferro_runtime/
error.rs

1//! Error types for the tenferro runtime crate.
2//!
3//! # Examples
4//!
5//! ```rust
6//! use tenferro_runtime::error::Error;
7//!
8//! let err = Error::InvalidSubscripts("bad label".into());
9//! assert!(err.to_string().contains("bad label"));
10//! ```
11
12use tenferro_tensor::DType;
13
14/// Errors produced by einsum, eval, and other tenferro operations.
15///
16/// # Examples
17///
18/// ```rust
19/// use tenferro_runtime::error::Error;
20///
21/// let err = Error::InvalidSubscripts("rank mismatch".into());
22/// ```
23#[derive(Debug, thiserror::Error)]
24pub enum Error {
25    /// Einsum subscript string is invalid or cannot be parsed.
26    #[error("invalid subscripts: {0}")]
27    InvalidSubscripts(String),
28
29    /// Contraction optimization failed (shape mismatch, bad path, etc.).
30    #[error("contraction error: {0}")]
31    ContractionError(String),
32
33    /// A required input tensor is missing from the inputs map.
34    #[error("missing input: {0}")]
35    MissingInput(String),
36
37    /// Reverse-mode gradient requires a scalar output.
38    #[error("grad requires a scalar output, got shape {shape:?}")]
39    NonScalarGrad { shape: Vec<usize> },
40
41    /// Runtime tensor execution failed in the backend layer.
42    #[error(transparent)]
43    TensorRuntime(#[from] tenferro_tensor::Error),
44
45    /// A `TracedTensor` passed to graph-executor input bindings is not a
46    /// placeholder (has attached data).
47    #[error(
48        "binding #{binding_index} is not a placeholder; \
49         only tensors built via input_concrete_shape / input_symbolic_shape \
50         can be bound"
51    )]
52    UnexpectedBinding { binding_index: usize },
53
54    /// A placeholder appearing in the graph has no binding supplied.
55    #[error("placeholder {input_key} has no runtime input binding")]
56    UnboundPlaceholder { input_key: String },
57
58    /// The same placeholder was bound more than once in the `bindings` slice.
59    #[error("placeholder {input_key} was bound more than once")]
60    DuplicateBinding { input_key: String },
61
62    /// A binding tensor's dtype does not match the placeholder's dtype.
63    #[error("binding dtype mismatch for placeholder: expected {expected:?}, got {actual:?}")]
64    PlaceholderDtypeMismatch { expected: DType, actual: DType },
65
66    /// A binding tensor's shape does not match an `input_concrete_shape`
67    /// placeholder's fixed shape.
68    #[error(
69        "binding shape mismatch for concrete-shape placeholder: \
70         expected {expected:?}, got {actual:?}"
71    )]
72    PlaceholderShapeMismatch {
73        expected: Vec<usize>,
74        actual: Vec<usize>,
75    },
76
77    /// A binding tensor's rank does not match an `input_symbolic_shape`
78    /// placeholder's declared rank.
79    #[error(
80        "binding rank mismatch for symbolic-shape placeholder: \
81         expected rank {expected}, got rank {actual}"
82    )]
83    PlaceholderRankMismatch { expected: usize, actual: usize },
84
85    /// Operation attempted to mix tensors from different eager contexts.
86    #[error(
87        "tensors belong to different eager AD contexts ({lhs} vs {rhs}); \
88         detach into the target context before combining them"
89    )]
90    ContextMismatch { lhs: ContextId, rhs: ContextId },
91
92    /// Traced graph construction rejected an invalid operation configuration.
93    #[error("{op}: invalid traced graph build: {message}")]
94    InvalidGraphBuild {
95        /// Public operation name.
96        op: &'static str,
97        /// Validation failure details.
98        message: String,
99    },
100
101    /// Lowering rejected an inconsistent compiled graph.
102    #[error("invalid compiled graph: {message}")]
103    InvalidCompiledGraph {
104        /// Validation failure details.
105        message: String,
106    },
107
108    /// An unexpected internal error.
109    #[error("internal error: {0}")]
110    Internal(String),
111}
112
113/// Opaque identifier for an eager AD runtime, used in [`Error::ContextMismatch`].
114#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
115pub struct ContextId(usize);
116
117impl ContextId {
118    #[doc(hidden)]
119    pub fn from_ptr<T>(ptr: *const T) -> Self {
120        Self(ptr as usize)
121    }
122}
123
124impl std::fmt::Display for ContextId {
125    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126        write!(f, "ctx@{:x}", self.0)
127    }
128}
129
130/// Result type alias for tenferro operations.
131pub type Result<T> = std::result::Result<T, Error>;