1use std::{collections::HashSet, fmt};
4
5use crate::{
6 arith::Constraint, ast::AstConversionError, error::ErrorLocation, PrimitiveType, TupleIndex,
7 TupleLen, Type,
8};
9use arithmetic_parser::UnsupportedType;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13#[non_exhaustive]
14pub enum TupleContext {
15 Generic,
17 FnArgs,
19}
20
21impl TupleContext {
22 pub(crate) fn element(self, index: usize) -> ErrorLocation {
23 let index = TupleIndex::Start(index);
24 match self {
25 Self::Generic => ErrorLocation::TupleElement(Some(index)),
26 Self::FnArgs => ErrorLocation::FnArg(Some(index)),
27 }
28 }
29
30 pub(crate) fn end_element(self, index: usize) -> ErrorLocation {
31 let index = TupleIndex::End(index);
32 match self {
33 Self::Generic => ErrorLocation::TupleElement(Some(index)),
34 Self::FnArgs => ErrorLocation::FnArg(Some(index)),
35 }
36 }
37}
38
39#[derive(Debug, Clone)]
41#[non_exhaustive]
42pub enum ErrorKind<Prim: PrimitiveType> {
43 TypeMismatch(Type<Prim>, Type<Prim>),
45 TupleLenMismatch {
47 lhs: TupleLen,
50 rhs: TupleLen,
53 context: TupleContext,
55 },
56 UndefinedVar(String),
58 RecursiveType(Type<Prim>),
60
61 RepeatedAssignment(String),
63
64 InvalidFieldName(String),
66 CannotIndex,
68 UnsupportedIndex,
71 IndexOutOfBounds {
73 index: usize,
75 len: TupleLen,
77 },
78
79 RepeatedField(String),
81 CannotAccessFields,
83 FieldsMismatch {
85 lhs_fields: HashSet<String>,
87 rhs_fields: HashSet<String>,
89 },
90 MissingFields {
92 fields: HashSet<String>,
94 available_fields: HashSet<String>,
96 },
97
98 UnresolvedParam,
107
108 FailedConstraint {
110 ty: Type<Prim>,
112 constraint: Box<dyn Constraint<Prim>>,
114 },
115 DynamicLen(TupleLen),
119
120 UnsupportedFeature(UnsupportedType),
122
123 UnsupportedType(Type<Prim>),
130
131 UnsupportedParam,
140
141 AstConversion(AstConversionError),
143}
144
145impl<Prim: PrimitiveType> fmt::Display for ErrorKind<Prim> {
146 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
147 match self {
148 Self::TypeMismatch(lhs, rhs) => write!(
149 formatter,
150 "Type `{}` is not assignable to type `{}`",
151 rhs, lhs
152 ),
153 Self::TupleLenMismatch {
154 lhs,
155 rhs,
156 context: TupleContext::FnArgs,
157 } => write!(
158 formatter,
159 "Function expects {} args, but is called with {} args",
160 lhs, rhs
161 ),
162 Self::TupleLenMismatch { lhs, rhs, .. } => write!(
163 formatter,
164 "Expected a tuple with {} elements, got one with {} elements",
165 lhs, rhs
166 ),
167
168 Self::UndefinedVar(name) => write!(formatter, "Variable `{}` is not defined", name),
169
170 Self::RecursiveType(ty) => write!(
171 formatter,
172 "Cannot unify type 'T with a type containing it: {}",
173 ty
174 ),
175
176 Self::RepeatedAssignment(name) => {
177 write!(
178 formatter,
179 "Repeated assignment to the same variable `{}`",
180 name
181 )
182 }
183
184 Self::InvalidFieldName(name) => {
185 write!(formatter, "`{}` is not a valid field name", name)
186 }
187 Self::CannotIndex => formatter.write_str("Value cannot be indexed"),
188 Self::UnsupportedIndex => formatter.write_str("Unsupported indexing operation"),
189 Self::IndexOutOfBounds { index, len } => write!(
190 formatter,
191 "Attempting to get element {} from tuple with length {}",
192 index, len
193 ),
194
195 Self::RepeatedField(name) => write!(formatter, "Repeated object field `{}`", name),
196 Self::CannotAccessFields => formatter.write_str("Value is not an object"),
197 Self::FieldsMismatch {
198 lhs_fields,
199 rhs_fields,
200 } => write!(
201 formatter,
202 "Cannot assign object with fields {rhs:?} to object with fields {lhs:?}",
203 lhs = lhs_fields,
204 rhs = rhs_fields
205 ),
206 Self::MissingFields {
207 fields,
208 available_fields,
209 } => write!(
210 formatter,
211 "Missing field(s) {:?} from object (available fields: {:?})",
212 fields, available_fields
213 ),
214
215 Self::UnresolvedParam => {
216 formatter.write_str("Params not instantiated into variables cannot be unified")
217 }
218
219 Self::FailedConstraint { ty, constraint } => {
220 write!(formatter, "Type `{}` fails constraint `{}`", ty, constraint)
221 }
222 Self::DynamicLen(len) => {
223 write!(formatter, "Length `{}` is required to be static", len)
224 }
225
226 Self::UnsupportedFeature(ty) => write!(formatter, "Unsupported {}", ty),
227 Self::UnsupportedType(ty) => write!(formatter, "Unsupported type: {}", ty),
228 Self::UnsupportedParam => {
229 formatter.write_str("Params in declared function types are not supported yet")
230 }
231
232 Self::AstConversion(err) => write!(
233 formatter,
234 "Error instantiating type from annotation: {}",
235 err
236 ),
237 }
238 }
239}
240
241impl<Prim: PrimitiveType> std::error::Error for ErrorKind<Prim> {
242 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
243 match self {
244 Self::AstConversion(err) => Some(err),
245 _ => None,
246 }
247 }
248}
249
250impl<Prim: PrimitiveType> ErrorKind<Prim> {
251 pub fn unsupported<T: Into<UnsupportedType>>(ty: T) -> Self {
253 Self::UnsupportedFeature(ty.into())
254 }
255
256 pub fn failed_constraint(ty: Type<Prim>, constraint: impl Constraint<Prim> + Clone) -> Self {
258 Self::FailedConstraint {
259 ty,
260 constraint: Box::new(constraint),
261 }
262 }
263}