Skip to main content

tenferro_runtime/program/
error.rs

1/// Errors reported while adding semantic-program structure.
2#[derive(Debug, thiserror::Error)]
3#[non_exhaustive]
4pub enum ProgramBuildError {
5    /// A value token was issued by another builder.
6    #[error("value does not belong to this semantic-program builder")]
7    ForeignValue,
8    /// An import root belongs to another semantic program.
9    #[error("import root does not belong to the source semantic program")]
10    ForeignImportRoot,
11    /// Import bindings were frozen for another semantic program.
12    #[error("import bindings do not belong to the source semantic program")]
13    ForeignBindings,
14    /// A trace context was re-entered while an operation still borrowed it.
15    #[error("trace context is already borrowed by an operation in progress")]
16    ReentrantContextBorrow,
17    /// Structured control flow is reserved for the later region/block model.
18    #[error("semantic control-flow construct {construct:?} is not supported")]
19    UnsupportedControlFlow {
20        /// Frontend construct that could not be represented.
21        construct: &'static str,
22    },
23    /// A frozen source program failed import-time structural validation.
24    #[error("source semantic program is invalid for import: {source}")]
25    InvalidImport {
26        #[source]
27        source: ProgramStructuralError,
28    },
29    /// A binding target is a computed value rather than an external input.
30    #[error("tensor bindings may target only semantic-program inputs")]
31    BindingTargetNotInput,
32    /// A shape guard target is not produced by a semantic operation.
33    #[error("semantic shape guards may target only operation outputs")]
34    GuardTargetNotOperationOutput,
35    /// An external input already has a tensor binding.
36    #[error("semantic-program input already has a tensor binding")]
37    DuplicateBinding,
38    /// The builder cannot represent another value slot.
39    #[error("semantic-program value count exceeds the supported u32 range")]
40    TooManyValues,
41    /// An operation received the wrong number of SSA inputs.
42    #[error("semantic operation expects {expected} inputs, got {actual}")]
43    Arity {
44        /// Declared input count.
45        expected: usize,
46        /// Supplied input count.
47        actual: usize,
48    },
49    /// Semantic dtype or shape inference failed.
50    #[error("semantic operation metadata inference failed: {source}")]
51    Metadata {
52        /// Original typed runtime inference error.
53        #[source]
54        source: Box<crate::Error>,
55    },
56    /// Inference did not return the declared number of outputs.
57    #[error("semantic operation declares {expected} outputs, inferred {actual}")]
58    OutputMetadataCount {
59        /// Declared output count.
60        expected: usize,
61        /// Inferred metadata count.
62        actual: usize,
63    },
64    /// An extension did not explicitly declare its observable effects.
65    #[error("extension family {family:?} has no semantic effect declaration")]
66    UndeclaredExtensionEffects {
67        /// Stable extension family.
68        family: &'static str,
69    },
70    /// An extension did not explicitly declare output aliases.
71    #[error("extension family {family:?} has no semantic alias declaration")]
72    UndeclaredExtensionAliases {
73        /// Stable extension family.
74        family: &'static str,
75    },
76    /// An extension declared an invalid resource family.
77    #[error("extension family {family:?} declared an invalid effect resource: {source}")]
78    InvalidEffectResource {
79        /// Stable extension family.
80        family: &'static str,
81        /// Typed resource validation failure.
82        #[source]
83        source: EffectResourceError,
84    },
85    /// An alias referenced an input or output outside the operation arity.
86    #[error(
87        "semantic alias index is out of bounds: output {output}/{output_count}, input {input:?}/{input_count}"
88    )]
89    AliasOutOfBounds {
90        /// Referenced output.
91        output: usize,
92        /// Output arity.
93        output_count: usize,
94        /// Referenced input, when applicable.
95        input: Option<usize>,
96        /// Input arity.
97        input_count: usize,
98    },
99    /// An externally defined scalar reached the semantic program.
100    #[error(
101        "externally defined scalar {dtype:?} reached {site} without a canonical program \
102identity; a contribution must declare a stable scalar identity before a traced program can \
103carry it"
104    )]
105    ExternalScalarWithoutIdentity {
106        /// The externally defined tag that reached the program.
107        dtype: tenferro_tensor::DType,
108        /// Where the tag reached the program.
109        site: &'static str,
110    },
111    /// Alias declarations did not cover every output exactly once.
112    #[error("semantic aliases must cover {expected} outputs exactly once, got {actual}")]
113    AliasCoverage {
114        /// Output arity.
115        expected: usize,
116        /// Number of distinct valid output declarations.
117        actual: usize,
118    },
119}
120
121/// Errors reported while querying an immutable semantic program.
122#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
123pub enum ProgramQueryError {
124    /// A value token belongs to another program or names no frozen value.
125    #[error("value does not belong to this semantic program")]
126    ForeignValue,
127}
128
129/// Internal structural validation failures detected during atomic freeze.
130#[derive(Clone, Copy, Debug, PartialEq, Eq, thiserror::Error)]
131#[non_exhaustive]
132pub enum ProgramStructuralError {
133    /// An operation references a value outside the frozen value table.
134    #[error("semantic operation references a value outside the program")]
135    InvalidValueReference,
136    /// An operation output is not strictly after all prior values.
137    #[error("semantic operation outputs violate SSA ordering")]
138    InvalidSsaOrder,
139}
140
141/// Tensor-binding validation failures detected during atomic freeze.
142#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
143#[non_exhaustive]
144pub enum ProgramBindingError {
145    /// A pending binding no longer names an external input.
146    #[error("tensor binding target is not a semantic-program input")]
147    InvalidTarget,
148    /// Tensor dtype differs from the input declaration.
149    #[error("tensor binding dtype mismatch: expected {expected:?}, got {actual:?}")]
150    DTypeMismatch {
151        /// Declared input dtype.
152        expected: tenferro_tensor::DType,
153        /// Bound tensor dtype.
154        actual: tenferro_tensor::DType,
155    },
156    /// Tensor rank differs from the input declaration.
157    #[error("tensor binding rank mismatch: expected {expected}, got {actual}")]
158    RankMismatch {
159        /// Declared input rank.
160        expected: usize,
161        /// Bound tensor rank.
162        actual: usize,
163    },
164    /// A statically exact dimension differs from the input declaration.
165    #[error("tensor binding extent mismatch at axis {axis}: expected {expected}, got {actual}")]
166    ExactExtentMismatch {
167        /// Mismatching axis.
168        axis: usize,
169        /// Declared exact extent.
170        expected: usize,
171        /// Bound tensor extent.
172        actual: usize,
173    },
174    /// A bounded dimension exceeds the declared upper bound.
175    #[error(
176        "tensor binding extent exceeds upper bound at axis {axis}: bound {bound}, got {actual}"
177    )]
178    UpperBoundExceeded {
179        /// Axis whose bound was exceeded.
180        axis: usize,
181        /// Declared upper bound.
182        bound: usize,
183        /// Bound tensor extent.
184        actual: usize,
185    },
186}
187
188/// Errors reported while atomically freezing semantic structure and bindings.
189#[derive(Debug, thiserror::Error)]
190#[non_exhaustive]
191pub enum ProgramFinishError {
192    /// One requested output belongs to another builder or names no value.
193    #[error("program output does not belong to this semantic-program builder")]
194    ForeignOutput,
195    /// Rebuilding the live closure failed while snapshotting.
196    #[error("snapshot rebuild failed: {source}")]
197    SnapshotRebuild {
198        /// Typed failure from replaying the live operations.
199        #[source]
200        source: ProgramBuildError,
201    },
202    /// A checkpoint alias could not be materialized as a prefixed slice.
203    #[error("checkpoint alias substitution failed: {source}")]
204    AliasSubstitution {
205        /// Typed failure from building the substituted slice.
206        #[source]
207        source: ProgramBuildError,
208    },
209    /// A trace context was re-entered while a snapshot still borrowed it.
210    #[error("trace context is already borrowed by an operation in progress")]
211    ReentrantContextBorrow,
212    /// Frozen structure failed an invariant check.
213    #[error("semantic-program structural validation failed: {source}")]
214    StructuralValidation {
215        /// Typed structural invariant failure.
216        #[source]
217        source: ProgramStructuralError,
218    },
219    /// A tensor default or large constant does not match its input declaration.
220    #[error("semantic-program binding finalization failed: {source}")]
221    BindingFinalization {
222        /// Typed binding mismatch.
223        #[source]
224        source: ProgramBindingError,
225    },
226}
227
228/// Failures produced by a validated semantic transform transaction.
229#[derive(Debug, thiserror::Error)]
230#[non_exhaustive]
231pub enum SemanticTransformError {
232    /// Program construction or import failed inside the transform.
233    #[error(transparent)]
234    Build(#[from] ProgramBuildError),
235    /// Atomic freeze failed after the transform returned roots.
236    #[error(transparent)]
237    Finish(#[from] ProgramFinishError),
238    /// The transform returned a value not owned by its destination builder.
239    #[error("semantic transform returned a foreign destination value")]
240    ForeignReturnedValue,
241    /// The transform did not carry every input tensor binding forward.
242    #[error("semantic transform discarded one or more tensor bindings")]
243    DroppedBindings,
244    /// The transform deliberately rejected this input.
245    #[error("semantic transform rejected the input")]
246    Rejected,
247}
248
249/// Invalid typed effect-resource identity.
250#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
251pub enum EffectResourceError {
252    /// Resource-family names must be nonempty and versioned.
253    #[error("effect resource family must be a nonempty versioned identifier")]
254    InvalidFamily,
255}