pliron_math/error.rs
1use thiserror::Error;
2
3/// Broad recovery strategy for a `math` diagnostic.
4///
5/// Use this classification to distinguish invalid caller input from missing
6/// implementation support, rather than parsing error text.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum RecoveryCategory {
10 /// Correct the operand types, attributes, or operation structure and retry.
11 InvalidInput,
12}
13
14/// Structured failures raised by `math` verification.
15///
16/// These errors are wrapped in [`pliron::result::Error`]. Use
17/// [`Diagnostic::from_error`] to recover the structured details.
18#[derive(Debug, Error)]
19#[non_exhaustive]
20pub enum Diagnostic {
21 /// An operation's attributes, types, or structure violate its contract.
22 #[error("operation {operation} at {location}: {reason}")]
23 InvalidOperation {
24 /// Operation name identifying the failed check.
25 operation: String,
26 /// Rendered source location, or a placeholder when no source is available.
27 location: String,
28 /// Specific violated constraint; correct the IR before retrying.
29 reason: &'static str,
30 },
31}
32
33impl Diagnostic {
34 /// Finds the first `math` diagnostic in an error and its source chain.
35 ///
36 /// Traverses framework `err` payloads as well as standard error sources.
37 pub fn from_error(error: &pliron::result::Error) -> Option<&Self> {
38 let mut source: &dyn std::error::Error = error;
39 loop {
40 if let Some(diagnostic) = source.downcast_ref::<Self>() {
41 return Some(diagnostic);
42 }
43 source = if let Some(envelope) = source.downcast_ref::<pliron::result::Error>() {
44 envelope.err.as_ref()
45 } else {
46 source.source()?
47 };
48 }
49 }
50
51 /// Classifies the action a caller should take before retrying.
52 pub fn recovery_category(&self) -> RecoveryCategory {
53 match self {
54 Self::InvalidOperation { .. } => RecoveryCategory::InvalidInput,
55 }
56 }
57}
58
59impl From<Diagnostic> for pliron::result::Error {
60 fn from(diagnostic: Diagnostic) -> Self {
61 pliron::arg_error_noloc!(diagnostic)
62 }
63}