1use crate::type_inference::type_hint::{GetTypeHint, TypeHint};
16use crate::{Expr, InferredType, Path, PathElem};
17use golem_wasm_ast::analysis::AnalysedType;
18use std::fmt;
19use std::fmt::Display;
20
21#[derive(Debug, Clone)]
22pub struct AmbiguousTypeError {
23 pub expr: Expr,
24 pub ambiguous_types: Vec<String>,
25 pub additional_error_details: Vec<String>,
26}
27
28impl AmbiguousTypeError {
29 pub fn new(
30 inferred_expr: &InferredType,
31 expr: &Expr,
32 expected: &TypeHint,
33 ) -> AmbiguousTypeError {
34 let actual_kind = inferred_expr.get_type_hint();
35 match actual_kind {
36 TypeHint::Ambiguous { possibilities } => {
37 let possibilities = possibilities
38 .into_iter()
39 .map(|x| x.to_string())
40 .collect::<Vec<_>>();
41
42 AmbiguousTypeError {
43 expr: expr.clone(),
44 ambiguous_types: possibilities,
45 additional_error_details: vec![],
46 }
47 }
48 _ => AmbiguousTypeError {
49 expr: expr.clone(),
50 ambiguous_types: vec![expected.to_string(), inferred_expr.printable()],
51 additional_error_details: vec![],
52 },
53 }
54 }
55
56 pub fn with_additional_error_detail(&self, detail: &str) -> AmbiguousTypeError {
57 let mut error = self.clone();
58 error.additional_error_details.push(detail.to_string());
59 error
60 }
61}
62
63pub enum InvalidPatternMatchError {
64 ConstructorMismatch {
65 predicate_expr: Expr,
66 match_expr: Expr,
67 constructor_name: String,
68 },
69 ArgSizeMismatch {
70 predicate_expr: Expr,
71 match_expr: Expr,
72 constructor_name: String,
73 expected_arg_size: usize,
74 actual_arg_size: usize,
75 },
76}
77
78impl InvalidPatternMatchError {
79 pub fn constructor_type_mismatch(
80 predicate_expr: &Expr,
81 match_expr: &Expr,
82 constructor_name: &str,
83 ) -> InvalidPatternMatchError {
84 InvalidPatternMatchError::ConstructorMismatch {
85 predicate_expr: predicate_expr.clone(),
86 match_expr: match_expr.clone(),
87 constructor_name: constructor_name.to_string(),
88 }
89 }
90
91 pub fn arg_size_mismatch(
92 predicate_expr: &Expr,
93 match_expr: &Expr,
94 constructor_name: &str,
95 expected_arg_size: usize,
96 actual_arg_size: usize,
97 ) -> InvalidPatternMatchError {
98 InvalidPatternMatchError::ArgSizeMismatch {
99 predicate_expr: predicate_expr.clone(),
100 match_expr: match_expr.clone(),
101 expected_arg_size,
102 actual_arg_size,
103 constructor_name: constructor_name.to_string(),
104 }
105 }
106}
107
108#[derive(Clone, Debug)]
109pub struct TypeMismatchError {
110 pub expr_with_wrong_type: Expr,
111 pub parent_expr: Option<Expr>,
112 pub expected_type: ExpectedType,
113 pub actual_type: ActualType,
114 pub field_path: Path,
115 pub additional_error_detail: Vec<String>,
116}
117
118#[derive(Clone, Debug)]
119pub enum ExpectedType {
120 AnalysedType(AnalysedType),
121 Hint(TypeHint),
122}
123
124#[derive(Clone, Debug)]
126pub enum ActualType {
127 Inferred(InferredType),
128 Hint(TypeHint),
129}
130
131impl TypeMismatchError {
132 pub fn updated_expected_type(&self, expected_type: &AnalysedType) -> TypeMismatchError {
133 let mut mismatch_error: TypeMismatchError = self.clone();
134 mismatch_error.expected_type = ExpectedType::AnalysedType(expected_type.clone());
135 mismatch_error
136 }
137
138 pub fn at_field(&self, field_name: String) -> TypeMismatchError {
139 let mut mismatch_error: TypeMismatchError = self.clone();
140 mismatch_error
141 .field_path
142 .push_front(PathElem::Field(field_name));
143 mismatch_error
144 }
145
146 pub fn with_actual_inferred_type(
147 expr: &Expr,
148 parent_expr: Option<&Expr>,
149 expected_type: AnalysedType,
150 actual_type: InferredType,
151 ) -> Self {
152 TypeMismatchError {
153 expr_with_wrong_type: expr.clone(),
154 parent_expr: parent_expr.cloned(),
155 expected_type: ExpectedType::AnalysedType(expected_type),
156 actual_type: ActualType::Inferred(actual_type),
157 field_path: Path::default(),
158 additional_error_detail: Vec::new(),
159 }
160 }
161
162 pub fn with_actual_type_kind(
163 expr: &Expr,
164 parent_expr: Option<&Expr>,
165 expected_type: AnalysedType,
166 actual_type: &TypeHint,
167 ) -> Self {
168 TypeMismatchError {
169 expr_with_wrong_type: expr.clone(),
170 parent_expr: parent_expr.cloned(),
171 expected_type: ExpectedType::AnalysedType(expected_type),
172 actual_type: ActualType::Hint(actual_type.clone()),
173 field_path: Path::default(),
174 additional_error_detail: Vec::new(),
175 }
176 }
177}
178
179pub struct MultipleUnResolvedTypesError(pub Vec<UnResolvedTypesError>);
180
181#[derive(Debug, Clone)]
182pub struct UnResolvedTypesError {
183 pub unresolved_expr: Expr,
184 pub parent_expr: Option<Expr>,
185 pub additional_messages: Vec<String>,
186 pub help_messages: Vec<String>,
187 pub path: Path,
188}
189
190impl UnResolvedTypesError {
191 pub fn from(expr: &Expr, parent_expr: Option<Expr>) -> Self {
192 let unresolved_types = UnResolvedTypesError {
193 unresolved_expr: expr.clone(),
194 additional_messages: Vec::new(),
195 parent_expr: parent_expr.clone(),
196 help_messages: Vec::new(),
197 path: Path::default(),
198 };
199
200 unresolved_types.with_default_help_messages()
201 }
202
203 pub fn with_default_help_messages(&self) -> Self {
204 self.with_help_message(
205 "try specifying the expected type explicitly",
206 ).with_help_message(
207 "if the issue persists, please review the script for potential type inconsistencies"
208 )
209 }
210
211 pub fn with_parent_expr(&self, expr: &Expr) -> UnResolvedTypesError {
212 let mut unresolved_error: UnResolvedTypesError = self.clone();
213 unresolved_error.parent_expr = Some(expr.clone());
214 unresolved_error
215 }
216
217 pub fn with_additional_error_detail(&self, message: impl AsRef<str>) -> UnResolvedTypesError {
218 let mut unresolved_error: UnResolvedTypesError = self.clone();
219 unresolved_error
220 .additional_messages
221 .push(message.as_ref().to_string());
222 unresolved_error
223 }
224
225 pub fn with_help_message(&self, message: impl AsRef<str>) -> UnResolvedTypesError {
226 let mut unresolved_error: UnResolvedTypesError = self.clone();
227 unresolved_error
228 .help_messages
229 .push(message.as_ref().to_string());
230
231 unresolved_error
232 }
233
234 pub fn at_field(&self, field_name: String) -> UnResolvedTypesError {
235 let mut unresolved_error: UnResolvedTypesError = self.clone();
236 unresolved_error
237 .path
238 .push_front(PathElem::Field(field_name));
239 unresolved_error
240 }
241
242 pub fn at_index(&self, index: usize) -> UnResolvedTypesError {
243 let mut unresolved_error: UnResolvedTypesError = self.clone();
244 unresolved_error.path.push_front(PathElem::Index(index));
245 unresolved_error
246 }
247}
248
249impl Display for UnResolvedTypesError {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 let span = self.unresolved_expr.source_span();
252
253 writeln!(
254 f,
255 "cannot determine the type of the following rib expression found at line {}, column {}",
256 span.start_line(),
257 span.start_column()
258 )?;
259
260 writeln!(f, "`{}`", self.unresolved_expr)?;
261
262 if let Some(parent) = &self.parent_expr {
263 writeln!(f, "found within:")?;
264 writeln!(f, "`{}`", parent)?;
265 }
266
267 if !self.additional_messages.is_empty() {
268 for message in &self.additional_messages {
269 writeln!(f, "{}", message)?;
270 }
271 }
272
273 Ok(())
274 }
275}
276
277#[derive(Debug, Clone)]
278pub enum FunctionCallError {
279 InvalidFunctionCall {
280 function_name: String,
281 expr: Expr,
282 message: String,
283 },
284 TypeMisMatch {
285 function_name: String,
286 argument: Expr,
287 error: TypeMismatchError,
288 },
289 MissingRecordFields {
290 function_name: String,
291 argument: Expr,
292 missing_fields: Vec<Path>,
293 },
294 UnResolvedTypes {
295 function_name: String,
296 argument: Expr,
297 unresolved_error: UnResolvedTypesError,
298 expected_type: AnalysedType,
299 },
300
301 InvalidResourceMethodCall {
302 resource_method_name: String,
303 invalid_lhs: Expr,
304 },
305
306 InvalidGenericTypeParameter {
307 generic_type_parameter: String,
308 expr: Expr,
309 message: String,
310 },
311
312 ArgumentSizeMisMatch {
313 function_name: String,
314 expr: Expr,
315 expected: usize,
316 provided: usize,
317 },
318}
319
320pub struct InvalidWorkerName {
321 pub worker_name_expr: Expr,
322 pub message: String,
323}
324
325#[derive(Clone)]
326pub struct CustomError {
327 pub expr: Expr,
328 pub message: String,
329 pub help_message: Vec<String>,
330}
331
332impl CustomError {
333 pub fn new(expr: &Expr, message: impl AsRef<str>) -> CustomError {
334 CustomError {
335 expr: expr.clone(),
336 message: message.as_ref().to_string(),
337 help_message: Vec::new(),
338 }
339 }
340
341 pub fn with_help_message(&self, message: impl AsRef<str>) -> CustomError {
342 let mut custom_error: CustomError = self.clone();
343 custom_error.help_message.push(message.as_ref().to_string());
344 custom_error
345 }
346}