1pub(crate) use flatten::*;
16mod flatten;
17mod unification;
18use crate::instance_type::InstanceType;
19use crate::type_inference::type_hint::GetTypeHint;
20use crate::TypeName;
21use bigdecimal::num_bigint::Sign;
22use bigdecimal::BigDecimal;
23use golem_wasm_ast::analysis::analysed_type::*;
24use golem_wasm_ast::analysis::*;
25use std::collections::HashSet;
26use std::fmt::{Display, Formatter};
27use std::hash::{Hash, Hasher};
28
29#[derive(Debug, Clone, Ord, PartialOrd)]
30pub enum InferredType {
31 Bool,
32 S8,
33 U8,
34 S16,
35 U16,
36 S32,
37 U32,
38 S64,
39 U64,
40 F32,
41 F64,
42 Chr,
43 Str,
44 List(Box<InferredType>),
45 Tuple(Vec<InferredType>),
46 Record(Vec<(String, InferredType)>),
47 Flags(Vec<String>),
48 Enum(Vec<String>),
49 Option(Box<InferredType>),
50 Result {
51 ok: Option<Box<InferredType>>,
52 error: Option<Box<InferredType>>,
53 },
54 Variant(Vec<(String, Option<InferredType>)>),
55 Resource {
56 resource_id: u64,
57 resource_mode: u8,
58 },
59 Range {
60 from: Box<InferredType>,
61 to: Option<Box<InferredType>>,
62 },
63 Instance {
64 instance_type: Box<InstanceType>,
65 },
66 OneOf(Vec<InferredType>),
67 AllOf(Vec<InferredType>),
68 Unknown,
69 Sequence(Vec<InferredType>),
71}
72
73impl Eq for InferredType {}
74
75impl Hash for InferredType {
76 fn hash<H: Hasher>(&self, state: &mut H) {
77 match self {
78 InferredType::Bool => 0.hash(state),
79 InferredType::S8 => 1.hash(state),
80 InferredType::U8 => 2.hash(state),
81 InferredType::S16 => 3.hash(state),
82 InferredType::U16 => 4.hash(state),
83 InferredType::S32 => 5.hash(state),
84 InferredType::U32 => 6.hash(state),
85 InferredType::S64 => 7.hash(state),
86 InferredType::U64 => 8.hash(state),
87 InferredType::F32 => 9.hash(state),
88 InferredType::F64 => 10.hash(state),
89 InferredType::Chr => 11.hash(state),
90 InferredType::Str => 12.hash(state),
91 InferredType::List(inner) => {
92 13.hash(state);
93 inner.hash(state);
94 }
95 InferredType::Tuple(inner) => {
96 14.hash(state);
97 inner.hash(state);
98 }
99 InferredType::Record(fields) => {
100 15.hash(state);
101 let mut sorted_fields = fields.clone();
102 sorted_fields.sort_by(|a, b| a.0.cmp(&b.0));
103 sorted_fields.hash(state);
104 }
105 InferredType::Flags(flags) => {
106 16.hash(state);
107 let mut sorted_flags = flags.clone();
108 sorted_flags.sort();
109 sorted_flags.hash(state);
110 }
111 InferredType::Enum(variants) => {
112 17.hash(state);
113 let mut sorted_variants = variants.clone();
114 sorted_variants.sort();
115 sorted_variants.hash(state);
116 }
117 InferredType::Option(inner) => {
118 18.hash(state);
119 inner.hash(state);
120 }
121 InferredType::Result { ok, error } => {
122 19.hash(state);
123 ok.hash(state);
124 error.hash(state);
125 }
126 InferredType::Variant(fields) => {
127 20.hash(state);
128 let mut sorted_fields = fields.clone();
129 sorted_fields.sort_by(|a, b| a.0.cmp(&b.0));
130 sorted_fields.hash(state);
131 }
132 InferredType::Resource {
133 resource_id,
134 resource_mode,
135 } => {
136 21.hash(state);
137 resource_id.hash(state);
138 resource_mode.hash(state);
139 }
140 InferredType::Range { from, to } => {
141 22.hash(state);
142 from.hash(state);
143 to.hash(state);
144 }
145 InferredType::Instance { instance_type } => {
146 23.hash(state);
147 instance_type.hash(state);
148 }
149 InferredType::OneOf(types)
150 | InferredType::AllOf(types)
151 | InferredType::Sequence(types) => {
152 24.hash(state);
153 let mut sorted_types = types.clone();
154 sorted_types.sort();
155 sorted_types.hash(state);
156 }
157 InferredType::Unknown => 25.hash(state),
158 }
159 }
160}
161
162impl PartialEq for InferredType {
163 fn eq(&self, other: &Self) -> bool {
164 match (self, other) {
165 (InferredType::Bool, InferredType::Bool) => true,
166 (InferredType::S8, InferredType::S8) => true,
167 (InferredType::U8, InferredType::U8) => true,
168 (InferredType::S16, InferredType::S16) => true,
169 (InferredType::U16, InferredType::U16) => true,
170 (InferredType::S32, InferredType::S32) => true,
171 (InferredType::U32, InferredType::U32) => true,
172 (InferredType::S64, InferredType::S64) => true,
173 (InferredType::U64, InferredType::U64) => true,
174 (InferredType::F32, InferredType::F32) => true,
175 (InferredType::F64, InferredType::F64) => true,
176 (InferredType::Chr, InferredType::Chr) => true,
177 (InferredType::Str, InferredType::Str) => true,
178 (InferredType::List(t1), InferredType::List(t2)) => t1 == t2,
179 (InferredType::Tuple(ts1), InferredType::Tuple(ts2)) => ts1 == ts2,
180 (InferredType::Record(fs1), InferredType::Record(fs2)) => fs1 == fs2,
181 (InferredType::Flags(vs1), InferredType::Flags(vs2)) => vs1 == vs2,
182 (InferredType::Enum(vs1), InferredType::Enum(vs2)) => vs1 == vs2,
183 (InferredType::Option(t1), InferredType::Option(t2)) => t1 == t2,
184 (
185 InferredType::Result {
186 ok: ok1,
187 error: error1,
188 },
189 InferredType::Result {
190 ok: ok2,
191 error: error2,
192 },
193 ) => ok1 == ok2 && error1 == error2,
194 (InferredType::Variant(vs1), InferredType::Variant(vs2)) => vs1 == vs2,
195 (
196 InferredType::Resource {
197 resource_id: id1,
198 resource_mode: mode1,
199 },
200 InferredType::Resource {
201 resource_id: id2,
202 resource_mode: mode2,
203 },
204 ) => id1 == id2 && mode1 == mode2,
205 (
206 InferredType::Range {
207 from: from1,
208 to: to1,
209 },
210 InferredType::Range {
211 from: from2,
212 to: to2,
213 },
214 ) => from1 == from2 && to1 == to2,
215 (
216 InferredType::Instance { instance_type: t1 },
217 InferredType::Instance { instance_type: t2 },
218 ) => t1 == t2,
219 (InferredType::Unknown, InferredType::Unknown) => true,
220
221 (InferredType::OneOf(ts1), InferredType::OneOf(ts2)) => {
223 let mut ts1_sorted = ts1.clone();
224 let mut ts2_sorted = ts2.clone();
225 ts1_sorted.sort();
226 ts2_sorted.sort();
227 ts1_sorted == ts2_sorted
228 }
229 (InferredType::AllOf(ts1), InferredType::AllOf(ts2)) => {
230 let mut ts1_sorted = ts1.clone();
231 let mut ts2_sorted = ts2.clone();
232 ts1_sorted.sort();
233 ts2_sorted.sort();
234 ts1_sorted == ts2_sorted
235 }
236 (InferredType::Sequence(ts1), InferredType::Sequence(ts2)) => {
237 let mut ts1_sorted = ts1.clone();
238 let mut ts2_sorted = ts2.clone();
239 ts1_sorted.sort();
240 ts2_sorted.sort();
241 ts1_sorted == ts2_sorted
242 }
243
244 _ => false,
245 }
246 }
247}
248
249#[derive(PartialEq, Clone, Debug)]
250pub enum InferredNumber {
251 S8,
252 U8,
253 S16,
254 U16,
255 S32,
256 U32,
257 S64,
258 U64,
259 F32,
260 F64,
261}
262
263impl From<InferredNumber> for InferredType {
264 fn from(inferred_number: InferredNumber) -> Self {
265 match inferred_number {
266 InferredNumber::S8 => InferredType::S8,
267 InferredNumber::U8 => InferredType::U8,
268 InferredNumber::S16 => InferredType::S16,
269 InferredNumber::U16 => InferredType::U16,
270 InferredNumber::S32 => InferredType::S32,
271 InferredNumber::U32 => InferredType::U32,
272 InferredNumber::S64 => InferredType::S64,
273 InferredNumber::U64 => InferredType::U64,
274 InferredNumber::F32 => InferredType::F32,
275 InferredNumber::F64 => InferredType::F64,
276 }
277 }
278}
279
280impl From<&BigDecimal> for InferredType {
281 fn from(value: &BigDecimal) -> Self {
282 let sign = value.sign();
283
284 if value.fractional_digit_count() <= 0 {
285 match sign {
286 Sign::NoSign => InferredType::U64,
287 Sign::Minus => InferredType::S64,
288 Sign::Plus => InferredType::U64,
289 }
290 } else {
291 InferredType::F64
292 }
293 }
294}
295
296#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
297pub struct RangeType {
298 from: Box<InferredType>,
299 to: Option<Box<InferredType>>,
300}
301
302impl Display for InferredNumber {
303 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
304 let type_name = TypeName::from(self);
305 write!(f, "{}", type_name)
306 }
307}
308
309impl InferredType {
310 pub fn printable(&self) -> String {
311 TypeName::try_from(self.clone())
314 .map(|tn| tn.to_string())
315 .unwrap_or(self.get_type_hint().to_string())
316 }
317
318 pub fn contains_only_number(&self) -> bool {
319 match self {
320 InferredType::S8
321 | InferredType::U8
322 | InferredType::S16
323 | InferredType::U16
324 | InferredType::S32
325 | InferredType::U32
326 | InferredType::S64
327 | InferredType::U64
328 | InferredType::F32
329 | InferredType::F64 => true,
330 InferredType::AllOf(types) => types.iter().all(|t| t.contains_only_number()),
331 InferredType::OneOf(types) => types.iter().all(|t| t.contains_only_number()),
332 InferredType::Bool => false,
333 InferredType::Chr => false,
334 InferredType::Str => false,
335 InferredType::List(_) => false,
336 InferredType::Tuple(_) => false,
337 InferredType::Record(_) => false,
338 InferredType::Flags(_) => false,
339 InferredType::Enum(_) => false,
340 InferredType::Option(_) => false,
341 InferredType::Result { .. } => false,
342 InferredType::Variant(_) => false,
343 InferredType::Resource { .. } => false,
344 InferredType::Range { .. } => false,
345 InferredType::Instance { .. } => false,
346 InferredType::Unknown => false,
347 InferredType::Sequence(_) => false,
348 }
349 }
350
351 pub fn as_number(&self) -> Result<InferredNumber, String> {
352 fn go(inferred_type: &InferredType, found: &mut Vec<InferredNumber>) -> Result<(), String> {
353 match inferred_type {
354 InferredType::S8 => {
355 found.push(InferredNumber::S8);
356 Ok(())
357 }
358 InferredType::U8 => {
359 found.push(InferredNumber::U8);
360 Ok(())
361 }
362 InferredType::S16 => {
363 found.push(InferredNumber::S16);
364 Ok(())
365 }
366 InferredType::U16 => {
367 found.push(InferredNumber::U16);
368 Ok(())
369 }
370 InferredType::S32 => {
371 found.push(InferredNumber::U16);
372 Ok(())
373 }
374 InferredType::U32 => {
375 found.push(InferredNumber::U32);
376 Ok(())
377 }
378 InferredType::S64 => {
379 found.push(InferredNumber::S64);
380 Ok(())
381 }
382 InferredType::U64 => {
383 found.push(InferredNumber::U64);
384 Ok(())
385 }
386 InferredType::F32 => {
387 found.push(InferredNumber::F32);
388 Ok(())
389 }
390 InferredType::F64 => {
391 found.push(InferredNumber::F64);
392 Ok(())
393 }
394 InferredType::AllOf(all_variables) => {
395 let mut previous: Option<InferredNumber> = None;
396 for variable in all_variables {
397 go(variable, found)?;
398
399 if let Some(current) = found.first() {
400 match &previous {
401 None => {
402 previous = Some(current.clone());
403 found.push(current.clone());
404 }
405 Some(previous) => {
406 if previous != current {
407 return Err(format!(
408 "expected the same type of number. But found {}, {}",
409 current, previous
410 ));
411 }
412
413 found.push(current.clone());
414 }
415 }
416 } else {
417 return Err("failed to get a number".to_string());
418 }
419 }
420
421 Ok(())
422 }
423 InferredType::Range { .. } => Err("used as range".to_string()),
424 InferredType::Bool => Err(format!("used as {}", "bool")),
425 InferredType::Chr => Err(format!("used as {}", "char")),
426 InferredType::Str => Err(format!("used as {}", "string")),
427 InferredType::List(_) => Err(format!("used as {}", "list")),
428 InferredType::Tuple(_) => Err(format!("used as {}", "tuple")),
429 InferredType::Record(_) => Err(format!("used as {}", "record")),
430 InferredType::Flags(_) => Err(format!("used as {}", "flags")),
431 InferredType::Enum(_) => Err(format!("used as {}", "enum")),
432 InferredType::Option(_) => Err(format!("used as {}", "option")),
433 InferredType::Result { .. } => Err(format!("used as {}", "result")),
434 InferredType::Variant(_) => Err(format!("used as {}", "variant")),
435
436 InferredType::OneOf(_) => {
438 if found.is_empty() {
439 Err("not a number.".to_string())
440 } else {
441 Ok(())
442 }
443 }
444 InferredType::Unknown => Err("found unknown".to_string()),
445
446 InferredType::Sequence(_) => {
447 Err(format!("used as {}", "function-multi-parameter-return"))
448 }
449 InferredType::Resource { .. } => Err(format!("used as {}", "resource")),
450 InferredType::Instance { .. } => Err(format!("used as {}", "instance")),
451 }
452 }
453
454 let mut found: Vec<InferredNumber> = vec![];
455 go(self, &mut found)?;
456 found.first().cloned().ok_or("Failed".to_string())
457 }
458
459 pub fn number() -> InferredType {
460 InferredType::OneOf(vec![
461 InferredType::U64,
462 InferredType::U32,
463 InferredType::U8,
464 InferredType::U16,
465 InferredType::S64,
466 InferredType::S32,
467 InferredType::S8,
468 InferredType::S16,
469 InferredType::F64,
470 InferredType::F32,
471 ])
472 }
473
474 pub fn un_resolved(&self) -> bool {
475 self.is_unknown() || self.is_one_of()
476 }
477
478 pub fn all_of(types: Vec<InferredType>) -> Option<InferredType> {
479 let flattened = InferredType::flatten_all_of_inferred_types(&types);
480
481 let mut types: Vec<InferredType> =
482 flattened.into_iter().filter(|t| !t.is_unknown()).collect();
483
484 let mut unique_types: HashSet<InferredType> = HashSet::new();
485 types.retain(|t| unique_types.insert(t.clone()));
486
487 if unique_types.is_empty() {
488 None
489 } else if unique_types.len() == 1 {
490 unique_types.into_iter().next()
491 } else {
492 let mut unique_all_of_types: Vec<InferredType> = unique_types.into_iter().collect();
493 unique_all_of_types.sort();
494 Some(InferredType::AllOf(unique_all_of_types))
495 }
496 }
497
498 pub fn one_of(types: Vec<InferredType>) -> Option<InferredType> {
499 let flattened = InferredType::flatten_one_of_inferred_types(&types);
500
501 let mut types: Vec<InferredType> =
502 flattened.into_iter().filter(|t| !t.is_unknown()).collect();
503
504 let mut unique_types: HashSet<InferredType> = HashSet::new();
506 types.retain(|t| unique_types.insert(t.clone()));
507
508 if types.is_empty() {
509 None
510 } else if types.len() == 1 {
511 types.into_iter().next()
512 } else {
513 let mut unique_one_of_types: Vec<InferredType> = unique_types.into_iter().collect();
514 unique_one_of_types.sort();
515 Some(InferredType::OneOf(unique_one_of_types))
516 }
517 }
518
519 pub fn is_unit(&self) -> bool {
520 match self {
521 InferredType::Sequence(types) => types.is_empty(),
522 _ => false,
523 }
524 }
525 pub fn is_unknown(&self) -> bool {
526 matches!(self, InferredType::Unknown)
527 }
528
529 pub fn is_one_of(&self) -> bool {
530 matches!(self, InferredType::OneOf(_))
531 }
532
533 pub fn is_valid_wit_type(&self) -> bool {
534 AnalysedType::try_from(self.clone()).is_ok()
535 }
536
537 pub fn is_all_of(&self) -> bool {
538 matches!(self, InferredType::AllOf(_))
539 }
540
541 pub fn is_number(&self) -> bool {
542 matches!(
543 self,
544 InferredType::S8
545 | InferredType::U8
546 | InferredType::S16
547 | InferredType::U16
548 | InferredType::S32
549 | InferredType::U32
550 | InferredType::S64
551 | InferredType::U64
552 | InferredType::F32
553 | InferredType::F64
554 )
555 }
556
557 pub fn is_string(&self) -> bool {
558 matches!(self, InferredType::Str)
559 }
560
561 pub fn flatten_all_of_inferred_types(types: &Vec<InferredType>) -> Vec<InferredType> {
562 flatten_all_of_list(types)
563 }
564
565 pub fn flatten_one_of_inferred_types(types: &Vec<InferredType>) -> Vec<InferredType> {
566 flatten_one_of_list(types)
567 }
568
569 pub fn try_unify(&self) -> Result<InferredType, String> {
572 unification::try_unify_type(self)
573 }
574
575 pub fn unify(&self) -> Result<InferredType, String> {
576 unification::unify(self).map(|unified| unified.inferred_type())
577 }
578
579 pub fn unify_all_alternative_types(types: &Vec<InferredType>) -> InferredType {
580 unification::unify_all_alternative_types(types)
581 }
582
583 pub fn unify_all_required_types(types: &Vec<InferredType>) -> Result<InferredType, String> {
584 unification::unify_all_required_types(types)
585 }
586
587 pub fn unify_with_required(&self, other: &InferredType) -> Result<InferredType, String> {
590 unification::unify_with_required(self, other)
591 }
592
593 pub fn unify_with_alternative(&self, other: &InferredType) -> Result<InferredType, String> {
594 unification::unify_with_alternative(self, other)
595 }
596
597 pub fn merge(&self, new_inferred_type: InferredType) -> InferredType {
599 if !internal::need_update(self, &new_inferred_type) {
600 return self.clone();
601 }
602
603 match (self, new_inferred_type) {
604 (InferredType::Unknown, new_type) => new_type,
605
606 (InferredType::AllOf(existing_types), InferredType::AllOf(new_types)) => {
607 let mut all_types = new_types.clone();
608 all_types.extend(existing_types.clone());
609
610 InferredType::all_of(all_types).unwrap_or(InferredType::Unknown)
611 }
612
613 (InferredType::AllOf(existing_types), new_type) => {
614 let mut all_types = existing_types.clone();
615 all_types.push(new_type);
616
617 InferredType::all_of(all_types).unwrap_or(InferredType::Unknown)
618 }
619
620 (current_type, InferredType::AllOf(new_types)) => {
621 let mut all_types = new_types.clone();
622 all_types.push(current_type.clone());
623
624 InferredType::all_of(all_types).unwrap_or(InferredType::Unknown)
625 }
626
627 (InferredType::OneOf(existing_types), InferredType::OneOf(new_types)) => {
628 let mut one_of_types = new_types.clone();
629 if &new_types == existing_types {
630 return InferredType::OneOf(one_of_types);
631 } else {
632 one_of_types.extend(existing_types.clone());
633 }
634
635 InferredType::one_of(one_of_types).unwrap_or(InferredType::Unknown)
636 }
637
638 (InferredType::OneOf(existing_types), new_type) => {
639 if existing_types.contains(&new_type) {
640 new_type
641 } else {
642 InferredType::all_of(vec![self.clone(), new_type])
643 .unwrap_or(InferredType::Unknown)
644 }
645 }
646
647 (current_type, InferredType::OneOf(newtypes)) => {
648 if newtypes.contains(current_type) {
649 current_type.clone()
650 } else {
651 InferredType::all_of(vec![current_type.clone(), InferredType::OneOf(newtypes)])
652 .unwrap_or(InferredType::Unknown)
653 }
654 }
655
656 (current_type, new_type) => {
657 InferredType::all_of(vec![current_type.clone(), new_type.clone()])
658 .unwrap_or(InferredType::Unknown)
659 }
660 }
661 }
662
663 pub fn from_variant_cases(type_variant: &TypeVariant) -> InferredType {
664 let cases = type_variant
665 .cases
666 .iter()
667 .map(|name_type_pair| {
668 (
669 name_type_pair.name.clone(),
670 name_type_pair.typ.clone().map(|t| t.into()),
671 )
672 })
673 .collect();
674
675 InferredType::Variant(cases)
676 }
677
678 pub fn from_enum_cases(type_enum: &TypeEnum) -> InferredType {
679 InferredType::Enum(type_enum.cases.clone())
680 }
681}
682
683impl TryFrom<InferredType> for AnalysedType {
684 type Error = String;
685
686 fn try_from(value: InferredType) -> Result<Self, Self::Error> {
687 match value {
688 InferredType::Bool => Ok(bool()),
689 InferredType::S8 => Ok(s8()),
690 InferredType::U8 => Ok(u8()),
691 InferredType::S16 => Ok(s16()),
692 InferredType::U16 => Ok(u16()),
693 InferredType::S32 => Ok(s32()),
694 InferredType::U32 => Ok(u32()),
695 InferredType::S64 => Ok(s64()),
696 InferredType::U64 => Ok(u64()),
697 InferredType::F32 => Ok(f32()),
698 InferredType::F64 => Ok(f64()),
699 InferredType::Chr => Ok(chr()),
700 InferredType::Str => Ok(str()),
701 InferredType::List(typ) => {
702 let typ: AnalysedType = (*typ).try_into()?;
703 Ok(list(typ))
704 }
705 InferredType::Tuple(types) => {
706 let types: Vec<AnalysedType> = types
707 .into_iter()
708 .map(|t| t.try_into())
709 .collect::<Result<Vec<AnalysedType>, _>>()?;
710 Ok(tuple(types))
711 }
712 InferredType::Record(field_and_types) => {
713 let mut field_pairs: Vec<NameTypePair> = vec![];
714 for (name, typ) in field_and_types {
715 let typ: AnalysedType = typ.try_into()?;
716 field_pairs.push(NameTypePair { name, typ });
717 }
718 Ok(record(field_pairs))
719 }
720 InferredType::Flags(names) => Ok(AnalysedType::Flags(TypeFlags { names })),
721 InferredType::Enum(cases) => Ok(AnalysedType::Enum(TypeEnum { cases })),
722 InferredType::Option(typ) => {
723 let typ: AnalysedType = (*typ).try_into()?;
724 Ok(option(typ))
725 }
726 InferredType::Result { ok, error } => {
727 let ok_option: Option<AnalysedType> = ok.map(|t| (*t).try_into()).transpose()?;
728 let ok = ok_option.ok_or("Expected ok type in result".to_string())?;
729 let error_option: Option<AnalysedType> =
730 error.map(|t| (*t).try_into()).transpose()?;
731 let error = error_option.ok_or("Expected error type in result".to_string())?;
732 Ok(result(ok, error))
733 }
734 InferredType::Variant(name_and_optiona_inferred_types) => {
735 let mut cases: Vec<NameOptionTypePair> = vec![];
736 for (name, typ) in name_and_optiona_inferred_types {
737 let typ: Option<AnalysedType> = typ.map(|t| t.try_into()).transpose()?;
738 cases.push(NameOptionTypePair { name, typ });
739 }
740 Ok(variant(cases))
741 }
742 InferredType::Resource {
743 resource_id,
744 resource_mode,
745 } => Ok(handle(
746 AnalysedResourceId(resource_id),
747 match resource_mode {
748 0 => AnalysedResourceMode::Owned,
749 1 => AnalysedResourceMode::Borrowed,
750 _ => return Err("Invalid resource mode".to_string()),
751 },
752 )),
753 InferredType::Instance { .. } => {
754 Err("Cannot convert instance type to analysed type".to_string())
755 }
756 InferredType::OneOf(_) => {
757 Err("Cannot convert one of type to analysed type".to_string())
758 }
759 InferredType::AllOf(_) => {
760 Err("Cannot convert all of type to analysed type".to_string())
761 }
762 InferredType::Unknown => {
763 Err("Cannot convert unknown type to analysed type".to_string())
764 }
765 InferredType::Sequence(_) => {
766 Err("Cannot convert function return sequence type to analysed type".to_string())
767 }
768 InferredType::Range { from, to } => {
769 let from: AnalysedType = (*from).try_into()?;
770 let to: Option<AnalysedType> = to.map(|t| (*t).try_into()).transpose()?;
771 let analysed_type = match (from, to) {
772 (from_type, Some(to_type)) => record(vec![
773 field("from", option(from_type)),
774 field("to", option(to_type)),
775 field("inclusive", bool()),
776 ]),
777
778 (from_type, None) => record(vec![
779 field("from", option(from_type)),
780 field("inclusive", bool()),
781 ]),
782 };
783 Ok(analysed_type)
784 }
785 }
786 }
787}
788
789impl From<AnalysedType> for InferredType {
790 fn from(analysed_type: AnalysedType) -> Self {
791 match analysed_type {
792 AnalysedType::Bool(_) => InferredType::Bool,
793 AnalysedType::S8(_) => InferredType::S8,
794 AnalysedType::U8(_) => InferredType::U8,
795 AnalysedType::S16(_) => InferredType::S16,
796 AnalysedType::U16(_) => InferredType::U16,
797 AnalysedType::S32(_) => InferredType::S32,
798 AnalysedType::U32(_) => InferredType::U32,
799 AnalysedType::S64(_) => InferredType::S64,
800 AnalysedType::U64(_) => InferredType::U64,
801 AnalysedType::F32(_) => InferredType::F32,
802 AnalysedType::F64(_) => InferredType::F64,
803 AnalysedType::Chr(_) => InferredType::Chr,
804 AnalysedType::Str(_) => InferredType::Str,
805 AnalysedType::List(t) => InferredType::List(Box::new((*t.inner).into())),
806 AnalysedType::Tuple(ts) => {
807 InferredType::Tuple(ts.items.into_iter().map(|t| t.into()).collect())
808 }
809 AnalysedType::Record(fs) => InferredType::Record(
810 fs.fields
811 .into_iter()
812 .map(|name_type| (name_type.name, name_type.typ.into()))
813 .collect(),
814 ),
815 AnalysedType::Flags(vs) => InferredType::Flags(vs.names),
816 AnalysedType::Enum(vs) => InferredType::from_enum_cases(&vs),
817 AnalysedType::Option(t) => InferredType::Option(Box::new((*t.inner).into())),
818 AnalysedType::Result(golem_wasm_ast::analysis::TypeResult { ok, err, .. }) => {
819 InferredType::Result {
820 ok: ok.map(|t| Box::new((*t).into())),
821 error: err.map(|t| Box::new((*t).into())),
822 }
823 }
824 AnalysedType::Variant(vs) => InferredType::from_variant_cases(&vs),
825 AnalysedType::Handle(golem_wasm_ast::analysis::TypeHandle { resource_id, mode }) => {
826 InferredType::Resource {
827 resource_id: resource_id.0,
828 resource_mode: match mode {
829 AnalysedResourceMode::Owned => 0,
830 AnalysedResourceMode::Borrowed => 1,
831 },
832 }
833 }
834 }
835 }
836}
837
838mod internal {
839 use crate::InferredType;
840
841 pub(crate) fn need_update(
842 current_inferred_type: &InferredType,
843 new_inferred_type: &InferredType,
844 ) -> bool {
845 current_inferred_type != new_inferred_type && !new_inferred_type.is_unknown()
846 }
847}
848
849#[cfg(test)]
850mod test {
851
852 #[test]
853 fn test_flatten_one_of() {
854 use super::InferredType;
855 let one_of = vec![
856 InferredType::U8,
857 InferredType::U16,
858 InferredType::U32,
859 InferredType::OneOf(vec![
860 InferredType::U8,
861 InferredType::U16,
862 InferredType::U32,
863 InferredType::AllOf(vec![
864 InferredType::U64,
865 InferredType::OneOf(vec![InferredType::U64, InferredType::U8]),
866 ]),
867 ]),
868 ];
869
870 let flattened = InferredType::flatten_one_of_inferred_types(&one_of);
871
872 let expected = vec![
873 InferredType::U8,
874 InferredType::U16,
875 InferredType::U32,
876 InferredType::U8,
877 InferredType::U16,
878 InferredType::U32,
879 InferredType::AllOf(vec![
880 InferredType::U64,
881 InferredType::OneOf(vec![InferredType::U64, InferredType::U8]),
882 ]),
883 ];
884
885 assert_eq!(flattened, expected)
886 }
887}