1use crate::{
2 DefinedType, DefinedTypeId, FuncType, FuncTypeId, Interface, InterfaceId, ItemKind,
3 ModuleTypeId, Record, Resource, ResourceAlias, ResourceId, SubtypeChecker, Type, Types,
4 UsedType, ValueType, Variant, World, WorldId,
5};
6use anyhow::{bail, Context, Result};
7use indexmap::IndexMap;
8use std::collections::HashMap;
9
10#[derive(Default, Debug)]
22pub struct TypeAggregator {
23 types: Types,
25 imports: IndexMap<String, ItemKind>,
27 remapped: HashMap<Type, Type>,
29 interfaces: HashMap<String, InterfaceId>,
31}
32
33impl TypeAggregator {
34 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn types(&self) -> &Types {
41 &self.types
42 }
43
44 pub fn imports(&self) -> impl Iterator<Item = (&str, ItemKind)> {
46 self.imports.iter().map(|(n, k)| (n.as_str(), *k))
47 }
48
49 pub fn aggregate(
54 mut self,
55 name: &str,
56 types: &Types,
57 kind: ItemKind,
58 checker: &mut SubtypeChecker,
59 ) -> Result<Self> {
60 if let Some(existing) = self.imports.get(name).copied() {
64 self.merge_item_kind(existing, types, kind, checker)?;
65 return Ok(self);
66 }
67
68 let remapped = self.remap_item_kind(types, kind, checker)?;
69 let prev = self.imports.insert(name.to_string(), remapped);
70 assert!(prev.is_none());
71 Ok(self)
72 }
73
74 fn merge_item_kind(
75 &mut self,
76 existing: ItemKind,
77 types: &Types,
78 kind: ItemKind,
79 checker: &mut SubtypeChecker,
80 ) -> Result<()> {
81 match (existing, kind) {
82 (ItemKind::Instance(existing), ItemKind::Instance(id)) => {
83 self.merge_interface(existing, types, id, checker)
84 }
85 (ItemKind::Component(existing), ItemKind::Component(id)) => {
86 self.merge_world(existing, types, id, checker)
87 }
88 (ItemKind::Func(existing), ItemKind::Func(id)) => {
89 self.merge_func_type(existing, types, id, checker)
90 }
91 (ItemKind::Module(existing), ItemKind::Module(id)) => {
92 self.merge_module_type(existing, types, id, checker)
93 }
94 (ItemKind::Type(existing), ItemKind::Type(ty)) => {
95 self.merge_type(existing, types, ty, checker)
96 }
97 (ItemKind::Value(existing), ItemKind::Value(ty)) => {
98 self.merge_value_type(existing, types, ty, checker)
99 }
100 (existing, kind) => {
101 bail!(
102 "{existing} cannot be merged with {kind}",
103 existing = existing.desc(&self.types),
104 kind = kind.desc(types)
105 );
106 }
107 }
108 }
109
110 fn merge_interface(
111 &mut self,
112 existing: InterfaceId,
113 types: &Types,
114 id: InterfaceId,
115 checker: &mut SubtypeChecker,
116 ) -> Result<()> {
117 self.merge_interface_used_types(existing, types, id, checker)?;
119
120 for (name, source_kind) in &types[id].exports {
122 if let Some(target_kind) = self.types[existing].exports.get(name).copied() {
123 if checker
125 .is_subtype(*source_kind, types, target_kind, &self.types)
126 .is_ok()
127 {
128 self.remapped.insert(source_kind.ty(), target_kind.ty());
131 continue;
132 }
133
134 checker
137 .is_subtype(target_kind, &self.types, *source_kind, types)
138 .with_context(|| format!("mismatched type for export `{name}`"))?;
139 }
140
141 let remapped = self.remap_item_kind(types, *source_kind, checker)?;
142 self.types[existing].exports.insert(name.clone(), remapped);
143 }
144
145 Ok(())
146 }
147
148 fn merge_interface_used_types(
149 &mut self,
150 existing: InterfaceId,
151 types: &Types,
152 id: InterfaceId,
153 checker: &mut SubtypeChecker,
154 ) -> Result<()> {
155 let source = &types[id];
156 for (name, used) in &source.uses {
157 let used_interface = types[used.interface]
158 .id
159 .as_ref()
160 .context("used type has no interface identifier")?;
161
162 if let Some(existing) = self.types[existing].uses.get(name) {
164 let existing_interface = self.types[existing.interface]
165 .id
166 .as_ref()
167 .context("used type has no interface identifier")?;
168
169 if existing_interface != used_interface {
171 bail!("cannot merge used type `{name}` as it is expected to be from interface `{existing_interface}` but it is from interface `{used_interface}`");
172 }
173
174 if existing.name != used.name {
176 bail!("cannot merge used type `{name}` as the export names are mismatched");
177 }
178 }
179
180 let remapped = self.remap_interface(types, used.interface, checker)?;
182 match self.types[existing].uses.get(name) {
183 Some(existing) => {
184 assert_eq!(
185 existing.interface, remapped,
186 "expected a merge to have occurred"
187 );
188 }
189 None => {
190 self.types[existing].uses.insert(
191 name.clone(),
192 UsedType {
193 interface: remapped,
194 name: used.name.clone(),
195 },
196 );
197 }
198 }
199 }
200
201 Ok(())
202 }
203
204 fn merge_world(
205 &mut self,
206 existing: WorldId,
207 types: &Types,
208 id: WorldId,
209 checker: &mut SubtypeChecker,
210 ) -> Result<()> {
211 self.merge_world_used_types(existing, types, id, checker)?;
213
214 checker.invert();
216 for (name, source_kind) in &types[id].imports {
217 if let Some(target_kind) = self.types[existing].imports.get(name).copied() {
218 if checker
220 .is_subtype(target_kind, &self.types, *source_kind, types)
221 .is_ok()
222 {
223 continue;
224 }
225
226 checker
229 .is_subtype(*source_kind, types, target_kind, &self.types)
230 .with_context(|| format!("mismatched type for export `{name}`"))?;
231 }
232
233 let remapped = self.remap_item_kind(types, *source_kind, checker)?;
234 self.types[existing].imports.insert(name.clone(), remapped);
235 }
236
237 checker.revert();
238
239 for (name, source_kind) in &types[id].exports {
241 if let Some(target_kind) = self.types[existing].exports.get(name).copied() {
242 if checker
244 .is_subtype(*source_kind, types, target_kind, &self.types)
245 .is_ok()
246 {
247 continue;
248 }
249
250 checker
253 .is_subtype(target_kind, &self.types, *source_kind, types)
254 .with_context(|| format!("mismatched type for export `{name}`"))?;
255 }
256
257 let remapped = self.remap_item_kind(types, *source_kind, checker)?;
258 self.types[existing].exports.insert(name.clone(), remapped);
259 }
260
261 Ok(())
262 }
263
264 fn merge_world_used_types(
265 &mut self,
266 existing: WorldId,
267 types: &Types,
268 id: WorldId,
269 checker: &mut SubtypeChecker,
270 ) -> Result<()> {
271 let source = &types[id];
272 for (name, used) in &source.uses {
273 let used_interface = types[used.interface]
274 .id
275 .as_ref()
276 .context("used type has no interface identifier")?;
277
278 if let Some(existing) = self.types[existing].uses.get(name) {
280 let existing_interface = self.types[existing.interface]
281 .id
282 .as_ref()
283 .context("used type has no interface identifier")?;
284
285 if existing_interface != used_interface {
287 bail!("cannot merge used type `{name}` as it is expected to be from interface `{existing_interface}` but it is from interface `{used_interface}`");
288 }
289
290 if existing.name != used.name {
292 bail!("cannot merge used type `{name}` as the export names are mismatched");
293 }
294 }
295
296 let remapped = self.remap_interface(types, used.interface, checker)?;
298 match self.types[existing].uses.get(name) {
299 Some(existing) => {
300 assert_eq!(
301 existing.interface, remapped,
302 "expected a merge to have occurred"
303 );
304 }
305 None => {
306 let prev = self.types[existing].uses.insert(
307 name.clone(),
308 UsedType {
309 interface: remapped,
310 name: used.name.clone(),
311 },
312 );
313 assert!(prev.is_none());
314 }
315 }
316 }
317
318 Ok(())
319 }
320
321 fn merge_func_type(
322 &mut self,
323 existing: FuncTypeId,
324 types: &Types,
325 id: FuncTypeId,
326 checker: &mut SubtypeChecker,
327 ) -> Result<()> {
328 checker.is_subtype(
331 ItemKind::Func(id),
332 types,
333 ItemKind::Func(existing),
334 &self.types,
335 )?;
336 checker.is_subtype(
337 ItemKind::Func(existing),
338 &self.types,
339 ItemKind::Func(id),
340 types,
341 )?;
342
343 Ok(())
344 }
345
346 fn merge_module_type(
347 &mut self,
348 existing: ModuleTypeId,
349 types: &Types,
350 id: ModuleTypeId,
351 checker: &mut SubtypeChecker,
352 ) -> Result<()> {
353 checker.invert();
355 for (name, source_extern) in &types[id].imports {
356 if let Some(target_extern) = self.types[existing].imports.get(name) {
357 if checker
359 .core_extern(target_extern, &self.types, source_extern, types)
360 .is_ok()
361 {
362 continue;
363 }
364
365 checker
368 .core_extern(source_extern, types, target_extern, &self.types)
369 .with_context(|| {
370 format!(
371 "mismatched type for import `{m}::{n}`",
372 m = name.0,
373 n = name.1
374 )
375 })?;
376 }
377
378 self.types[existing]
379 .imports
380 .insert(name.clone(), source_extern.clone());
381 }
382
383 checker.revert();
384
385 for (name, source_extern) in &types[id].exports {
387 if let Some(target_extern) = self.types[existing].exports.get(name) {
388 if checker
391 .core_extern(source_extern, types, target_extern, &self.types)
392 .is_ok()
393 {
394 continue;
395 }
396
397 checker
400 .core_extern(target_extern, &self.types, source_extern, types)
401 .with_context(|| format!("mismatched type for export `{name}`"))?;
402 }
403
404 self.types[existing]
405 .exports
406 .insert(name.clone(), source_extern.clone());
407 }
408
409 Ok(())
410 }
411
412 fn merge_type(
413 &mut self,
414 existing: Type,
415 types: &Types,
416 ty: Type,
417 checker: &mut SubtypeChecker,
418 ) -> Result<()> {
419 match (existing, ty) {
420 (Type::Resource(existing), Type::Resource(id)) => {
421 self.merge_resource(existing, types, id, checker)
422 }
423 (Type::Func(existing), Type::Func(id)) => {
424 self.merge_func_type(existing, types, id, checker)
425 }
426 (Type::Value(existing), Type::Value(ty)) => {
427 self.merge_value_type(existing, types, ty, checker)
428 }
429 (Type::Interface(existing), Type::Interface(id)) => {
430 self.merge_interface(existing, types, id, checker)
431 }
432 (Type::World(existing), Type::World(id)) => {
433 self.merge_world(existing, types, id, checker)
434 }
435 (Type::Module(existing), Type::Module(id)) => {
436 self.merge_module_type(existing, types, id, checker)
437 }
438 _ => bail!(
439 "{existing} cannot be merged with {ty}",
440 existing = existing.desc(&self.types),
441 ty = ty.desc(types)
442 ),
443 }
444 }
445
446 fn merge_resource(
447 &mut self,
448 existing: ResourceId,
449 types: &Types,
450 id: ResourceId,
451 checker: &mut SubtypeChecker,
452 ) -> Result<()> {
453 checker.is_subtype(
456 ItemKind::Type(Type::Resource(id)),
457 types,
458 ItemKind::Type(Type::Resource(existing)),
459 &self.types,
460 )?;
461
462 checker.is_subtype(
463 ItemKind::Type(Type::Resource(existing)),
464 &self.types,
465 ItemKind::Type(Type::Resource(id)),
466 types,
467 )?;
468
469 Ok(())
470 }
471
472 fn merge_value_type(
473 &mut self,
474 existing: ValueType,
475 types: &Types,
476 ty: ValueType,
477 checker: &mut SubtypeChecker,
478 ) -> Result<()> {
479 checker.is_subtype(
481 ItemKind::Value(ty),
482 types,
483 ItemKind::Value(existing),
484 &self.types,
485 )?;
486
487 checker.is_subtype(
488 ItemKind::Value(existing),
489 &self.types,
490 ItemKind::Value(ty),
491 types,
492 )?;
493
494 Ok(())
495 }
496
497 fn remap_item_kind(
498 &mut self,
499 types: &Types,
500 kind: ItemKind,
501 checker: &mut SubtypeChecker,
502 ) -> Result<ItemKind> {
503 match kind {
504 ItemKind::Type(ty) => Ok(ItemKind::Type(self.remap_type(types, ty, checker)?)),
505 ItemKind::Func(id) => Ok(ItemKind::Func(self.remap_func_type(types, id, checker)?)),
506 ItemKind::Instance(id) => Ok(ItemKind::Instance(
507 self.remap_interface(types, id, checker)?,
508 )),
509 ItemKind::Component(id) => {
510 Ok(ItemKind::Component(self.remap_world(types, id, checker)?))
511 }
512 ItemKind::Module(id) => Ok(ItemKind::Module(self.remap_module_type(types, id))),
513 ItemKind::Value(ty) => Ok(ItemKind::Value(self.remap_value_type(types, ty, checker)?)),
514 }
515 }
516
517 fn remap_type(
518 &mut self,
519 types: &Types,
520 ty: Type,
521 checker: &mut SubtypeChecker,
522 ) -> Result<Type> {
523 match ty {
524 Type::Resource(id) => Ok(Type::Resource(self.remap_resource(types, id, checker)?)),
525 Type::Func(id) => Ok(Type::Func(self.remap_func_type(types, id, checker)?)),
526 Type::Value(ty) => Ok(Type::Value(self.remap_value_type(types, ty, checker)?)),
527 Type::Interface(id) => Ok(Type::Interface(self.remap_interface(types, id, checker)?)),
528 Type::World(id) => Ok(Type::World(self.remap_world(types, id, checker)?)),
529 Type::Module(id) => Ok(Type::Module(self.remap_module_type(types, id))),
530 }
531 }
532
533 fn remap_resource(
534 &mut self,
535 types: &Types,
536 id: ResourceId,
537 checker: &mut SubtypeChecker,
538 ) -> Result<ResourceId> {
539 if let Some(kind) = self.remapped.get(&Type::Resource(id)) {
540 return match kind {
541 Type::Resource(id) => Ok(*id),
542 _ => panic!("expected a resource"),
543 };
544 }
545
546 let resource = &types[id];
547 let remapped = Resource {
548 name: resource.name.clone(),
549 alias: resource
550 .alias
551 .map(|a| -> Result<_> {
552 let owner = a
553 .owner
554 .map(|id| {
555 self.remap_interface(types, id, checker)
558 })
559 .transpose()?;
560 if let Some(owner) = owner {
562 let name = self.types()[owner]
563 .id
564 .as_deref()
565 .expect("interface has no id");
566 if !self.imports.contains_key(name) {
567 self.imports
568 .insert(name.to_owned(), ItemKind::Instance(owner));
569 }
570 }
571 Ok(ResourceAlias {
572 owner,
573 source: self.remap_resource(types, a.source, checker)?,
574 })
575 })
576 .transpose()?,
577 };
578 let remapped_id = self.types.add_resource(remapped);
579
580 let prev = self
581 .remapped
582 .insert(Type::Resource(id), Type::Resource(remapped_id));
583 assert!(prev.is_none());
584 Ok(remapped_id)
585 }
586
587 fn remap_func_type(
588 &mut self,
589 types: &Types,
590 id: FuncTypeId,
591 checker: &mut SubtypeChecker,
592 ) -> Result<FuncTypeId> {
593 if let Some(kind) = self.remapped.get(&Type::Func(id)) {
594 return match kind {
595 Type::Func(id) => Ok(*id),
596 _ => panic!("expected a function type"),
597 };
598 }
599
600 let ty = &types[id];
601 let remapped = FuncType {
602 params: ty
603 .params
604 .iter()
605 .map(|(n, ty)| Ok((n.clone(), self.remap_value_type(types, *ty, checker)?)))
606 .collect::<Result<_>>()?,
607 result: ty
608 .result
609 .map(|ty| self.remap_value_type(types, ty, checker))
610 .transpose()?,
611 };
612
613 let remapped_id = self.types.add_func_type(remapped);
614 let prev = self
615 .remapped
616 .insert(Type::Func(id), Type::Func(remapped_id));
617 assert!(prev.is_none());
618 Ok(remapped_id)
619 }
620
621 fn remap_value_type(
622 &mut self,
623 types: &Types,
624 ty: ValueType,
625 checker: &mut SubtypeChecker,
626 ) -> Result<ValueType> {
627 match ty {
628 ValueType::Primitive(ty) => Ok(ValueType::Primitive(ty)),
629 ValueType::Borrow(id) => {
630 Ok(ValueType::Borrow(self.remap_resource(types, id, checker)?))
631 }
632 ValueType::Own(id) => Ok(ValueType::Own(self.remap_resource(types, id, checker)?)),
633 ValueType::Defined(id) => Ok(ValueType::Defined(
634 self.remap_defined_type(types, id, checker)?,
635 )),
636 }
637 }
638
639 fn remap_interface(
640 &mut self,
641 types: &Types,
642 id: InterfaceId,
643 checker: &mut SubtypeChecker,
644 ) -> Result<InterfaceId> {
645 if let Some(name) = types[id].id.as_ref() {
648 if let Some(existing) = self.interfaces.get(name).copied() {
649 self.merge_interface(existing, types, id, checker)
650 .with_context(|| format!("failed to merge interface `{name}`"))?;
651 return Ok(existing);
652 }
653 }
654
655 if let Some(kind) = self.remapped.get(&Type::Interface(id)) {
656 return match kind {
657 Type::Interface(id) => Ok(*id),
658 _ => panic!("expected an interface"),
659 };
660 }
661
662 let ty = &types[id];
663 let interface = Interface {
664 id: ty.id.clone(),
665 uses: ty
666 .uses
667 .iter()
668 .map(|(n, u)| {
669 if types[u.interface].id.is_none() {
670 bail!("used type `{n}` is from an interface without an identifier");
671 }
672
673 Ok((
674 n.clone(),
675 UsedType {
676 interface: self.remap_interface(types, u.interface, checker)?,
677 name: u.name.clone(),
678 },
679 ))
680 })
681 .collect::<Result<_>>()?,
682 exports: ty
683 .exports
684 .iter()
685 .map(|(n, k)| Ok((n.clone(), self.remap_item_kind(types, *k, checker)?)))
686 .collect::<Result<_>>()?,
687 };
688
689 let remapped = self.types.add_interface(interface);
690 let prev = self
691 .remapped
692 .insert(Type::Interface(id), Type::Interface(remapped));
693 assert!(prev.is_none());
694
695 if let Some(name) = self.types[remapped].id.as_ref() {
696 let prev = self.interfaces.insert(name.clone(), remapped);
697 assert!(prev.is_none());
698 }
699
700 Ok(remapped)
701 }
702
703 fn remap_world(
704 &mut self,
705 types: &Types,
706 id: WorldId,
707 checker: &mut SubtypeChecker,
708 ) -> Result<WorldId> {
709 if let Some(kind) = self.remapped.get(&Type::World(id)) {
710 return match kind {
711 Type::World(id) => Ok(*id),
712 _ => panic!("expected a world"),
713 };
714 }
715
716 let ty = &types[id];
717 let world = World {
718 id: ty.id.clone(),
719 uses: ty
720 .uses
721 .iter()
722 .map(|(n, u)| {
723 if types[u.interface].id.is_none() {
724 bail!("used type `{n}` is from an interface without an identifier");
725 }
726
727 Ok((
728 n.clone(),
729 UsedType {
730 interface: self.remap_interface(types, u.interface, checker)?,
731 name: u.name.clone(),
732 },
733 ))
734 })
735 .collect::<Result<_>>()?,
736 imports: ty
737 .imports
738 .iter()
739 .map(|(n, k)| Ok((n.clone(), self.remap_item_kind(types, *k, checker)?)))
740 .collect::<Result<_>>()?,
741 exports: ty
742 .exports
743 .iter()
744 .map(|(n, k)| Ok((n.clone(), self.remap_item_kind(types, *k, checker)?)))
745 .collect::<Result<_>>()?,
746 };
747
748 let remapped = self.types.add_world(world);
749 let prev = self.remapped.insert(Type::World(id), Type::World(remapped));
750 assert!(prev.is_none());
751
752 Ok(remapped)
753 }
754
755 fn remap_module_type(&mut self, types: &Types, id: ModuleTypeId) -> ModuleTypeId {
756 if let Some(kind) = self.remapped.get(&Type::Module(id)) {
757 return match kind {
758 Type::Module(id) => *id,
759 _ => panic!("expected a module type"),
760 };
761 }
762
763 let ty = &types[id];
764 let remapped = self.types.add_module_type(ty.clone());
765 let prev = self
766 .remapped
767 .insert(Type::Module(id), Type::Module(remapped));
768 assert!(prev.is_none());
769 remapped
770 }
771
772 fn remap_defined_type(
773 &mut self,
774 types: &Types,
775 id: DefinedTypeId,
776 checker: &mut SubtypeChecker,
777 ) -> Result<DefinedTypeId> {
778 if let Some(kind) = self.remapped.get(&Type::Value(ValueType::Defined(id))) {
779 return match kind {
780 Type::Value(ValueType::Defined(id)) => Ok(*id),
781 _ => panic!("expected a defined type got {kind:?}"),
782 };
783 }
784
785 let defined = match &types[id] {
786 DefinedType::Tuple(tys) => DefinedType::Tuple(
787 tys.iter()
788 .map(|ty| self.remap_value_type(types, *ty, checker))
789 .collect::<Result<_>>()?,
790 ),
791 DefinedType::List(ty) => DefinedType::List(self.remap_value_type(types, *ty, checker)?),
792 DefinedType::FixedSizeList(ty, elements) => {
793 DefinedType::FixedSizeList(self.remap_value_type(types, *ty, checker)?, *elements)
794 }
795 DefinedType::Option(ty) => {
796 DefinedType::Option(self.remap_value_type(types, *ty, checker)?)
797 }
798 DefinedType::Result { ok, err } => DefinedType::Result {
799 ok: ok
800 .as_ref()
801 .map(|ty| self.remap_value_type(types, *ty, checker))
802 .transpose()?,
803 err: err
804 .as_ref()
805 .map(|ty| self.remap_value_type(types, *ty, checker))
806 .transpose()?,
807 },
808 DefinedType::Variant(v) => DefinedType::Variant(Variant {
809 cases: v
810 .cases
811 .iter()
812 .map(|(n, ty)| {
813 Ok((
814 n.clone(),
815 ty.as_ref()
816 .map(|ty| self.remap_value_type(types, *ty, checker))
817 .transpose()?,
818 ))
819 })
820 .collect::<Result<_>>()?,
821 }),
822 DefinedType::Record(r) => DefinedType::Record(Record {
823 fields: r
824 .fields
825 .iter()
826 .map(|(n, ty)| Ok((n.clone(), self.remap_value_type(types, *ty, checker)?)))
827 .collect::<Result<_>>()?,
828 }),
829 DefinedType::Flags(f) => DefinedType::Flags(f.clone()),
830 DefinedType::Enum(e) => DefinedType::Enum(e.clone()),
831 DefinedType::Alias(ty) => {
832 DefinedType::Alias(self.remap_value_type(types, *ty, checker)?)
833 }
834 DefinedType::Stream(s) => DefinedType::Stream(
835 s.as_ref()
836 .map(|ty| self.remap_value_type(types, *ty, checker))
837 .transpose()?,
838 ),
839 DefinedType::Future(f) => DefinedType::Future(
840 f.as_ref()
841 .map(|ty| self.remap_value_type(types, *ty, checker))
842 .transpose()?,
843 ),
844 };
845
846 let remapped = self.types.add_defined_type(defined);
847 let prev = self.remapped.insert(
848 Type::Value(ValueType::Defined(id)),
849 Type::Value(ValueType::Defined(remapped)),
850 );
851 assert!(prev.is_none());
852 Ok(remapped)
853 }
854}