1use crate::position::Position;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "kind", rename_all = "snake_case")]
8pub enum TypeError {
9 TypeMismatch {
10 at_node: String,
11 expected: String,
12 got: String,
13 context: Vec<String>,
14 },
15 UnknownIdentifier {
16 at_node: String,
17 name: String,
18 },
19 ArityMismatch {
20 at_node: String,
21 expected: usize,
22 got: usize,
23 },
24 NonExhaustiveMatch {
25 at_node: String,
26 missing: Vec<String>,
27 },
28 UnknownField {
29 at_node: String,
30 record_type: String,
31 field: String,
32 },
33 DuplicateField {
34 at_node: String,
35 field: String,
36 },
37 UnknownVariant {
38 at_node: String,
39 constructor: String,
40 },
41 EffectNotDeclared {
42 at_node: String,
43 effect: String,
44 },
45 InfiniteType {
46 at_node: String,
47 },
48 AmbiguousType {
49 at_node: String,
50 },
51 RecursiveTypeWithoutConstructor {
52 at_node: String,
53 name: String,
54 },
55 RefinementViolation {
61 at_node: String,
62 fn_name: String,
63 param_index: usize,
64 binding: String,
65 reason: String,
66 },
67 ExamplesOnEffectfulFn {
72 at_node: String,
73 fn_name: String,
74 },
75 ExampleArityMismatch {
78 at_node: String,
79 fn_name: String,
80 case_index: usize,
82 expected: usize,
83 got: usize,
84 },
85 ExampleMismatch {
90 at_node: String,
91 fn_name: String,
92 case_index: usize,
93 expected: String,
95 got: String,
97 },
98}
99
100impl TypeError {
101 pub fn node(&self) -> &str {
102 match self {
103 TypeError::TypeMismatch { at_node, .. }
104 | TypeError::UnknownIdentifier { at_node, .. }
105 | TypeError::ArityMismatch { at_node, .. }
106 | TypeError::NonExhaustiveMatch { at_node, .. }
107 | TypeError::UnknownField { at_node, .. }
108 | TypeError::DuplicateField { at_node, .. }
109 | TypeError::UnknownVariant { at_node, .. }
110 | TypeError::EffectNotDeclared { at_node, .. }
111 | TypeError::InfiniteType { at_node, .. }
112 | TypeError::AmbiguousType { at_node, .. }
113 | TypeError::RecursiveTypeWithoutConstructor { at_node, .. }
114 | TypeError::RefinementViolation { at_node, .. }
115 | TypeError::ExamplesOnEffectfulFn { at_node, .. }
116 | TypeError::ExampleArityMismatch { at_node, .. }
117 | TypeError::ExampleMismatch { at_node, .. } => at_node,
118 }
119 }
120}
121
122impl std::fmt::Display for TypeError {
123 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
124 match self {
125 TypeError::TypeMismatch { at_node, expected, got, context } => {
126 write!(f, "type mismatch at {at_node}: expected {expected}, got {got}")?;
127 if !context.is_empty() { write!(f, " ({})", context.join(" / "))?; }
128 Ok(())
129 }
130 TypeError::UnknownIdentifier { at_node, name } => write!(f, "unknown identifier `{name}` at {at_node}"),
131 TypeError::ArityMismatch { at_node, expected, got } => write!(f, "arity mismatch at {at_node}: expected {expected}, got {got}"),
132 TypeError::NonExhaustiveMatch { at_node, missing } => write!(f, "non-exhaustive match at {at_node}: missing {missing:?}"),
133 TypeError::UnknownField { at_node, record_type, field } => write!(f, "unknown field `{field}` on {record_type} at {at_node}"),
134 TypeError::DuplicateField { at_node, field } => write!(f, "duplicate field `{field}` at {at_node}"),
135 TypeError::UnknownVariant { at_node, constructor } => write!(f, "unknown constructor `{constructor}` at {at_node}"),
136 TypeError::EffectNotDeclared { at_node, effect } => write!(f, "effect `{effect}` not declared at {at_node}"),
137 TypeError::InfiniteType { at_node } => write!(f, "infinite type (occurs check) at {at_node}"),
138 TypeError::AmbiguousType { at_node } => write!(f, "ambiguous type at {at_node}"),
139 TypeError::RecursiveTypeWithoutConstructor { at_node, name } => write!(f, "recursive type {name} has no constructor at {at_node}"),
140 TypeError::RefinementViolation { at_node, fn_name, param_index, binding, reason } =>
141 write!(f, "refinement violated at {at_node}: argument {} of `{fn_name}` (binding `{binding}`): {reason}",
142 param_index + 1),
143 TypeError::ExamplesOnEffectfulFn { at_node, fn_name } =>
144 write!(f, "function `{fn_name}` at {at_node} carries `examples` but declares effects; \
145 v1 restricts examples to pure functions"),
146 TypeError::ExampleArityMismatch { at_node, fn_name, case_index, expected, got } =>
147 write!(f, "example #{} of `{fn_name}` at {at_node}: expected {expected} argument(s), got {got}",
148 case_index + 1),
149 TypeError::ExampleMismatch { at_node, fn_name, case_index, expected, got } =>
150 write!(f, "example #{} of `{fn_name}` at {at_node}: expected {expected}, got {got}",
151 case_index + 1),
152 }
153 }
154}
155
156impl std::error::Error for TypeError {}
157
158#[derive(Debug, Clone)]
173pub struct PositionedError {
174 pub error: TypeError,
175 pub position: Option<Position>,
176}
177
178impl Serialize for PositionedError {
179 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
180 use serde::ser::SerializeMap;
181 let inner = serde_json::to_value(&self.error)
186 .map_err(serde::ser::Error::custom)?;
187 let obj = inner
188 .as_object()
189 .ok_or_else(|| serde::ser::Error::custom("TypeError did not serialize as an object"))?;
190 let extra = if self.position.is_some() { 3 } else { 2 };
191 let mut map = serializer.serialize_map(Some(obj.len() + extra))?;
192 for (k, v) in obj {
193 map.serialize_entry(k, v)?;
194 }
195 map.serialize_entry("rule_tag", self.error.rule_tag())?;
196 map.serialize_entry("rule_explanation", self.error.rule_explanation())?;
197 if let Some(p) = &self.position {
198 map.serialize_entry("position", p)?;
199 }
200 map.end()
201 }
202}
203
204impl<'de> Deserialize<'de> for PositionedError {
205 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
206 let mut value = serde_json::Value::deserialize(deserializer)?;
211 let position = value
212 .as_object_mut()
213 .and_then(|o| o.remove("position"))
214 .and_then(|p| serde_json::from_value::<Position>(p).ok());
215 if let Some(o) = value.as_object_mut() {
216 o.remove("rule_tag");
217 o.remove("rule_explanation");
218 }
219 let error: TypeError =
220 serde_json::from_value(value).map_err(serde::de::Error::custom)?;
221 Ok(PositionedError { error, position })
222 }
223}
224
225impl PositionedError {
226 pub fn new(error: TypeError, position: Option<Position>) -> Self {
227 Self { error, position }
228 }
229
230 pub fn without_position(error: TypeError) -> Self {
231 Self { error, position: None }
232 }
233
234 pub fn node(&self) -> &str {
235 self.error.node()
236 }
237}
238
239impl std::fmt::Display for PositionedError {
240 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
241 match &self.position {
242 Some(p) => write!(f, "[{}] {}", p.render(), self.error),
243 None => self.error.fmt(f),
244 }
245 }
246}
247
248impl std::error::Error for PositionedError {}
249
250impl From<TypeError> for PositionedError {
251 fn from(e: TypeError) -> Self {
252 Self::without_position(e)
253 }
254}