1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/// Errors that can occur in GAT operations.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum GatError {
/// A referenced sort was not found in the theory.
#[error("sort not found: {0}")]
SortNotFound(String),
/// A referenced operation was not found in the theory.
#[error("operation not found: {0}")]
OpNotFound(String),
/// A referenced theory was not found in the registry.
#[error("theory not found: {0}")]
TheoryNotFound(String),
/// Sort arity mismatch in a morphism or model.
#[error("sort arity mismatch for {sort}: expected {expected}, got {got}")]
SortArityMismatch {
/// The sort with mismatched arity.
sort: String,
/// Expected number of parameters.
expected: usize,
/// Actual number of parameters.
got: usize,
},
/// Operation type mismatch in a morphism or model.
#[error("operation type mismatch for {op}: {detail}")]
OpTypeMismatch {
/// The operation with mismatched types.
op: String,
/// Details about the mismatch.
detail: String,
},
/// An equation is not preserved by a morphism.
#[error("equation {equation} not preserved: {detail}")]
EquationNotPreserved {
/// The equation that failed preservation.
equation: String,
/// Details about the failure.
detail: String,
},
/// A directed equation is not preserved by a morphism.
#[error("directed equation {equation} not preserved: {detail}")]
DirectedEquationNotPreserved {
/// The directed equation that failed preservation.
equation: String,
/// Details about the failure.
detail: String,
},
/// Sort conflict during colimit computation.
#[error("sort conflict in colimit: {name} has incompatible definitions")]
SortConflict {
/// The conflicting sort name.
name: String,
},
/// Operation conflict during colimit computation.
#[error("operation conflict in colimit: {name} has incompatible definitions")]
OpConflict {
/// The conflicting operation name.
name: String,
},
/// Equation conflict during colimit computation.
#[error("equation conflict in colimit: {name}")]
EqConflict {
/// The conflicting equation name.
name: String,
},
/// Directed equation conflict during colimit computation.
#[error("directed equation conflict in colimit: {name}")]
DirectedEqConflict {
/// The conflicting directed equation name.
name: String,
},
/// Conflict policy conflict during colimit computation.
#[error("conflict policy conflict in colimit: {name}")]
PolicyConflict {
/// The conflicting policy name.
name: String,
},
/// A morphism is missing a sort mapping.
#[error("morphism missing sort mapping for: {0}")]
MissingSortMapping(String),
/// A morphism is missing an operation mapping.
#[error("morphism missing operation mapping for: {0}")]
MissingOpMapping(String),
/// Morphism composition failed: an element in the first morphism's
/// codomain image is not in the second morphism's domain.
#[error(
"compose: {kind} `{name}` maps to `{image}` which has no mapping in the second morphism"
)]
ComposeUnmapped {
/// Whether this is a "sort" or "op".
kind: &'static str,
/// The element in the first morphism's domain.
name: String,
/// The image in the first morphism's codomain (missing from second morphism).
image: String,
},
/// Cyclic dependency detected in theory extends chain.
#[error("cyclic dependency detected involving theory: {0}")]
CyclicDependency(String),
/// Model interpretation error.
#[error("model error: {0}")]
ModelError(String),
// --- Type-checking errors ---
/// A variable was not found in the typing context.
#[error("unbound variable: {0}")]
UnboundVariable(String),
/// An operation was applied to the wrong number of arguments.
#[error("arity mismatch for operation {op}: expected {expected} args, got {got}")]
TermArityMismatch {
/// The operation name.
op: String,
/// Expected number of arguments.
expected: usize,
/// Actual number of arguments.
got: usize,
},
/// An argument's sort doesn't match the operation's expected input sort.
#[error("type mismatch for {op} argument {arg_index}: expected {expected}, got {got}")]
ArgTypeMismatch {
/// The operation name.
op: String,
/// Zero-based argument index.
arg_index: usize,
/// Expected sort name.
expected: String,
/// Actual sort name.
got: String,
},
/// The two sides of an equation have different sorts.
#[error("equation {equation} sides have different sorts: lhs={lhs_sort}, rhs={rhs_sort}")]
EquationSortMismatch {
/// The equation name.
equation: String,
/// Sort of the left-hand side.
lhs_sort: String,
/// Sort of the right-hand side.
rhs_sort: String,
},
/// A variable is used at conflicting sorts across an equation.
#[error("variable {var} used at conflicting sorts: {sort1} and {sort2}")]
ConflictingVarSort {
/// The variable name.
var: String,
/// First inferred sort.
sort1: String,
/// Second (conflicting) inferred sort.
sort2: String,
},
/// Sort-expression unification failed (e.g. heads differ, arity
/// mismatch, or occurs check).
#[error("sort unification failure: {reason}")]
SortUnificationFailure {
/// Human-readable reason for the failure.
reason: String,
},
// --- Natural transformation errors ---
/// Source and target morphisms of a natural transformation have different domains.
#[error(
"natural transformation domain mismatch: {source_morphism} and {target_morphism} have different domains"
)]
NatTransDomainMismatch {
/// Source morphism name.
source_morphism: String,
/// Target morphism name.
target_morphism: String,
},
/// A natural transformation is missing a component for a sort.
#[error("missing natural transformation component for sort: {0}")]
MissingNatTransComponent(String),
/// A natural transformation component is invalid.
#[error("invalid natural transformation component for sort {sort}: {detail}")]
NatTransComponentInvalid {
/// The sort name.
sort: String,
/// Details about the invalidity.
detail: String,
},
/// The naturality condition is violated for an operation.
#[error("naturality violated for operation {op}")]
NaturalityViolation {
/// The operation where naturality fails.
op: String,
/// LHS of the naturality square.
lhs: String,
/// RHS of the naturality square.
rhs: String,
},
/// Natural transformation composition mismatch.
#[error("cannot compose: alpha target {alpha_target} != beta source {beta_source}")]
NatTransComposeMismatch {
/// Target morphism of first nat trans.
alpha_target: String,
/// Source morphism of second nat trans.
beta_source: String,
},
/// Sort kind mismatch in a morphism: source and target sorts have different kinds.
#[error("sort kind mismatch for {sort}: expected {expected:?}, got {got:?}")]
SortKindMismatch {
/// The sort with mismatched kind.
sort: String,
/// Expected sort kind.
expected: crate::sort::SortKind,
/// Actual sort kind.
got: crate::sort::SortKind,
},
/// Sort parameter sort mismatch in a morphism: a dependent sort's parameter
/// sort is not preserved under the sort mapping.
#[error(
"sort parameter mismatch for {sort} at index {param_index}: expected {expected}, got {got}"
)]
SortParamMismatch {
/// The sort with mismatched parameter.
sort: String,
/// Zero-based parameter index.
param_index: usize,
/// Expected parameter sort (after mapping).
expected: String,
/// Actual parameter sort in the target.
got: String,
},
/// Horizontal composition domain mismatch: G's codomain differs from H's domain.
#[error("horizontal compose domain mismatch: {g_codomain} != {h_domain}")]
HorizontalComposeMismatch {
/// G morphism's codomain.
g_codomain: String,
/// H morphism's domain.
h_domain: String,
},
// --- Factorization errors ---
/// Factorization error.
#[error("factorization error: {0}")]
FactorizationError(String),
// --- Free model errors ---
/// Cyclic sort dependencies detected in topological sort.
#[error("cyclic sort dependencies: {0:?}")]
CyclicSortDependency(Vec<String>),
// --- Quotient errors ---
/// A case expression fails to cover every constructor of its
/// scrutinee's closed sort.
#[error("case on sort {sort} missing branches for: {missing:?}")]
NonExhaustiveCase {
/// The scrutinee's sort name.
sort: String,
/// Constructor names not covered.
missing: Vec<String>,
},
/// A case expression has two branches for the same constructor.
#[error("case on sort {sort} has a redundant branch for constructor {constructor}")]
RedundantCaseBranch {
/// The scrutinee's sort name.
sort: String,
/// The duplicated constructor name.
constructor: String,
},
/// A case branch names a constructor that is not in the scrutinee's
/// closed-sort constructor list.
#[error("case on sort {sort} references unknown constructor {constructor}")]
UnknownCaseConstructor {
/// The scrutinee's sort name.
sort: String,
/// The offending constructor name.
constructor: String,
},
/// A case expression's scrutinee has an open sort; pattern
/// matching requires a closed sort.
#[error("case scrutinee has open sort {sort}; pattern matching requires a closed sort")]
CaseOnOpenSort {
/// The scrutinee's sort name.
sort: String,
},
/// A closed sort's constructor list references an op that either
/// does not exist, does not produce this sort, or conflicts with
/// another op producing the sort.
#[error("closed sort {sort} has invalid constructor {constructor}: {detail}")]
InvalidClosedSortConstructor {
/// The closed sort name.
sort: String,
/// The offending constructor op name.
constructor: String,
/// Details about the problem.
detail: String,
},
/// A morphism does not preserve a domain sort's closure: the
/// image of the constructor list under the op map is not the
/// codomain sort's constructor list.
#[error(
"morphism fails closure preservation for sort {sort}: expected closure {expected:?}, got {got:?}"
)]
MorphismClosureMismatch {
/// The domain sort name.
sort: String,
/// Expected constructor set (domain closure image under `op_map`).
expected: Vec<String>,
/// Actual constructor set in the codomain sort.
got: Vec<String>,
},
/// An operation declares an implicit parameter whose value cannot
/// be recovered from the explicit inputs at a call site.
///
/// An implicit parameter must occur as a `Term::Var` somewhere in
/// the sort expression of at least one explicit input or in the
/// output sort, so that first-order unification of the declared
/// input sorts against the call site's actual sorts pins down the
/// parameter's value. Implicit parameters that do not appear in
/// such a position are rejected at theory-declaration time.
#[error(
"operation {op} declares implicit parameter {param} that does not occur in any explicit input sort or the output sort"
)]
NonInferrableImplicit {
/// The operation name.
op: String,
/// The implicit parameter name.
param: String,
},
/// An instance-style binding names a key that is neither a sort
/// parameter nor an operation of the class theory. Produced by the
/// `instance!` proc-macro when validating its bindings.
#[error(
"instance {instance} binds unknown name {name} which is neither a sort nor an op of class {class}"
)]
InstanceBindingUnknown {
/// The instance name.
instance: String,
/// The class theory name.
class: String,
/// The offending binding key.
name: String,
},
/// An instance-style declaration passes more type arguments than the
/// class theory has sort parameters.
#[error(
"instance {instance} passes {passed} type arguments to class {class} which declares {declared} sort(s)"
)]
InstanceTypeArgsArity {
/// The instance name.
instance: String,
/// The class theory name.
class: String,
/// Number of type arguments passed.
passed: usize,
/// Number of sort parameters declared by the class.
declared: usize,
},
/// A rewrite position is invalid: the path descends through a term
/// variant that does not have the requested child index.
#[error("invalid rewrite position {path:?}: node is {node_kind}")]
InvalidRewritePosition {
/// The path that was requested.
path: Vec<usize>,
/// The kind of node that could not be descended into.
node_kind: &'static str,
},
/// An equation (or directed equation) contains one or more typed
/// holes on its LHS or RHS. Holes are only meaningful inside terms
/// being typechecked for completion, not in equations that must
/// hold in every model.
#[error("equation {equation} contains {count} hole(s); holes are not permitted in equations")]
HolesInEquation {
/// The equation name.
equation: String,
/// The number of holes encountered across both sides.
count: usize,
},
/// An LPO termination check encountered a rewrite rule that contains
/// a hole on one of its sides. Holes in rewrite rules are not
/// meaningful for LPO comparison.
#[error("LPO: rule {rule} contains a hole; holes are not comparable under LPO")]
LpoHoleInRule {
/// The offending rule name.
rule: String,
},
/// Identified elements are incompatible for quotienting.
#[error("cannot identify {name_a} and {name_b}: {detail}")]
QuotientIncompatible {
/// First element name.
name_a: String,
/// Second element name.
name_b: String,
/// Reason for incompatibility.
detail: String,
},
}