1use core::fmt;
4
5use arithmetic_parser::UnsupportedType;
6
7use crate::{
8 PrimitiveType, TupleIndex, TupleLen, Type,
9 alloc::{Box, HashSet, String},
10 arith::Constraint,
11 ast::AstConversionError,
12 error::ErrorPathFragment,
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) => {
152 write!(formatter, "Type `{rhs}` is not assignable to type `{lhs}`")
153 }
154 Self::TupleLenMismatch {
155 lhs,
156 rhs,
157 context: TupleContext::FnArgs,
158 } => write!(
159 formatter,
160 "Function expects {lhs} args, but is called with {rhs} args"
161 ),
162 Self::TupleLenMismatch { lhs, rhs, .. } => write!(
163 formatter,
164 "Expected a tuple with {lhs} elements, got one with {rhs} elements"
165 ),
166
167 Self::UndefinedVar(name) => write!(formatter, "Variable `{name}` is not defined"),
168
169 Self::RecursiveType(ty) => write!(
170 formatter,
171 "Cannot unify type 'T with a type containing it: {ty}"
172 ),
173
174 Self::RepeatedAssignment(name) => {
175 write!(
176 formatter,
177 "Repeated assignment to the same variable `{name}`"
178 )
179 }
180
181 Self::InvalidFieldName(name) => {
182 write!(formatter, "`{name}` is not a valid field name")
183 }
184 Self::CannotIndex => formatter.write_str("Value cannot be indexed"),
185 Self::UnsupportedIndex => formatter.write_str("Unsupported indexing operation"),
186 Self::IndexOutOfBounds { index, len } => write!(
187 formatter,
188 "Attempting to get element {index} from tuple with length {len}"
189 ),
190
191 Self::RepeatedField(name) => write!(formatter, "Repeated object field `{name}`"),
192 Self::CannotAccessFields => formatter.write_str("Value is not an object"),
193 Self::FieldsMismatch {
194 lhs_fields,
195 rhs_fields,
196 } => write!(
197 formatter,
198 "Cannot assign object with fields {rhs_fields:?} to object with fields {lhs_fields:?}"
199 ),
200 Self::MissingFields {
201 fields,
202 available_fields,
203 } => write!(
204 formatter,
205 "Missing field(s) {fields:?} from object (available fields: {available_fields:?})"
206 ),
207
208 Self::UnresolvedParam => {
209 formatter.write_str("Params not instantiated into variables cannot be unified")
210 }
211
212 Self::FailedConstraint { ty, constraint } => {
213 write!(formatter, "Type `{ty}` fails constraint `{constraint}`")
214 }
215 Self::DynamicLen(len) => {
216 write!(formatter, "Length `{len}` is required to be static")
217 }
218
219 Self::UnsupportedFeature(ty) => write!(formatter, "Unsupported {ty}"),
220 Self::UnsupportedType(ty) => write!(formatter, "Unsupported type: {ty}"),
221 Self::UnsupportedParam => {
222 formatter.write_str("Params in declared function types are not supported yet")
223 }
224
225 Self::AstConversion(err) => {
226 write!(formatter, "Error instantiating type from annotation: {err}")
227 }
228 }
229 }
230}
231
232#[cfg(feature = "std")]
233impl<Prim: PrimitiveType> std::error::Error for ErrorKind<Prim> {
234 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
235 match self {
236 Self::AstConversion(err) => Some(err),
237 _ => None,
238 }
239 }
240}
241
242impl<Prim: PrimitiveType> ErrorKind<Prim> {
243 pub fn unsupported<T: Into<UnsupportedType>>(ty: T) -> Self {
245 Self::UnsupportedFeature(ty.into())
246 }
247
248 pub fn failed_constraint(ty: Type<Prim>, constraint: impl Constraint<Prim> + Clone) -> Self {
250 Self::FailedConstraint {
251 ty: Box::new(ty),
252 constraint: Box::new(constraint),
253 }
254 }
255}