Skip to main content

rib/type_inference/
errors.rs

1use crate::rib_source_span::SourceSpan;
2use crate::type_inference::type_hint::{GetTypeHint, TypeHint};
3use crate::wit_type::WitType;
4use crate::{InferredType, Path, PathElem};
5
6#[derive(Debug, Clone)]
7pub struct AmbiguousTypeError {
8    pub ambiguous_expr_source_span: SourceSpan,
9    pub ambiguous_types: Vec<String>,
10    pub additional_error_details: Vec<String>,
11}
12
13impl AmbiguousTypeError {
14    pub fn new(
15        inferred_expr: &InferredType,
16        source_span: &SourceSpan,
17        expected: &TypeHint,
18    ) -> AmbiguousTypeError {
19        let actual_kind = inferred_expr.get_type_hint();
20        match actual_kind {
21            TypeHint::Ambiguous { possibilities } => {
22                let possibilities = possibilities
23                    .into_iter()
24                    .map(|x| x.to_string())
25                    .collect::<Vec<_>>();
26
27                AmbiguousTypeError {
28                    ambiguous_expr_source_span: source_span.clone(),
29                    ambiguous_types: possibilities,
30                    additional_error_details: vec![],
31                }
32            }
33            _ => AmbiguousTypeError {
34                ambiguous_expr_source_span: source_span.clone(),
35                ambiguous_types: vec![expected.to_string(), inferred_expr.printable()],
36                additional_error_details: vec![],
37            },
38        }
39    }
40
41    pub fn with_additional_error_detail(&self, detail: &str) -> AmbiguousTypeError {
42        let mut error = self.clone();
43        error.additional_error_details.push(detail.to_string());
44        error
45    }
46}
47
48pub enum InvalidPatternMatchError {
49    ConstructorMismatch {
50        match_expr_source_span: SourceSpan,
51        constructor_name: String,
52    },
53    ArgSizeMismatch {
54        match_expr_source_span: SourceSpan,
55        constructor_name: String,
56        expected_arg_size: usize,
57        actual_arg_size: usize,
58    },
59}
60
61impl InvalidPatternMatchError {
62    pub fn constructor_type_mismatch(
63        match_expr_source_span: SourceSpan,
64        constructor_name: &str,
65    ) -> InvalidPatternMatchError {
66        InvalidPatternMatchError::ConstructorMismatch {
67            match_expr_source_span,
68            constructor_name: constructor_name.to_string(),
69        }
70    }
71
72    pub fn arg_size_mismatch(
73        match_expr_source_span: SourceSpan,
74        constructor_name: &str,
75        expected_arg_size: usize,
76        actual_arg_size: usize,
77    ) -> InvalidPatternMatchError {
78        InvalidPatternMatchError::ArgSizeMismatch {
79            match_expr_source_span,
80            expected_arg_size,
81            actual_arg_size,
82            constructor_name: constructor_name.to_string(),
83        }
84    }
85}
86
87#[derive(Debug, Clone)]
88pub struct UnificationError {}
89
90#[derive(Clone, Debug)]
91pub struct TypeMismatchError {
92    pub source_span: SourceSpan,
93    pub expected_type: ExpectedType,
94    pub actual_type: ActualType,
95    pub field_path: Path,
96    pub additional_error_detail: Vec<String>,
97}
98
99#[derive(Clone, Debug)]
100pub enum ExpectedType {
101    WitType(WitType),
102    // If the expected type is not fully known yet but only a hint is available.
103    // Example: when compiler cannot proceed unless it is a `record`, or `list` etc
104    Hint(TypeHint),
105    InferredType(InferredType),
106}
107
108#[derive(Clone, Debug)]
109pub enum ActualType {
110    Inferred(InferredType),
111    // If the actual type is not fully known yet but only a hint is available
112    Hint(TypeHint),
113}
114
115impl TypeMismatchError {
116    pub fn updated_expected_type(&self, expected_type: &WitType) -> TypeMismatchError {
117        let mut mismatch_error: TypeMismatchError = self.clone();
118        mismatch_error.expected_type = ExpectedType::WitType(expected_type.clone());
119        mismatch_error
120    }
121
122    pub fn at_field(&self, field_name: String) -> TypeMismatchError {
123        let mut mismatch_error: TypeMismatchError = self.clone();
124        mismatch_error
125            .field_path
126            .push_front(PathElem::Field(field_name));
127        mismatch_error
128    }
129}
130
131// A type unification can fail either due to a type mismatch or due to unresolved types
132pub enum TypeUnificationError {
133    TypeMismatchError { error: TypeMismatchError },
134    UnresolvedTypesError { error: UnResolvedTypesError },
135}
136
137impl TypeUnificationError {
138    pub fn unresolved_types_error(
139        source_span: SourceSpan,
140        additional_messages: Vec<String>,
141    ) -> TypeUnificationError {
142        TypeUnificationError::UnresolvedTypesError {
143            error: UnResolvedTypesError {
144                source_span,
145                additional_messages,
146                help_messages: vec![],
147                path: Path::default(),
148            },
149        }
150    }
151    pub fn type_mismatch_error(
152        source_span: SourceSpan,
153        expected_type: InferredType,
154        actual_type: InferredType,
155        additional_error_detail: Vec<String>,
156    ) -> TypeUnificationError {
157        TypeUnificationError::TypeMismatchError {
158            error: TypeMismatchError {
159                source_span,
160                expected_type: ExpectedType::InferredType(expected_type),
161                actual_type: ActualType::Inferred(actual_type),
162                field_path: Path::default(),
163                additional_error_detail,
164            },
165        }
166    }
167}
168
169#[derive(Debug, Clone)]
170pub struct UnResolvedTypesError {
171    pub source_span: SourceSpan,
172    pub help_messages: Vec<String>,
173    pub path: Path,
174    pub additional_messages: Vec<String>,
175}
176
177impl UnResolvedTypesError {
178    pub fn from(source_span: SourceSpan) -> Self {
179        let unresolved_types = UnResolvedTypesError {
180            source_span,
181            help_messages: Vec::new(),
182            path: Path::default(),
183            additional_messages: Vec::new(),
184        };
185
186        unresolved_types.with_default_help_messages()
187    }
188
189    pub fn with_default_help_messages(&self) -> Self {
190        self.with_help_message(
191            "try specifying the expected type explicitly",
192        ).with_help_message(
193            "if the issue persists, please review the script for potential type inconsistencies"
194        )
195    }
196
197    pub fn with_additional_error_detail(&self, message: impl AsRef<str>) -> UnResolvedTypesError {
198        let mut unresolved_error: UnResolvedTypesError = self.clone();
199        unresolved_error
200            .additional_messages
201            .push(message.as_ref().to_string());
202        unresolved_error
203    }
204
205    pub fn with_help_message(&self, message: impl AsRef<str>) -> UnResolvedTypesError {
206        let mut unresolved_error: UnResolvedTypesError = self.clone();
207        unresolved_error
208            .help_messages
209            .push(message.as_ref().to_string());
210
211        unresolved_error
212    }
213
214    pub fn at_field(&self, field_name: String) -> UnResolvedTypesError {
215        let mut unresolved_error: UnResolvedTypesError = self.clone();
216        unresolved_error
217            .path
218            .push_front(PathElem::Field(field_name));
219        unresolved_error
220    }
221
222    pub fn at_index(&self, index: usize) -> UnResolvedTypesError {
223        let mut unresolved_error: UnResolvedTypesError = self.clone();
224        unresolved_error.path.push_front(PathElem::Index(index));
225        unresolved_error
226    }
227}
228
229#[derive(Debug, Clone)]
230pub enum FunctionCallError {
231    InvalidFunctionCall {
232        function_name: String,
233        source_span: SourceSpan,
234        message: String,
235    },
236    TypeMisMatch {
237        function_name: String,
238        argument_source_span: SourceSpan,
239        error: TypeMismatchError,
240    },
241    MissingRecordFields {
242        function_name: String,
243        argument_source_span: SourceSpan,
244        missing_fields: Vec<Path>,
245    },
246    UnResolvedTypes {
247        function_name: String,
248        source_span: SourceSpan,
249        unresolved_error: UnResolvedTypesError,
250        expected_type: WitType,
251    },
252
253    InvalidResourceMethodCall {
254        resource_method_name: String,
255        invalid_lhs_source_span: SourceSpan,
256    },
257
258    ArgumentSizeMisMatch {
259        function_name: String,
260        source_span: SourceSpan,
261        expected: usize,
262        provided: usize,
263    },
264}
265
266impl FunctionCallError {
267    pub fn invalid_function_call(
268        function_name: &str,
269        function_source_span: SourceSpan,
270        message: impl AsRef<str>,
271    ) -> FunctionCallError {
272        FunctionCallError::InvalidFunctionCall {
273            function_name: function_name.to_string(),
274            source_span: function_source_span,
275            message: message.as_ref().to_string(),
276        }
277    }
278}
279
280pub struct InvalidWorkerName {
281    pub worker_name_source_span: SourceSpan,
282    pub message: String,
283}
284
285#[derive(Clone)]
286pub struct CustomError {
287    pub source_span: SourceSpan,
288    pub message: String,
289    pub help_message: Vec<String>,
290}
291
292impl CustomError {
293    pub fn new(source_span: SourceSpan, message: impl AsRef<str>) -> CustomError {
294        CustomError {
295            source_span,
296            message: message.as_ref().to_string(),
297            help_message: Vec::new(),
298        }
299    }
300
301    pub fn with_help_message(&self, message: impl AsRef<str>) -> CustomError {
302        let mut custom_error: CustomError = self.clone();
303        custom_error.help_message.push(message.as_ref().to_string());
304        custom_error
305    }
306}