Skip to main content

xlog_core/
error.rs

1//! Error types for XLOG
2
3use thiserror::Error;
4
5/// Primary error type for XLOG operations
6#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum XlogError {
9    /// Parse error from the Datalog frontend.
10    #[error("Parse error: {0}")]
11    Parse(String),
12
13    /// Stratification failed due to a cycle through negation.
14    #[error("Stratification failed: cycle through negation involving {0:?}")]
15    StratificationCycle(Vec<String>),
16
17    /// A variable is not bound in any positive body literal (domain safety violation).
18    #[error("Domain safety: variable {0} not bound in positive literal")]
19    UnsafeVariable(String),
20
21    /// GPU memory budget exceeded.
22    #[error("Resource exhausted: {context}, estimated {estimated_bytes} bytes, budget {budget_bytes} bytes")]
23    ResourceExhausted {
24        /// Description of the operation that exceeded the budget.
25        context: String,
26        /// Estimated memory required in bytes.
27        estimated_bytes: u64,
28        /// Available memory budget in bytes.
29        budget_bytes: u64,
30    },
31
32    /// The D4 **compile** phase declined a CNF too large to compile safely
33    /// (the knowledge-compilation emit buffers are fixed-capacity; a larger
34    /// instance would overrun them and fail with a context-poisoning CUDA
35    /// launch error). A typed, catchable decline distinct from the verify-phase
36    /// signal — "too big to compile", not "verify gave up". The caller can skip
37    /// the query or fall back to an approximate engine.
38    #[error("D4 compile declined: {context}: {detail}")]
39    CompileCapacityExceeded {
40        /// Description of the compile operation that was declined.
41        context: String,
42        /// Which capacity tripped and its measured/configured values.
43        detail: String,
44    },
45
46    /// The GPU CDCL equivalence **verifier** declined rather than risk a
47    /// CUDA launch failure that poisons the primary context: a per-verify
48    /// conflict budget ran out before the search reached a definite answer
49    /// (INDETERMINATE — declined fail-closed, never trusted as a proof).
50    /// Distinct from [`CompileCapacityExceeded`] so the two phases stay
51    /// diagnosably separate. The caller can skip the query or fall back to an
52    /// approximate engine.
53    #[error("D4 equivalence verify declined: {context}: {detail}")]
54    VerifyBudgetExceeded {
55        /// Description of the verify operation that was declined.
56        context: String,
57        /// Which budget tripped and its measured/configured values.
58        detail: String,
59    },
60
61    /// GPU kernel launch or execution error.
62    #[error("Kernel error: {0}")]
63    Kernel(String),
64
65    /// Type checking or inference error.
66    #[error("Type error: {0}")]
67    Type(String),
68
69    /// Compilation pipeline error.
70    #[error("Compilation error: {0}")]
71    Compilation(String),
72
73    /// Epistemic construct is known to the frontend but unsupported in this context.
74    #[error("Unsupported epistemic construct: {construct} ({context})")]
75    UnsupportedEpistemicConstruct {
76        /// Construct that was rejected.
77        construct: String,
78        /// Context where the construct was rejected.
79        context: String,
80    },
81
82    /// Runtime execution error.
83    #[error("Execution error: {0}")]
84    Execution(String),
85}
86
87impl XlogError {
88    /// Create a Kernel error with structured context: "op: detail: source".
89    pub fn kernel_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
90        XlogError::Kernel(format!("{op}: {detail}: {source}"))
91    }
92
93    /// Create an Execution error with structured context.
94    pub fn execution_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
95        XlogError::Execution(format!("{op}: {detail}: {source}"))
96    }
97
98    /// Create a Compilation error with structured context.
99    pub fn compilation_ctx(op: &str, detail: &str, source: &impl std::fmt::Display) -> Self {
100        XlogError::Compilation(format!("{op}: {detail}: {source}"))
101    }
102}
103
104/// Result alias using XlogError
105pub type Result<T> = std::result::Result<T, XlogError>;
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_parse_error_display() {
113        let err = XlogError::Parse("unexpected token".to_string());
114        assert_eq!(err.to_string(), "Parse error: unexpected token");
115    }
116
117    #[test]
118    fn test_stratification_cycle_display() {
119        let err = XlogError::StratificationCycle(vec!["foo".to_string(), "bar".to_string()]);
120        assert!(err.to_string().contains("foo"));
121        assert!(err.to_string().contains("bar"));
122    }
123
124    #[test]
125    fn test_resource_exhausted_display() {
126        let err = XlogError::ResourceExhausted {
127            context: "join operation".to_string(),
128            estimated_bytes: 1024,
129            budget_bytes: 512,
130        };
131        assert!(err.to_string().contains("1024"));
132        assert!(err.to_string().contains("512"));
133    }
134
135    #[test]
136    fn test_kernel_ctx() {
137        let err = XlogError::kernel_ctx("download_column", "dtoh copy failed", &"device error 42");
138        assert_eq!(
139            err.to_string(),
140            "Kernel error: download_column: dtoh copy failed: device error 42"
141        );
142    }
143
144    #[test]
145    fn test_execution_ctx() {
146        let err = XlogError::execution_ctx("execute_node", "filter failed", &"type mismatch");
147        assert_eq!(
148            err.to_string(),
149            "Execution error: execute_node: filter failed: type mismatch"
150        );
151    }
152
153    #[test]
154    fn test_compilation_ctx() {
155        let err = XlogError::compilation_ctx("compile_d4", "frontier overflow", &"limit 1024");
156        assert_eq!(
157            err.to_string(),
158            "Compilation error: compile_d4: frontier overflow: limit 1024"
159        );
160    }
161}