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