1use snafu::Snafu;
2use svod_ir::shape::Shape;
3
4#[derive(Debug, Snafu)]
5#[snafu(visibility(pub))]
6pub enum Error {
7 #[snafu(display("IR operation error: {source}"))]
11 UOp { source: svod_ir::Error },
12
13 #[snafu(display("Tensor shape is unknown (symbolic or not yet inferred)"))]
17 ShapeUnknown,
18
19 #[snafu(display("Operation '{operation}' does not support symbolic shapes"))]
20 SymbolicShapeUnsupported { operation: String },
21
22 #[snafu(display("Axis {axis} is out of range for tensor with {ndim} dimensions"))]
23 AxisOutOfRange { axis: isize, ndim: usize },
24
25 #[snafu(display("Permutation length mismatch: expected {expected} axes, got {got}"))]
26 PermutationLengthMismatch { expected: usize, got: usize },
27
28 #[snafu(display("Invalid permutation: axes {axes:?} is not a valid permutation"))]
29 InvalidPermutation { axes: Vec<isize> },
30
31 #[snafu(display("Multiple -1 dimensions in reshape are not allowed"))]
32 MultipleInferDimensions,
33
34 #[snafu(display("Negative dimension {dim} is not allowed (except -1 for inference)"))]
35 NegativeDimension { dim: isize },
36
37 #[snafu(display("Reshape size mismatch during {operation}"))]
38 ReshapeSizeMismatch { operation: String },
39
40 #[snafu(display(
41 "Expand dimension mismatch: current shape has {current_dims} dims, target has {target_dims} dims"
42 ))]
43 ExpandDimensionMismatch { current_dims: usize, target_dims: usize },
44
45 #[snafu(display("Cannot squeeze dimension {dim}: size is {size}, not 1"))]
46 SqueezeDimensionNotOne { dim: usize, size: usize },
47
48 #[snafu(display("{op} requires exactly {expected}D input, got {actual}D"))]
52 NdimExact { op: &'static str, expected: usize, actual: usize },
53
54 #[snafu(display("{op} requires at least {min}D input, got {actual}D"))]
55 NdimMinimum { op: &'static str, min: usize, actual: usize },
56
57 #[snafu(display("{op}: {lhs_name} ({lhs}) must be divisible by {rhs_name} ({rhs})"))]
58 Divisibility { op: &'static str, lhs_name: &'static str, lhs: usize, rhs_name: &'static str, rhs: usize },
59
60 #[snafu(display("{op}: {param} = {value} is invalid, expected {constraint}"))]
61 ParamRange { op: &'static str, param: &'static str, value: String, constraint: &'static str },
62
63 #[snafu(display("Cannot specify both 'dtype' and 'promote=true' in reduction operation"))]
67 ConflictingReductionOptions,
68
69 #[snafu(display(
73 "Matrix multiplication requires tensors with at least 1 dimension, got lhs: {lhs_dims}D, rhs: {rhs_dims}D"
74 ))]
75 DotDimensionError { lhs_dims: usize, rhs_dims: usize },
76
77 #[snafu(display(
78 "Matrix multiplication shape mismatch: cannot multiply shapes {lhs_shape:?} and {rhs_shape:?} (contraction dimension mismatch)"
79 ))]
80 DotShapeMismatch { lhs_shape: Box<Shape>, rhs_shape: Box<Shape> },
81
82 #[snafu(display(
86 "Cannot broadcast to fewer dimensions: tensor has {from_dims} dimensions, target has {to_dims} dimensions"
87 ))]
88 BroadcastFewerDimensions { from_dims: usize, to_dims: usize },
89
90 #[snafu(display(
91 "Incompatible dimension {dim} for broadcasting: cannot broadcast size {from_size} to size {to_size}"
92 ))]
93 BroadcastIncompatible { dim: usize, from_size: usize, to_size: usize },
94
95 #[snafu(display("Failed to render kernel: {source}"))]
99 RenderKernel { source: svod_device::Error },
100
101 #[snafu(display("Failed to compile kernel: {source}"))]
102 CompileKernel { source: svod_device::Error },
103
104 #[snafu(display("Rangeify failed: {source}"))]
108 Rangeify { source: svod_ir::Error },
109
110 #[snafu(display("Optimization error: {source}"))]
111 Optimize { source: svod_schedule::OptError },
112
113 #[snafu(display("No kernels found after scheduling pipeline"))]
114 NoKernelsFound,
115
116 #[snafu(display("Schedule contains dependency cycles"))]
117 DependencyCycles,
118
119 #[snafu(display("Empty schedule"))]
120 EmptySchedule,
121
122 #[snafu(display("Batch output count mismatch: expected {expected}, got {actual}"))]
123 BatchOutputMismatch { expected: usize, actual: usize },
124
125 #[snafu(display("Expected CALL operation"))]
126 ExpectedCallableOp,
127
128 #[snafu(display("Execution failed: {source}"))]
132 Execution { source: svod_runtime::Error },
133
134 #[snafu(display("Failed to create program: {source}"))]
135 CreateProgram { source: svod_device::Error },
136
137 #[snafu(display("Failed to get device: {source}"))]
138 DeviceFactory { source: svod_runtime::Error },
139
140 #[snafu(display("Buffer for UOp {} not found in registry", uop_id))]
141 BufferNotFound { uop_id: u64 },
142
143 #[snafu(display("Device error: {source}"))]
144 Device { source: svod_device::Error },
145
146 #[snafu(display("Expected Ptr dtype for {context}, got {actual:?}"))]
150 ExpectedPtrDtype { context: &'static str, actual: svod_dtype::DType },
151
152 #[snafu(display("Buffer Ptr dtype has no size"))]
153 BufferPtrNoSize,
154
155 #[snafu(display("Tensor has no buffer (unrealized tensor?)"))]
156 NoBuffer,
157
158 #[snafu(display("Tensor has no shape"))]
159 NoShape,
160
161 #[snafu(display("Shape mismatch for '{context}': expected {expected}, got {actual}"))]
162 ShapeMismatch { context: String, expected: String, actual: String },
163
164 #[snafu(display("IR construction error: {details}"))]
165 IrConstruction { details: String },
166
167 #[snafu(display("Type mismatch: expected {expected:?}, got {actual:?}"))]
168 TypeMismatch { expected: svod_dtype::DType, actual: svod_dtype::DType },
169
170 #[snafu(display("{op} requires floating-point dtype for {arg}, got {dtype:?}"))]
171 FloatDTypeRequired { op: &'static str, arg: &'static str, dtype: svod_dtype::DType },
172
173 #[snafu(display("Failed to create ndarray: {source}"))]
174 NdarrayShape { source: ndarray::ShapeError },
175
176 #[snafu(display("Variable '{name}' value {val} out of range [{min}, {max}]"))]
180 VariableOutOfRange { name: String, val: i64, min: i64, max: i64 },
181
182 #[snafu(display("Cannot read data from tensor with symbolic shape — reduce or slice to concrete shape first"))]
183 SymbolicShape,
184}
185
186pub type Result<T> = std::result::Result<T, Error>;