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}
68
69impl TypeError {
70 pub fn node(&self) -> &str {
71 match self {
72 TypeError::TypeMismatch { at_node, .. }
73 | TypeError::UnknownIdentifier { at_node, .. }
74 | TypeError::ArityMismatch { at_node, .. }
75 | TypeError::NonExhaustiveMatch { at_node, .. }
76 | TypeError::UnknownField { at_node, .. }
77 | TypeError::DuplicateField { at_node, .. }
78 | TypeError::UnknownVariant { at_node, .. }
79 | TypeError::EffectNotDeclared { at_node, .. }
80 | TypeError::InfiniteType { at_node, .. }
81 | TypeError::AmbiguousType { at_node, .. }
82 | TypeError::RecursiveTypeWithoutConstructor { at_node, .. }
83 | TypeError::RefinementViolation { at_node, .. } => at_node,
84 }
85 }
86}
87
88impl std::fmt::Display for TypeError {
89 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
90 match self {
91 TypeError::TypeMismatch { at_node, expected, got, context } => {
92 write!(f, "type mismatch at {at_node}: expected {expected}, got {got}")?;
93 if !context.is_empty() { write!(f, " ({})", context.join(" / "))?; }
94 Ok(())
95 }
96 TypeError::UnknownIdentifier { at_node, name } => write!(f, "unknown identifier `{name}` at {at_node}"),
97 TypeError::ArityMismatch { at_node, expected, got } => write!(f, "arity mismatch at {at_node}: expected {expected}, got {got}"),
98 TypeError::NonExhaustiveMatch { at_node, missing } => write!(f, "non-exhaustive match at {at_node}: missing {missing:?}"),
99 TypeError::UnknownField { at_node, record_type, field } => write!(f, "unknown field `{field}` on {record_type} at {at_node}"),
100 TypeError::DuplicateField { at_node, field } => write!(f, "duplicate field `{field}` at {at_node}"),
101 TypeError::UnknownVariant { at_node, constructor } => write!(f, "unknown constructor `{constructor}` at {at_node}"),
102 TypeError::EffectNotDeclared { at_node, effect } => write!(f, "effect `{effect}` not declared at {at_node}"),
103 TypeError::InfiniteType { at_node } => write!(f, "infinite type (occurs check) at {at_node}"),
104 TypeError::AmbiguousType { at_node } => write!(f, "ambiguous type at {at_node}"),
105 TypeError::RecursiveTypeWithoutConstructor { at_node, name } => write!(f, "recursive type {name} has no constructor at {at_node}"),
106 TypeError::RefinementViolation { at_node, fn_name, param_index, binding, reason } =>
107 write!(f, "refinement violated at {at_node}: argument {} of `{fn_name}` (binding `{binding}`): {reason}",
108 param_index + 1),
109 }
110 }
111}
112
113impl std::error::Error for TypeError {}
114
115#[derive(Debug, Clone)]
130pub struct PositionedError {
131 pub error: TypeError,
132 pub position: Option<Position>,
133}
134
135impl Serialize for PositionedError {
136 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
137 use serde::ser::SerializeMap;
138 let inner = serde_json::to_value(&self.error)
143 .map_err(serde::ser::Error::custom)?;
144 let obj = inner
145 .as_object()
146 .ok_or_else(|| serde::ser::Error::custom("TypeError did not serialize as an object"))?;
147 let extra = if self.position.is_some() { 3 } else { 2 };
148 let mut map = serializer.serialize_map(Some(obj.len() + extra))?;
149 for (k, v) in obj {
150 map.serialize_entry(k, v)?;
151 }
152 map.serialize_entry("rule_tag", self.error.rule_tag())?;
153 map.serialize_entry("rule_explanation", self.error.rule_explanation())?;
154 if let Some(p) = &self.position {
155 map.serialize_entry("position", p)?;
156 }
157 map.end()
158 }
159}
160
161impl<'de> Deserialize<'de> for PositionedError {
162 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
163 let mut value = serde_json::Value::deserialize(deserializer)?;
168 let position = value
169 .as_object_mut()
170 .and_then(|o| o.remove("position"))
171 .and_then(|p| serde_json::from_value::<Position>(p).ok());
172 if let Some(o) = value.as_object_mut() {
173 o.remove("rule_tag");
174 o.remove("rule_explanation");
175 }
176 let error: TypeError =
177 serde_json::from_value(value).map_err(serde::de::Error::custom)?;
178 Ok(PositionedError { error, position })
179 }
180}
181
182impl PositionedError {
183 pub fn new(error: TypeError, position: Option<Position>) -> Self {
184 Self { error, position }
185 }
186
187 pub fn without_position(error: TypeError) -> Self {
188 Self { error, position: None }
189 }
190
191 pub fn node(&self) -> &str {
192 self.error.node()
193 }
194}
195
196impl std::fmt::Display for PositionedError {
197 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
198 match &self.position {
199 Some(p) => write!(f, "[{}] {}", p.render(), self.error),
200 None => self.error.fmt(f),
201 }
202 }
203}
204
205impl std::error::Error for PositionedError {}
206
207impl From<TypeError> for PositionedError {
208 fn from(e: TypeError) -> Self {
209 Self::without_position(e)
210 }
211}