1pub use type_internal::*;
16
17pub(crate) use all_of::*;
18pub(crate) use type_origin::*;
19pub(crate) use unification::*;
20
21mod all_of;
22mod type_internal;
23mod type_origin;
24mod unification;
25
26use crate::instance_type::InstanceType;
27use crate::rib_source_span::SourceSpan;
28use crate::type_inference::GetTypeHint;
29use crate::TypeName;
30use bigdecimal::BigDecimal;
31use golem_wasm_ast::analysis::*;
32use std::fmt::{Display, Formatter};
33use std::hash::{Hash, Hasher};
34use std::ops::Deref;
35
36#[derive(Debug, Clone, Eq, PartialOrd, Ord)]
37pub struct InferredType {
38 pub inner: Box<TypeInternal>,
39 pub origin: TypeOrigin,
40}
41
42impl InferredType {
43 pub fn originated_at(&self, source_span: &SourceSpan) -> InferredType {
44 self.add_origin(TypeOrigin::OriginatedAt(source_span.clone()))
45 }
46
47 pub fn origin(&self) -> TypeOrigin {
48 self.origin.clone()
49 }
50
51 pub fn source_span(&self) -> Option<SourceSpan> {
52 let origin = self.origin();
53
54 match origin {
55 TypeOrigin::Default(_) => None,
56 TypeOrigin::NoOrigin => None,
57 TypeOrigin::Declared(_) => None,
58 TypeOrigin::Multiple(origins) => {
59 let mut source_span = None;
60 for origin in origins {
61 if let TypeOrigin::OriginatedAt(loc) = origin {
62 source_span = Some(loc.clone());
63 break;
64 }
65 }
66 source_span
67 }
68 TypeOrigin::OriginatedAt(_) => None,
69 }
70 }
71
72 pub fn as_number(&self) -> Result<InferredNumber, String> {
73 fn go(with_origin: &InferredType, found: &mut Vec<InferredNumber>) -> Result<(), String> {
74 match with_origin.inner.deref() {
75 TypeInternal::S8 => {
76 found.push(InferredNumber::S8);
77 Ok(())
78 }
79 TypeInternal::U8 => {
80 found.push(InferredNumber::U8);
81 Ok(())
82 }
83 TypeInternal::S16 => {
84 found.push(InferredNumber::S16);
85 Ok(())
86 }
87 TypeInternal::U16 => {
88 found.push(InferredNumber::U16);
89 Ok(())
90 }
91 TypeInternal::S32 => {
92 found.push(InferredNumber::S32);
93 Ok(())
94 }
95 TypeInternal::U32 => {
96 found.push(InferredNumber::U32);
97 Ok(())
98 }
99 TypeInternal::S64 => {
100 found.push(InferredNumber::S64);
101 Ok(())
102 }
103 TypeInternal::U64 => {
104 found.push(InferredNumber::U64);
105 Ok(())
106 }
107 TypeInternal::F32 => {
108 found.push(InferredNumber::F32);
109 Ok(())
110 }
111 TypeInternal::F64 => {
112 found.push(InferredNumber::F64);
113 Ok(())
114 }
115 TypeInternal::AllOf(all_variables) => {
116 let mut previous: Option<InferredNumber> = None;
117 for variable in all_variables {
118 go(variable, found)?;
119
120 if let Some(current) = found.first() {
121 match &previous {
122 None => {
123 previous = Some(current.clone());
124 found.push(current.clone());
125 }
126 Some(previous) => {
127 if previous != current {
128 return Err(format!(
129 "expected the same type of number. But found {current}, {previous}"
130 ));
131 }
132
133 found.push(current.clone());
134 }
135 }
136 } else {
137 return Err("failed to get a number".to_string());
138 }
139 }
140
141 Ok(())
142 }
143 TypeInternal::Range { .. } => Err("used as range".to_string()),
144 TypeInternal::Bool => Err(format!("used as {}", "bool")),
145 TypeInternal::Chr => Err(format!("used as {}", "char")),
146 TypeInternal::Str => Err(format!("used as {}", "string")),
147 TypeInternal::List(_) => Err(format!("used as {}", "list")),
148 TypeInternal::Tuple(_) => Err(format!("used as {}", "tuple")),
149 TypeInternal::Record(_) => Err(format!("used as {}", "record")),
150 TypeInternal::Flags(_) => Err(format!("used as {}", "flags")),
151 TypeInternal::Enum(_) => Err(format!("used as {}", "enum")),
152 TypeInternal::Option(_) => Err(format!("used as {}", "option")),
153 TypeInternal::Result { .. } => Err(format!("used as {}", "result")),
154 TypeInternal::Variant(_) => Err(format!("used as {}", "variant")),
155 TypeInternal::Unknown => Err("found unknown".to_string()),
156 TypeInternal::Sequence(_) => {
157 Err(format!("used as {}", "function-multi-parameter-return"))
158 }
159 TypeInternal::Resource { .. } => Err(format!("used as {}", "resource")),
160 TypeInternal::Instance { .. } => Err(format!("used as {}", "instance")),
161 }
162 }
163
164 let mut found: Vec<InferredNumber> = vec![];
165 go(self, &mut found)?;
166 found.first().cloned().ok_or("Failed".to_string())
167 }
168
169 pub fn bool() -> InferredType {
170 InferredType {
171 inner: Box::new(TypeInternal::Bool),
172 origin: TypeOrigin::NoOrigin,
173 }
174 }
175
176 pub fn char() -> InferredType {
177 InferredType {
178 inner: Box::new(TypeInternal::Chr),
179 origin: TypeOrigin::NoOrigin,
180 }
181 }
182
183 pub fn contains_only_number(&self) -> bool {
184 match self.inner.deref() {
185 TypeInternal::S8
186 | TypeInternal::U8
187 | TypeInternal::S16
188 | TypeInternal::U16
189 | TypeInternal::S32
190 | TypeInternal::U32
191 | TypeInternal::S64
192 | TypeInternal::U64
193 | TypeInternal::F32
194 | TypeInternal::F64 => true,
195 TypeInternal::Bool => false,
196 TypeInternal::Chr => false,
197 TypeInternal::Str => false,
198 TypeInternal::List(_) => false,
199 TypeInternal::Tuple(_) => false,
200 TypeInternal::Record(_) => false,
201 TypeInternal::Flags(_) => false,
202 TypeInternal::Enum(_) => false,
203 TypeInternal::Option(_) => false,
204 TypeInternal::Result { .. } => false,
205 TypeInternal::Variant(_) => false,
206 TypeInternal::Resource { .. } => false,
207 TypeInternal::Range { .. } => false,
208 TypeInternal::Instance { .. } => false,
209 TypeInternal::Unknown => false,
210 TypeInternal::Sequence(_) => false,
211 TypeInternal::AllOf(types) => types.iter().all(|t| t.contains_only_number()),
212 }
213 }
214
215 pub fn declared_at(&self, source_span: SourceSpan) -> InferredType {
216 self.add_origin(TypeOrigin::Declared(source_span.clone()))
217 }
218
219 pub fn as_default(&self, default_type: DefaultType) -> InferredType {
220 let new_origin = TypeOrigin::Default(default_type);
221
222 InferredType {
223 inner: self.inner.clone(),
224 origin: self.origin.add_origin(new_origin),
225 }
226 }
227
228 pub fn enum_(cases: Vec<String>) -> InferredType {
229 InferredType {
230 inner: Box::new(TypeInternal::Enum(cases)),
231 origin: TypeOrigin::NoOrigin,
232 }
233 }
234
235 pub fn f32() -> InferredType {
236 InferredType {
237 inner: Box::new(TypeInternal::F32),
238 origin: TypeOrigin::NoOrigin,
239 }
240 }
241
242 pub fn f64() -> InferredType {
243 InferredType {
244 inner: Box::new(TypeInternal::F64),
245 origin: TypeOrigin::NoOrigin,
246 }
247 }
248
249 pub fn flags(flags: Vec<String>) -> InferredType {
250 InferredType {
251 inner: Box::new(TypeInternal::Flags(flags)),
252 origin: TypeOrigin::NoOrigin,
253 }
254 }
255
256 pub fn instance(instance_type: InstanceType) -> InferredType {
257 InferredType {
258 inner: Box::new(TypeInternal::Instance {
259 instance_type: Box::new(instance_type),
260 }),
261 origin: TypeOrigin::NoOrigin,
262 }
263 }
264
265 pub fn internal_type(&self) -> &TypeInternal {
266 self.inner.as_ref()
267 }
268
269 pub fn internal_type_mut(&mut self) -> &mut TypeInternal {
270 self.inner.as_mut()
271 }
272
273 pub fn list(inner: InferredType) -> InferredType {
274 InferredType {
275 inner: Box::new(TypeInternal::List(inner)),
276 origin: TypeOrigin::NoOrigin,
277 }
278 }
279
280 pub fn new(inferred_type: TypeInternal, origin: TypeOrigin) -> InferredType {
281 InferredType {
282 inner: Box::new(inferred_type),
283 origin,
284 }
285 }
286
287 pub fn option(inner: InferredType) -> InferredType {
288 InferredType {
289 inner: Box::new(TypeInternal::Option(inner)),
290 origin: TypeOrigin::NoOrigin,
291 }
292 }
293
294 pub fn range(from: InferredType, to: Option<InferredType>) -> InferredType {
295 InferredType {
296 inner: Box::new(TypeInternal::Range { from, to }),
297 origin: TypeOrigin::NoOrigin,
298 }
299 }
300
301 pub fn eliminate_default(inferred_types: Vec<&InferredType>) -> Vec<&InferredType> {
302 inferred_types
303 .into_iter()
304 .filter(|&t| !t.origin.is_default())
305 .collect::<Vec<_>>()
306 }
307
308 pub fn record(fields: Vec<(String, InferredType)>) -> InferredType {
309 InferredType {
310 inner: Box::new(TypeInternal::Record(fields)),
311 origin: TypeOrigin::NoOrigin,
312 }
313 }
314
315 pub fn resolved(inferred_type: TypeInternal) -> InferredType {
316 InferredType {
317 inner: Box::new(inferred_type),
318 origin: TypeOrigin::NoOrigin,
319 }
320 }
321
322 pub fn resource(
323 resource_id: u64,
324 resource_mode: u8,
325 owner: Option<String>,
326 name: Option<String>,
327 ) -> InferredType {
328 InferredType {
329 inner: Box::new(TypeInternal::Resource {
330 resource_id,
331 resource_mode,
332 owner,
333 name,
334 }),
335 origin: TypeOrigin::NoOrigin,
336 }
337 }
338
339 pub fn result(ok: Option<InferredType>, error: Option<InferredType>) -> InferredType {
340 InferredType {
341 inner: Box::new(TypeInternal::Result { ok, error }),
342 origin: TypeOrigin::NoOrigin,
343 }
344 }
345
346 pub fn sequence(inferred_types: Vec<InferredType>) -> InferredType {
347 InferredType {
348 inner: Box::new(TypeInternal::Sequence(inferred_types)),
349 origin: TypeOrigin::NoOrigin,
350 }
351 }
352
353 pub fn string() -> InferredType {
354 InferredType {
355 inner: Box::new(TypeInternal::Str),
356 origin: TypeOrigin::NoOrigin,
357 }
358 }
359
360 pub fn s8() -> InferredType {
361 InferredType {
362 inner: Box::new(TypeInternal::S8),
363 origin: TypeOrigin::NoOrigin,
364 }
365 }
366
367 pub fn s16() -> InferredType {
368 InferredType {
369 inner: Box::new(TypeInternal::S16),
370 origin: TypeOrigin::NoOrigin,
371 }
372 }
373
374 pub fn s32() -> InferredType {
375 InferredType {
376 inner: Box::new(TypeInternal::S32),
377 origin: TypeOrigin::NoOrigin,
378 }
379 }
380
381 pub fn s64() -> InferredType {
382 InferredType {
383 inner: Box::new(TypeInternal::S64),
384 origin: TypeOrigin::NoOrigin,
385 }
386 }
387
388 pub fn tuple(inner: Vec<InferredType>) -> InferredType {
389 InferredType {
390 inner: Box::new(TypeInternal::Tuple(inner)),
391 origin: TypeOrigin::NoOrigin,
392 }
393 }
394
395 pub fn u8() -> InferredType {
396 InferredType {
397 inner: Box::new(TypeInternal::U8),
398 origin: TypeOrigin::NoOrigin,
399 }
400 }
401
402 pub fn unit() -> InferredType {
403 InferredType::tuple(vec![])
404 }
405
406 pub fn unknown() -> InferredType {
407 InferredType {
408 inner: Box::new(TypeInternal::Unknown),
409 origin: TypeOrigin::NoOrigin,
410 }
411 }
412
413 pub fn u16() -> InferredType {
414 InferredType {
415 inner: Box::new(TypeInternal::U16),
416 origin: TypeOrigin::NoOrigin,
417 }
418 }
419
420 pub fn u32() -> InferredType {
421 InferredType {
422 inner: Box::new(TypeInternal::U32),
423 origin: TypeOrigin::NoOrigin,
424 }
425 }
426
427 pub fn u64() -> InferredType {
428 InferredType {
429 inner: Box::new(TypeInternal::U64),
430 origin: TypeOrigin::NoOrigin,
431 }
432 }
433
434 pub fn variant(fields: Vec<(String, Option<InferredType>)>) -> InferredType {
435 InferredType {
436 inner: Box::new(TypeInternal::Variant(fields)),
437 origin: TypeOrigin::NoOrigin,
438 }
439 }
440
441 pub fn override_origin(&self, origin: TypeOrigin) -> InferredType {
442 InferredType {
443 inner: self.inner.clone(),
444 origin,
445 }
446 }
447
448 pub fn add_origin(&self, origin: TypeOrigin) -> InferredType {
449 let mut inferred_type = self.clone();
450 inferred_type.add_origin_mut(origin.clone());
451 inferred_type
452 }
453
454 pub fn add_origin_mut(&mut self, origin: TypeOrigin) {
455 self.origin = self.origin.add_origin(origin);
456 }
457
458 pub fn without_origin(inferred_type: TypeInternal) -> InferredType {
459 InferredType {
460 inner: Box::new(inferred_type),
461 origin: TypeOrigin::NoOrigin,
462 }
463 }
464
465 pub fn printable(&self) -> String {
466 TypeName::try_from(self.clone())
469 .map(|tn| tn.to_string())
470 .unwrap_or(self.get_type_hint().to_string())
471 }
472
473 pub fn all_of(types: Vec<InferredType>) -> InferredType {
474 get_merge_task(&types).complete()
475 }
476
477 pub fn is_unit(&self) -> bool {
478 match self.inner.deref() {
479 TypeInternal::Sequence(types) => types.is_empty(),
480 _ => false,
481 }
482 }
483 pub fn is_unknown(&self) -> bool {
484 matches!(self.inner.deref(), TypeInternal::Unknown)
485 }
486
487 pub fn is_valid_wit_type(&self) -> bool {
488 AnalysedType::try_from(self).is_ok()
489 }
490
491 pub fn is_all_of(&self) -> bool {
492 matches!(self.inner.deref(), TypeInternal::AllOf(_))
493 }
494
495 pub fn is_number(&self) -> bool {
496 matches!(
497 self.inner.deref(),
498 TypeInternal::S8
499 | TypeInternal::U8
500 | TypeInternal::S16
501 | TypeInternal::U16
502 | TypeInternal::S32
503 | TypeInternal::U32
504 | TypeInternal::S64
505 | TypeInternal::U64
506 | TypeInternal::F32
507 | TypeInternal::F64
508 )
509 }
510
511 pub fn is_string(&self) -> bool {
512 matches!(self.inner.deref(), TypeInternal::Str)
513 }
514
515 pub fn flatten_all_of_inferred_types(types: &Vec<InferredType>) -> Vec<InferredType> {
516 flatten_all_of_list(types)
517 }
518
519 pub fn unify(&self) -> Result<InferredType, UnificationFailureInternal> {
522 unify(self).map(|x| x.inferred_type())
523 }
524
525 pub fn merge(&self, new_inferred_type: InferredType) -> InferredType {
527 match (self.inner.deref(), new_inferred_type.inner.deref()) {
528 (TypeInternal::Unknown, _) => new_inferred_type.add_origin(self.origin.clone()),
529
530 (TypeInternal::AllOf(existing_types), TypeInternal::AllOf(new_types)) => {
531 let mut all_types = new_types.clone();
532 all_types.extend(existing_types.clone());
533
534 InferredType::all_of(all_types)
535 }
536
537 (TypeInternal::AllOf(existing_types), _) => {
538 let mut all_types = existing_types.clone();
539 all_types.push(new_inferred_type);
540
541 InferredType::all_of(all_types)
542 }
543
544 (_, TypeInternal::AllOf(new_types)) => {
545 let mut all_types = new_types.clone();
546 all_types.push(self.clone());
547
548 InferredType::all_of(all_types)
549 }
550
551 (_, _) => {
552 if self != &new_inferred_type && !new_inferred_type.is_unknown() {
553 InferredType::all_of(vec![self.clone(), new_inferred_type])
554 } else {
555 self.clone().add_origin(new_inferred_type.origin.clone())
556 }
557 }
558 }
559 }
560
561 pub fn from_type_variant(type_variant: &TypeVariant) -> InferredType {
562 let cases = type_variant
563 .cases
564 .iter()
565 .map(|name_type_pair| {
566 (
567 name_type_pair.name.clone(),
568 name_type_pair.typ.as_ref().map(|t| t.into()),
569 )
570 })
571 .collect();
572
573 InferredType::from_variant_cases(cases)
574 }
575
576 pub fn from_variant_cases(cases: Vec<(String, Option<InferredType>)>) -> InferredType {
577 InferredType::without_origin(TypeInternal::Variant(cases))
578 }
579
580 pub fn from_enum_cases(type_enum: &TypeEnum) -> InferredType {
581 InferredType::without_origin(TypeInternal::Enum(type_enum.cases.clone()))
582 }
583}
584
585impl PartialEq for InferredType {
586 fn eq(&self, other: &Self) -> bool {
587 self.inner == other.inner
588 }
589}
590
591impl Hash for InferredType {
592 fn hash<H: Hasher>(&self, state: &mut H) {
593 self.inner.hash(state);
594 }
595}
596
597#[derive(PartialEq, Clone, Debug)]
598pub enum InferredNumber {
599 S8,
600 U8,
601 S16,
602 U16,
603 S32,
604 U32,
605 S64,
606 U64,
607 F32,
608 F64,
609}
610
611impl From<&InferredNumber> for InferredType {
612 fn from(inferred_number: &InferredNumber) -> Self {
613 match inferred_number {
614 InferredNumber::S8 => InferredType::s8(),
615 InferredNumber::U8 => InferredType::u8(),
616 InferredNumber::S16 => InferredType::s16(),
617 InferredNumber::U16 => InferredType::u16(),
618 InferredNumber::S32 => InferredType::s32(),
619 InferredNumber::U32 => InferredType::u32(),
620 InferredNumber::S64 => InferredType::s64(),
621 InferredNumber::U64 => InferredType::u64(),
622 InferredNumber::F32 => InferredType::f32(),
623 InferredNumber::F64 => InferredType::f64(),
624 }
625 }
626}
627
628impl From<&DefaultType> for InferredType {
629 fn from(default_type: &DefaultType) -> Self {
630 match default_type {
631 DefaultType::String => InferredType::string().as_default(default_type.clone()),
632 DefaultType::F64 => InferredType::f64().as_default(default_type.clone()),
633 DefaultType::S32 => InferredType::s32().as_default(default_type.clone()),
634 }
635 }
636}
637
638impl From<&BigDecimal> for InferredType {
639 fn from(value: &BigDecimal) -> Self {
640 if value.fractional_digit_count() <= 0 {
641 InferredType::s32()
644 } else {
645 InferredType::f64()
647 }
648 }
649}
650
651#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
652pub struct RangeType {
653 from: Box<TypeInternal>,
654 to: Option<Box<TypeInternal>>,
655}
656
657impl Display for InferredNumber {
658 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
659 let type_name = TypeName::from(self);
660 write!(f, "{type_name}")
661 }
662}
663
664impl From<&AnalysedType> for InferredType {
665 fn from(analysed_type: &AnalysedType) -> Self {
666 match analysed_type {
667 AnalysedType::Bool(_) => InferredType::bool(),
668 AnalysedType::S8(_) => InferredType::s8(),
669 AnalysedType::U8(_) => InferredType::u8(),
670 AnalysedType::S16(_) => InferredType::s16(),
671 AnalysedType::U16(_) => InferredType::u16(),
672 AnalysedType::S32(_) => InferredType::s32(),
673 AnalysedType::U32(_) => InferredType::u32(),
674 AnalysedType::S64(_) => InferredType::s64(),
675 AnalysedType::U64(_) => InferredType::u64(),
676 AnalysedType::F32(_) => InferredType::f32(),
677 AnalysedType::F64(_) => InferredType::f64(),
678 AnalysedType::Chr(_) => InferredType::char(),
679 AnalysedType::Str(_) => InferredType::string(),
680 AnalysedType::List(t) => InferredType::list(t.inner.as_ref().into()),
681 AnalysedType::Tuple(ts) => {
682 InferredType::tuple(ts.items.iter().map(|t| t.into()).collect())
683 }
684 AnalysedType::Record(fs) => InferredType::record(
685 fs.fields
686 .iter()
687 .map(|name_type| (name_type.name.clone(), (&name_type.typ).into()))
688 .collect(),
689 ),
690 AnalysedType::Flags(vs) => InferredType::flags(vs.names.clone()),
691 AnalysedType::Enum(vs) => InferredType::from_enum_cases(vs),
692 AnalysedType::Option(t) => InferredType::option(t.inner.as_ref().into()),
693 AnalysedType::Result(golem_wasm_ast::analysis::TypeResult { ok, err, .. }) => {
694 InferredType::result(
695 ok.as_ref().map(|t| t.as_ref().into()),
696 err.as_ref().map(|t| t.as_ref().into()),
697 )
698 }
699 AnalysedType::Variant(vs) => InferredType::from_type_variant(vs),
700 AnalysedType::Handle(TypeHandle {
701 resource_id,
702 mode,
703 name,
704 owner,
705 }) => InferredType::resource(
706 resource_id.0,
707 match mode {
708 AnalysedResourceMode::Owned => 0,
709 AnalysedResourceMode::Borrowed => 1,
710 },
711 owner.clone(),
712 name.clone(),
713 ),
714 }
715 }
716}