panproto_lens/error.rs
1//! Error types for lens operations.
2//!
3//! [`LensError`] covers failures during lens construction and combinator
4//! compilation. [`LawViolation`] reports failures of the round-trip laws
5//! (`GetPut` and `PutGet`).
6
7use std::fmt;
8
9/// Errors from lens construction, combinator compilation, or lens operations.
10#[derive(Debug, thiserror::Error)]
11#[non_exhaustive]
12pub enum LensError {
13 /// A schema vertex referenced by a combinator was not found.
14 #[error("vertex not found: {0}")]
15 VertexNotFound(String),
16
17 /// An edge referenced by a combinator was not found.
18 #[error("edge not found: {src} -> {tgt}")]
19 EdgeNotFound {
20 /// Source vertex.
21 src: String,
22 /// Target vertex.
23 tgt: String,
24 },
25
26 /// A combinator references an invalid field name.
27 #[error("field not found: {0}")]
28 FieldNotFound(String),
29
30 /// A combinator references an NSID on a vertex that has no NSID.
31 #[error("no NSID on vertex: {0}")]
32 NsidNotFound(String),
33
34 /// A combinator references a constraint sort that does not exist.
35 #[error("constraint sort not found: {0}")]
36 ConstraintSortNotFound(String),
37
38 /// A combinator references an edge kind that does not exist.
39 #[error("edge kind not found: {0}")]
40 EdgeKindNotFound(String),
41
42 /// Type coercion between incompatible kinds.
43 #[error("cannot coerce from {from} to {to}")]
44 IncompatibleCoercion {
45 /// Source kind.
46 from: String,
47 /// Target kind.
48 to: String,
49 },
50
51 /// Lens composition failed because schemas don't align.
52 #[error(
53 "composition failed: target schema of first lens does not match source schema of second"
54 )]
55 CompositionMismatch,
56
57 /// Delegation to the restrict pipeline failed.
58 #[error("restrict error: {0}")]
59 Restrict(#[from] panproto_inst::RestrictError),
60
61 /// A complement was incompatible with the view during `put`.
62 #[error("complement mismatch: {detail}")]
63 ComplementMismatch {
64 /// Details about the mismatch.
65 detail: String,
66 },
67
68 /// A protolens operation failed.
69 #[error("protolens error: {0}")]
70 ProtolensError(String),
71
72 /// An edit could not be applied during law checking.
73 #[error("edit apply error: {0}")]
74 EditApply(#[from] panproto_inst::EditError),
75
76 /// Partial-monoid `Complement::compose` rejected an attempted merge
77 /// because both operands carried distinct entries on the same key.
78 /// Composition is defined exactly when the two complements agree on
79 /// every shared key (idempotent merge); disagreement is the
80 /// boundary of the partial-monoid's domain of definition.
81 #[error("complement conflict on {kind} key `{key}`")]
82 ComplementConflict {
83 /// Which keyed map produced the conflict.
84 kind: &'static str,
85 /// String representation of the conflicting key.
86 key: String,
87 },
88
89 /// Partial-monoid `Complement::compose` rejected an attempted merge
90 /// because the two complements were taken at distinct source
91 /// schemas (their fingerprints differ).
92 #[error(
93 "complement fingerprint mismatch: {left:#x} vs {right:#x}; complements were captured against different source schemas"
94 )]
95 ComplementFingerprintMismatch {
96 /// Left fingerprint.
97 left: u64,
98 /// Right fingerprint.
99 right: u64,
100 },
101
102 /// No enrichment synthesis driver is registered for the named
103 /// `(kind, enricher)` pair. The driver must be registered via
104 /// [`enrichment_registry::register_enricher`](crate::enrichment_registry::register_enricher)
105 /// before a protolens that adds this enrichment can be
106 /// instantiated.
107 #[error("no enrichment driver registered for ({kind:?}, {enricher:?})")]
108 UnknownEnricher {
109 /// The enrichment kind requested.
110 kind: panproto_gat::EnrichmentKind,
111 /// The enricher name (e.g. a grammar name for `Layout`).
112 enricher: String,
113 },
114
115 /// The registered enrichment synthesis driver rejected its input.
116 #[error("enrichment synthesis failed ({kind:?}, {enricher}): {detail}")]
117 EnrichmentSynthesisFailed {
118 /// The enrichment kind.
119 kind: panproto_gat::EnrichmentKind,
120 /// The enricher name.
121 enricher: String,
122 /// Human-readable failure.
123 detail: String,
124 },
125}
126
127/// A violation of a round-trip lens law.
128#[derive(Debug)]
129#[non_exhaustive]
130pub enum LawViolation {
131 /// `GetPut` law violation: `put(s, get(s)) != s`.
132 GetPut {
133 /// Human-readable description of the difference.
134 detail: String,
135 },
136
137 /// `PutGet` law violation: `get(put(s, v)) != v`.
138 PutGet {
139 /// Human-readable description of the difference.
140 detail: String,
141 },
142
143 /// An error occurred while checking the laws.
144 Error(LensError),
145}
146
147impl fmt::Display for LawViolation {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 match self {
150 Self::GetPut { detail } => write!(f, "GetPut law violated: {detail}"),
151 Self::PutGet { detail } => write!(f, "PutGet law violated: {detail}"),
152 Self::Error(e) => write!(f, "error during law check: {e}"),
153 }
154 }
155}
156
157impl std::error::Error for LawViolation {
158 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
159 match self {
160 Self::Error(e) => Some(e),
161 _ => None,
162 }
163 }
164}