1use super::{
4 component::{ComponentState, ExternKind},
5 core::Module,
6};
7use crate::std::ops::{Index, Range};
8use crate::std::sync::atomic::{AtomicUsize, Ordering};
9use crate::std::{
10 borrow::Borrow,
11 hash::{Hash, Hasher},
12 mem,
13 ops::{Deref, DerefMut},
14};
15use crate::{validator::names::KebabString, HeapType};
16use crate::{
17 BinaryReaderError, CompositeType, Export, ExternalKind, FuncType, GlobalType, Import, Matches,
18 MemoryType, PackedIndex, PrimitiveValType, RecGroup, RefType, Result, SubType, TableType,
19 TypeRef, UnpackedIndex, ValType, WithRecGroup,
20};
21use ahash::RandomState;
22use alloc::{boxed::Box, format, string::String, sync::Arc, vec::Vec};
23use hashbrown::hash_map::Entry;
24use hashbrown::{HashMap, HashSet};
25use indexmap::{IndexMap, IndexSet};
26
27const MAX_FLAT_FUNC_PARAMS: usize = 16;
32const MAX_FLAT_FUNC_RESULTS: usize = 1;
37
38const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
40
41pub(crate) struct LoweredTypes {
43 types: [ValType; MAX_LOWERED_TYPES],
44 len: usize,
45 max: usize,
46}
47
48impl LoweredTypes {
49 fn new(max: usize) -> Self {
50 assert!(max <= MAX_LOWERED_TYPES);
51 Self {
52 types: [ValType::I32; MAX_LOWERED_TYPES],
53 len: 0,
54 max,
55 }
56 }
57
58 fn len(&self) -> usize {
59 self.len
60 }
61
62 fn maxed(&self) -> bool {
63 self.len == self.max
64 }
65
66 fn get_mut(&mut self, index: usize) -> Option<&mut ValType> {
67 if index < self.len {
68 Some(&mut self.types[index])
69 } else {
70 None
71 }
72 }
73
74 fn push(&mut self, ty: ValType) -> bool {
75 if self.maxed() {
76 return false;
77 }
78
79 self.types[self.len] = ty;
80 self.len += 1;
81 true
82 }
83
84 fn clear(&mut self) {
85 self.len = 0;
86 }
87
88 pub fn as_slice(&self) -> &[ValType] {
89 &self.types[..self.len]
90 }
91
92 pub fn iter(&self) -> impl Iterator<Item = ValType> + '_ {
93 self.as_slice().iter().copied()
94 }
95}
96
97pub(crate) struct LoweringInfo {
99 pub(crate) params: LoweredTypes,
100 pub(crate) results: LoweredTypes,
101 pub(crate) requires_memory: bool,
102 pub(crate) requires_realloc: bool,
103}
104
105impl LoweringInfo {
106 pub(crate) fn into_func_type(self) -> FuncType {
107 FuncType::new(
108 self.params.as_slice().iter().copied(),
109 self.results.as_slice().iter().copied(),
110 )
111 }
112}
113
114impl Default for LoweringInfo {
115 fn default() -> Self {
116 Self {
117 params: LoweredTypes::new(MAX_FLAT_FUNC_PARAMS),
118 results: LoweredTypes::new(MAX_FLAT_FUNC_RESULTS),
119 requires_memory: false,
120 requires_realloc: false,
121 }
122 }
123}
124
125fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredTypes) -> bool {
126 match ty {
127 PrimitiveValType::Bool
128 | PrimitiveValType::S8
129 | PrimitiveValType::U8
130 | PrimitiveValType::S16
131 | PrimitiveValType::U16
132 | PrimitiveValType::S32
133 | PrimitiveValType::U32
134 | PrimitiveValType::Char => lowered_types.push(ValType::I32),
135 PrimitiveValType::S64 | PrimitiveValType::U64 => lowered_types.push(ValType::I64),
136 PrimitiveValType::F32 => lowered_types.push(ValType::F32),
137 PrimitiveValType::F64 => lowered_types.push(ValType::F64),
138 PrimitiveValType::String => {
139 lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32)
140 }
141 }
142}
143
144pub trait TypeIdentifier: crate::std::fmt::Debug + Copy + Eq + Sized + 'static {
150 type Data: TypeData<Id = Self>;
152
153 #[doc(hidden)]
155 fn from_index(index: u32) -> Self;
156
157 #[doc(hidden)]
160 fn list(types: &TypeList) -> &SnapshotList<Self::Data>;
161
162 #[doc(hidden)]
165 fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data>;
166
167 #[doc(hidden)]
169 fn index(&self) -> usize;
170}
171
172pub trait TypeData: crate::std::fmt::Debug {
177 type Id: TypeIdentifier<Data = Self>;
179
180 #[doc(hidden)]
182 fn type_info(&self, types: &TypeList) -> TypeInfo;
183}
184
185pub trait Aliasable {
187 #[doc(hidden)]
188 fn alias_id(&self) -> u32;
189
190 #[doc(hidden)]
191 fn set_alias_id(&mut self, alias_id: u32);
192}
193
194const NO_ALIAS: u32 = u32::MAX;
201
202macro_rules! define_type_id {
203 ($name:ident, $data:ty, $list:ident, $type_str:expr) => {
204 #[doc = "Represents a unique identifier for a "]
205 #[doc = $type_str]
206 #[doc = " type known to a [`crate::Validator`]."]
207 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
208 #[repr(C)] pub struct $name {
210 index: u32,
212 }
213
214 impl TypeIdentifier for $name {
215 type Data = $data;
216
217 fn from_index(index: u32) -> Self {
218 $name { index }
219 }
220
221 fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
222 &types.$list
223 }
224
225 fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
226 &mut types.$list
227 }
228
229 fn index(&self) -> usize {
230 usize::try_from(self.index).unwrap()
231 }
232 }
233
234 impl Aliasable for $name {
235 fn alias_id(&self) -> u32 {
236 NO_ALIAS
237 }
238
239 fn set_alias_id(&mut self, _: u32) {}
240 }
241
242 const _: () = {
245 assert!(crate::std::mem::size_of::<$name>() <= 4);
246 };
247 };
248}
249
250pub enum CoreType {
252 Sub(SubType),
254
255 Module(ModuleType),
260}
261
262#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
265#[repr(C)]
266pub struct CoreTypeId {
267 index: u32,
268}
269
270const _: () = {
271 assert!(crate::std::mem::size_of::<CoreTypeId>() <= 4);
272};
273
274impl TypeIdentifier for CoreTypeId {
275 type Data = SubType;
276
277 fn from_index(index: u32) -> Self {
278 CoreTypeId { index }
279 }
280
281 fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
282 &types.core_types
283 }
284
285 fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
286 &mut types.core_types
287 }
288
289 fn index(&self) -> usize {
290 usize::try_from(self.index).unwrap()
291 }
292}
293
294impl TypeData for SubType {
295 type Id = CoreTypeId;
296
297 fn type_info(&self, _types: &TypeList) -> TypeInfo {
298 let size = 1 + match &self.composite_type {
300 CompositeType::Func(ty) => 1 + (ty.params().len() + ty.results().len()) as u32,
301 CompositeType::Array(_) => 2,
302 CompositeType::Struct(ty) => 1 + 2 * ty.fields.len() as u32,
303 };
304 TypeInfo::core(size)
305 }
306}
307
308impl CoreType {
309 pub fn unwrap_sub(&self) -> &SubType {
311 match self {
312 CoreType::Sub(s) => s,
313 CoreType::Module(_) => panic!("`unwrap_sub` on module type"),
314 }
315 }
316
317 pub fn unwrap_func(&self) -> &FuncType {
319 match &self.unwrap_sub().composite_type {
320 CompositeType::Func(f) => f,
321 CompositeType::Array(_) | CompositeType::Struct(_) => {
322 panic!("`unwrap_func` on non-func composite type")
323 }
324 }
325 }
326
327 pub fn unwrap_module(&self) -> &ModuleType {
329 match self {
330 CoreType::Module(m) => m,
331 CoreType::Sub(_) => panic!("`unwrap_module` on a subtype"),
332 }
333 }
334}
335
336macro_rules! define_wrapper_id {
337 (
338 $(#[$outer_attrs:meta])*
339 pub enum $name:ident {
340 $(
341 #[unwrap = $unwrap:ident]
342 $(#[$inner_attrs:meta])*
343 $variant:ident ( $inner:ty ) ,
344 )*
345 }
346 ) => {
347 $(#[$outer_attrs])*
348 pub enum $name {
349 $(
350 $(#[$inner_attrs])*
351 $variant ( $inner ) ,
352 )*
353 }
354
355 $(
356 impl From<$inner> for $name {
357 #[inline]
358 fn from(x: $inner) -> Self {
359 Self::$variant(x)
360 }
361 }
362
363 impl TryFrom<$name> for $inner {
364 type Error = ();
365
366 #[inline]
367 fn try_from(x: $name) -> Result<Self, Self::Error> {
368 match x {
369 $name::$variant(x) => Ok(x),
370 _ => Err(())
371 }
372 }
373 }
374 )*
375
376 impl $name {
377 $(
378 #[doc = "Unwrap a `"]
379 #[doc = stringify!($inner)]
380 #[doc = "` or panic."]
381 #[inline]
382 pub fn $unwrap(self) -> $inner {
383 <$inner>::try_from(self).unwrap()
384 }
385 )*
386 }
387 };
388}
389
390macro_rules! define_transitive_conversions {
391 (
392 $(
393 $outer:ty,
394 $middle:ty,
395 $inner:ty,
396 $unwrap:ident;
397 )*
398 ) => {
399 $(
400 impl From<$inner> for $outer {
401 #[inline]
402 fn from(x: $inner) -> Self {
403 <$middle>::from(x).into()
404 }
405 }
406
407 impl TryFrom<$outer> for $inner {
408 type Error = ();
409
410 #[inline]
411 fn try_from(x: $outer) -> Result<Self, Self::Error> {
412 let middle = <$middle>::try_from(x)?;
413 <$inner>::try_from(middle)
414 }
415 }
416
417 impl $outer {
418 #[doc = "Unwrap a `"]
419 #[doc = stringify!($inner)]
420 #[doc = "` or panic."]
421 #[inline]
422 pub fn $unwrap(self) -> $inner {
423 <$inner>::try_from(self).unwrap()
424 }
425 }
426 )*
427 };
428}
429
430define_wrapper_id! {
431 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
433 pub enum AnyTypeId {
434 #[unwrap = unwrap_component_core_type]
435 Core(ComponentCoreTypeId),
437
438 #[unwrap = unwrap_component_any_type]
439 Component(ComponentAnyTypeId),
441 }
442}
443
444define_transitive_conversions! {
445 AnyTypeId, ComponentCoreTypeId, CoreTypeId, unwrap_core_type;
446 AnyTypeId, ComponentCoreTypeId, ComponentCoreModuleTypeId, unwrap_component_core_module_type;
447 AnyTypeId, ComponentAnyTypeId, AliasableResourceId, unwrap_aliasable_resource;
448 AnyTypeId, ComponentAnyTypeId, ComponentDefinedTypeId, unwrap_component_defined_type;
449 AnyTypeId, ComponentAnyTypeId, ComponentFuncTypeId, unwrap_component_func_type;
450 AnyTypeId, ComponentAnyTypeId, ComponentInstanceTypeId, unwrap_component_instance_type;
451 AnyTypeId, ComponentAnyTypeId, ComponentTypeId, unwrap_component_type;
452}
453
454impl AnyTypeId {
455 pub fn peel_alias(&self, types: &Types) -> Option<Self> {
458 match *self {
459 Self::Core(id) => id.peel_alias(types).map(Self::Core),
460 Self::Component(id) => types.peel_alias(id).map(Self::Component),
461 }
462 }
463}
464
465define_wrapper_id! {
466 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
468 pub enum ComponentCoreTypeId {
469 #[unwrap = unwrap_sub]
470 Sub(CoreTypeId),
472
473 #[unwrap = unwrap_module]
474 Module(ComponentCoreModuleTypeId),
476 }
477}
478
479impl ComponentCoreTypeId {
480 pub fn peel_alias(&self, types: &Types) -> Option<Self> {
483 match *self {
484 Self::Sub(_) => None,
485 Self::Module(id) => types.peel_alias(id).map(Self::Module),
486 }
487 }
488}
489
490#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
492pub struct AliasableResourceId {
493 id: ResourceId,
494 alias_id: u32,
495}
496
497impl Aliasable for AliasableResourceId {
498 fn alias_id(&self) -> u32 {
499 self.alias_id
500 }
501
502 fn set_alias_id(&mut self, alias_id: u32) {
503 self.alias_id = alias_id;
504 }
505}
506
507impl AliasableResourceId {
508 pub fn with_resource_id(&self, id: ResourceId) -> Self {
511 Self {
512 id,
513 alias_id: self.alias_id,
514 }
515 }
516
517 pub fn resource(&self) -> ResourceId {
519 self.id
520 }
521
522 pub(crate) fn resource_mut(&mut self) -> &mut ResourceId {
523 &mut self.id
524 }
525}
526
527define_wrapper_id! {
528 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
530 pub enum ComponentAnyTypeId {
531 #[unwrap = unwrap_resource]
532 Resource(AliasableResourceId),
534
535 #[unwrap = unwrap_defined]
536 Defined(ComponentDefinedTypeId),
538
539 #[unwrap = unwrap_func]
540 Func(ComponentFuncTypeId),
542
543 #[unwrap = unwrap_instance]
544 Instance(ComponentInstanceTypeId),
546
547 #[unwrap = unwrap_component]
548 Component(ComponentTypeId),
550 }
551}
552
553impl Aliasable for ComponentAnyTypeId {
554 fn alias_id(&self) -> u32 {
555 match self {
556 ComponentAnyTypeId::Resource(x) => x.alias_id(),
557 ComponentAnyTypeId::Defined(x) => x.alias_id(),
558 ComponentAnyTypeId::Func(x) => x.alias_id(),
559 ComponentAnyTypeId::Instance(x) => x.alias_id(),
560 ComponentAnyTypeId::Component(x) => x.alias_id(),
561 }
562 }
563
564 fn set_alias_id(&mut self, alias_id: u32) {
565 match self {
566 ComponentAnyTypeId::Resource(x) => x.set_alias_id(alias_id),
567 ComponentAnyTypeId::Defined(x) => x.set_alias_id(alias_id),
568 ComponentAnyTypeId::Func(x) => x.set_alias_id(alias_id),
569 ComponentAnyTypeId::Instance(x) => x.set_alias_id(alias_id),
570 ComponentAnyTypeId::Component(x) => x.set_alias_id(alias_id),
571 }
572 }
573}
574
575impl ComponentAnyTypeId {
576 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
577 match *self {
578 Self::Resource(_) => TypeInfo::new(),
579 Self::Defined(id) => types[id].type_info(types),
580 Self::Func(id) => types[id].type_info(types),
581 Self::Instance(id) => types[id].type_info(types),
582 Self::Component(id) => types[id].type_info(types),
583 }
584 }
585
586 pub(crate) fn desc(&self) -> &'static str {
587 match self {
588 Self::Resource(_) => "resource",
589 Self::Defined(_) => "defined type",
590 Self::Func(_) => "func",
591 Self::Instance(_) => "instance",
592 Self::Component(_) => "component",
593 }
594 }
595}
596
597define_type_id!(
598 RecGroupId,
599 Range<CoreTypeId>,
600 rec_group_elements,
601 "recursion group"
602);
603
604impl TypeData for Range<CoreTypeId> {
605 type Id = RecGroupId;
606
607 fn type_info(&self, _types: &TypeList) -> TypeInfo {
608 let size = self.end.index() - self.start.index();
609 TypeInfo::core(u32::try_from(size).unwrap())
610 }
611}
612
613define_type_id!(ComponentTypeId, ComponentType, components, "component");
614
615define_type_id!(
616 ComponentValueTypeId,
617 ComponentValType,
618 component_values,
619 "component value"
620);
621
622define_type_id!(
623 ComponentInstanceTypeId,
624 ComponentInstanceType,
625 component_instances,
626 "component instance"
627);
628
629define_type_id!(
630 ComponentFuncTypeId,
631 ComponentFuncType,
632 component_funcs,
633 "component function"
634);
635
636define_type_id!(
637 ComponentCoreInstanceTypeId,
638 InstanceType,
639 core_instances,
640 "component's core instance"
641);
642
643define_type_id!(
644 ComponentCoreModuleTypeId,
645 ModuleType,
646 core_modules,
647 "component's core module"
648);
649
650#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
653#[repr(C)]
654pub struct ComponentDefinedTypeId {
655 index: u32,
656 alias_id: u32,
657}
658
659const _: () = {
660 assert!(crate::std::mem::size_of::<ComponentDefinedTypeId>() <= 8);
661};
662
663impl TypeIdentifier for ComponentDefinedTypeId {
664 type Data = ComponentDefinedType;
665
666 fn from_index(index: u32) -> Self {
667 ComponentDefinedTypeId {
668 index,
669 alias_id: NO_ALIAS,
670 }
671 }
672
673 fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
674 &types.component_defined_types
675 }
676
677 fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
678 &mut types.component_defined_types
679 }
680
681 fn index(&self) -> usize {
682 usize::try_from(self.index).unwrap()
683 }
684}
685
686impl Aliasable for ComponentDefinedTypeId {
687 fn alias_id(&self) -> u32 {
688 self.alias_id
689 }
690
691 fn set_alias_id(&mut self, alias_id: u32) {
692 self.alias_id = alias_id;
693 }
694}
695
696#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
719#[doc(hidden)]
721pub struct TypeInfo(u32);
722
723impl TypeInfo {
724 pub(crate) fn new() -> TypeInfo {
729 TypeInfo::_new(1, false)
730 }
731
732 pub(crate) fn borrow() -> TypeInfo {
735 TypeInfo::_new(1, true)
736 }
737
738 pub(crate) fn core(size: u32) -> TypeInfo {
741 TypeInfo::_new(size, false)
742 }
743
744 fn _new(size: u32, contains_borrow: bool) -> TypeInfo {
745 assert!(size < (1 << 24));
746 TypeInfo(size | ((contains_borrow as u32) << 31))
747 }
748
749 pub(crate) fn combine(&mut self, other: TypeInfo, offset: usize) -> Result<()> {
758 *self = TypeInfo::_new(
759 super::combine_type_sizes(self.size(), other.size(), offset)?,
760 self.contains_borrow() || other.contains_borrow(),
761 );
762 Ok(())
763 }
764
765 pub(crate) fn size(&self) -> u32 {
766 self.0 & 0xffffff
767 }
768
769 pub(crate) fn contains_borrow(&self) -> bool {
770 (self.0 >> 31) != 0
771 }
772}
773
774#[derive(Debug, Clone, Copy)]
776pub enum ComponentValType {
777 Primitive(PrimitiveValType),
779 Type(ComponentDefinedTypeId),
781}
782
783impl TypeData for ComponentValType {
784 type Id = ComponentValueTypeId;
785
786 fn type_info(&self, types: &TypeList) -> TypeInfo {
787 match self {
788 ComponentValType::Primitive(_) => TypeInfo::new(),
789 ComponentValType::Type(id) => types[*id].type_info(types),
790 }
791 }
792}
793
794impl ComponentValType {
795 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
796 match self {
797 ComponentValType::Primitive(ty) => ty.contains_ptr(),
798 ComponentValType::Type(ty) => types[*ty].contains_ptr(types),
799 }
800 }
801
802 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
803 match self {
804 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
805 Self::Type(id) => types[*id].push_wasm_types(types, lowered_types),
806 }
807 }
808
809 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
810 match self {
811 Self::Primitive(_) => TypeInfo::new(),
812 Self::Type(id) => types[*id].type_info(types),
813 }
814 }
815}
816
817#[derive(Debug, Clone, Copy)]
819pub enum EntityType {
820 Func(CoreTypeId),
822 Table(TableType),
824 Memory(MemoryType),
826 Global(GlobalType),
828 Tag(CoreTypeId),
830}
831
832impl EntityType {
833 pub(crate) fn desc(&self) -> &'static str {
834 match self {
835 Self::Func(_) => "func",
836 Self::Table(_) => "table",
837 Self::Memory(_) => "memory",
838 Self::Global(_) => "global",
839 Self::Tag(_) => "tag",
840 }
841 }
842
843 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
844 match self {
845 Self::Func(id) | Self::Tag(id) => types[*id].type_info(types),
846 Self::Table(_) | Self::Memory(_) | Self::Global(_) => TypeInfo::new(),
847 }
848 }
849}
850
851trait ModuleImportKey {
852 fn module(&self) -> &str;
853 fn name(&self) -> &str;
854}
855
856impl<'a> Borrow<dyn ModuleImportKey + 'a> for (String, String) {
857 fn borrow(&self) -> &(dyn ModuleImportKey + 'a) {
858 self
859 }
860}
861
862impl Hash for (dyn ModuleImportKey + '_) {
863 fn hash<H: Hasher>(&self, state: &mut H) {
864 self.module().hash(state);
865 self.name().hash(state);
866 }
867}
868
869impl PartialEq for (dyn ModuleImportKey + '_) {
870 fn eq(&self, other: &Self) -> bool {
871 self.module() == other.module() && self.name() == other.name()
872 }
873}
874
875impl Eq for (dyn ModuleImportKey + '_) {}
876
877impl ModuleImportKey for (String, String) {
878 fn module(&self) -> &str {
879 &self.0
880 }
881
882 fn name(&self) -> &str {
883 &self.1
884 }
885}
886
887impl ModuleImportKey for (&str, &str) {
888 fn module(&self) -> &str {
889 self.0
890 }
891
892 fn name(&self) -> &str {
893 self.1
894 }
895}
896
897#[derive(Debug, Clone)]
899pub struct ModuleType {
900 pub(crate) info: TypeInfo,
902 pub imports: IndexMap<(String, String), EntityType, RandomState>,
904 pub exports: IndexMap<String, EntityType, RandomState>,
906}
907
908impl TypeData for ModuleType {
909 type Id = ComponentCoreModuleTypeId;
910
911 fn type_info(&self, _types: &TypeList) -> TypeInfo {
912 self.info
913 }
914}
915
916impl ModuleType {
917 pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
921 self.imports.get(&(module, name) as &dyn ModuleImportKey)
922 }
923}
924
925#[derive(Debug, Clone)]
927pub enum CoreInstanceTypeKind {
928 Instantiated(ComponentCoreModuleTypeId),
930
931 Exports(IndexMap<String, EntityType, RandomState>),
933}
934
935#[derive(Debug, Clone)]
937pub struct InstanceType {
938 pub(crate) info: TypeInfo,
940 pub kind: CoreInstanceTypeKind,
942}
943
944impl TypeData for InstanceType {
945 type Id = ComponentCoreInstanceTypeId;
946
947 fn type_info(&self, _types: &TypeList) -> TypeInfo {
948 self.info
949 }
950}
951
952impl InstanceType {
953 pub fn exports<'a>(
955 &'a self,
956 types: TypesRef<'a>,
957 ) -> &'a IndexMap<String, EntityType, RandomState> {
958 self.internal_exports(types.list)
959 }
960
961 pub(crate) fn internal_exports<'a>(
962 &'a self,
963 types: &'a TypeList,
964 ) -> &'a IndexMap<String, EntityType, RandomState> {
965 match &self.kind {
966 CoreInstanceTypeKind::Instantiated(id) => &types[*id].exports,
967 CoreInstanceTypeKind::Exports(exports) => exports,
968 }
969 }
970}
971
972#[derive(Debug, Clone, Copy)]
974pub enum ComponentEntityType {
975 Module(ComponentCoreModuleTypeId),
977 Func(ComponentFuncTypeId),
979 Value(ComponentValType),
981 Type {
983 referenced: ComponentAnyTypeId,
986 created: ComponentAnyTypeId,
993 },
994 Instance(ComponentInstanceTypeId),
996 Component(ComponentTypeId),
998}
999
1000impl ComponentEntityType {
1001 pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
1003 SubtypeCx::new(at.list, bt.list)
1004 .component_entity_type(a, b, 0)
1005 .is_ok()
1006 }
1007
1008 pub(crate) fn desc(&self) -> &'static str {
1009 match self {
1010 Self::Module(_) => "module",
1011 Self::Func(_) => "func",
1012 Self::Value(_) => "value",
1013 Self::Type { .. } => "type",
1014 Self::Instance(_) => "instance",
1015 Self::Component(_) => "component",
1016 }
1017 }
1018
1019 pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
1020 match self {
1021 Self::Module(ty) => types[*ty].type_info(types),
1022 Self::Func(ty) => types[*ty].type_info(types),
1023 Self::Type { referenced: ty, .. } => ty.info(types),
1024 Self::Instance(ty) => types[*ty].type_info(types),
1025 Self::Component(ty) => types[*ty].type_info(types),
1026 Self::Value(ty) => ty.info(types),
1027 }
1028 }
1029}
1030
1031#[derive(Debug, Clone)]
1033pub struct ComponentType {
1034 pub(crate) info: TypeInfo,
1036
1037 pub imports: IndexMap<String, ComponentEntityType, RandomState>,
1042
1043 pub exports: IndexMap<String, ComponentEntityType, RandomState>,
1048
1049 pub imported_resources: Vec<(ResourceId, Vec<usize>)>,
1065
1066 pub defined_resources: Vec<(ResourceId, Vec<usize>)>,
1075
1076 pub explicit_resources: IndexMap<ResourceId, Vec<usize>, RandomState>,
1085}
1086
1087impl TypeData for ComponentType {
1088 type Id = ComponentTypeId;
1089
1090 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1091 self.info
1092 }
1093}
1094
1095#[derive(Debug, Clone)]
1097pub struct ComponentInstanceType {
1098 pub(crate) info: TypeInfo,
1100
1101 pub exports: IndexMap<String, ComponentEntityType, RandomState>,
1105
1106 pub defined_resources: Vec<ResourceId>,
1139
1140 pub explicit_resources: IndexMap<ResourceId, Vec<usize>, RandomState>,
1143}
1144
1145impl TypeData for ComponentInstanceType {
1146 type Id = ComponentInstanceTypeId;
1147
1148 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1149 self.info
1150 }
1151}
1152
1153#[derive(Debug, Clone)]
1155pub struct ComponentFuncType {
1156 pub(crate) info: TypeInfo,
1158 pub params: Box<[(KebabString, ComponentValType)]>,
1160 pub results: Box<[(Option<KebabString>, ComponentValType)]>,
1162}
1163
1164impl TypeData for ComponentFuncType {
1165 type Id = ComponentFuncTypeId;
1166
1167 fn type_info(&self, _types: &TypeList) -> TypeInfo {
1168 self.info
1169 }
1170}
1171
1172impl ComponentFuncType {
1173 pub(crate) fn lower(&self, types: &TypeList, is_lower: bool) -> LoweringInfo {
1176 let mut info = LoweringInfo::default();
1177
1178 for (_, ty) in self.params.iter() {
1179 if is_lower {
1186 if !info.requires_memory {
1187 info.requires_memory = ty.contains_ptr(types);
1188 }
1189 } else {
1190 if !info.requires_realloc {
1191 info.requires_realloc = ty.contains_ptr(types);
1192 }
1193 }
1194
1195 if !ty.push_wasm_types(types, &mut info.params) {
1196 info.params.clear();
1200 assert!(info.params.push(ValType::I32));
1201 info.requires_memory = true;
1202
1203 if !is_lower {
1205 info.requires_realloc = true;
1206 }
1207 break;
1208 }
1209 }
1210
1211 for (_, ty) in self.results.iter() {
1212 if is_lower && !info.requires_realloc {
1217 info.requires_realloc = ty.contains_ptr(types);
1218 }
1219
1220 if !ty.push_wasm_types(types, &mut info.results) {
1221 info.results.clear();
1224 if is_lower {
1225 info.params.max = MAX_LOWERED_TYPES;
1226 assert!(info.params.push(ValType::I32));
1227 } else {
1228 assert!(info.results.push(ValType::I32));
1229 }
1230 info.requires_memory = true;
1231 break;
1232 }
1233 }
1234
1235 info.requires_memory |= info.requires_realloc;
1237
1238 info
1239 }
1240}
1241
1242#[derive(Debug, Clone)]
1244pub struct VariantCase {
1245 pub ty: Option<ComponentValType>,
1247 pub refines: Option<KebabString>,
1249}
1250
1251#[derive(Debug, Clone)]
1253pub struct RecordType {
1254 pub(crate) info: TypeInfo,
1256 pub fields: IndexMap<KebabString, ComponentValType, RandomState>,
1258}
1259
1260#[derive(Debug, Clone)]
1262pub struct VariantType {
1263 pub(crate) info: TypeInfo,
1265 pub cases: IndexMap<KebabString, VariantCase, RandomState>,
1267}
1268
1269#[derive(Debug, Clone)]
1271pub struct TupleType {
1272 pub(crate) info: TypeInfo,
1274 pub types: Box<[ComponentValType]>,
1276}
1277
1278#[derive(Debug, Clone)]
1280pub enum ComponentDefinedType {
1281 Primitive(PrimitiveValType),
1283 Record(RecordType),
1285 Variant(VariantType),
1287 List(ComponentValType),
1289 Tuple(TupleType),
1291 Flags(IndexSet<KebabString, RandomState>),
1293 Enum(IndexSet<KebabString, RandomState>),
1295 Option(ComponentValType),
1297 Result {
1299 ok: Option<ComponentValType>,
1301 err: Option<ComponentValType>,
1303 },
1304 Own(AliasableResourceId),
1306 Borrow(AliasableResourceId),
1308}
1309
1310impl TypeData for ComponentDefinedType {
1311 type Id = ComponentDefinedTypeId;
1312
1313 fn type_info(&self, types: &TypeList) -> TypeInfo {
1314 match self {
1315 Self::Primitive(_) | Self::Flags(_) | Self::Enum(_) | Self::Own(_) => TypeInfo::new(),
1316 Self::Borrow(_) => TypeInfo::borrow(),
1317 Self::Record(r) => r.info,
1318 Self::Variant(v) => v.info,
1319 Self::Tuple(t) => t.info,
1320 Self::List(ty) | Self::Option(ty) => ty.info(types),
1321 Self::Result { ok, err } => {
1322 let default = TypeInfo::new();
1323 let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1324 info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1325 .unwrap();
1326 info
1327 }
1328 }
1329 }
1330}
1331
1332impl ComponentDefinedType {
1333 pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1334 match self {
1335 Self::Primitive(ty) => ty.contains_ptr(),
1336 Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1337 Self::Variant(v) => v
1338 .cases
1339 .values()
1340 .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1341 Self::List(_) => true,
1342 Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1343 Self::Flags(_) | Self::Enum(_) | Self::Own(_) | Self::Borrow(_) => false,
1344 Self::Option(ty) => ty.contains_ptr(types),
1345 Self::Result { ok, err } => {
1346 ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1347 || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1348 }
1349 }
1350 }
1351
1352 fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1353 match self {
1354 Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1355 Self::Record(r) => r
1356 .fields
1357 .iter()
1358 .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1359 Self::Variant(v) => Self::push_variant_wasm_types(
1360 v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1361 types,
1362 lowered_types,
1363 ),
1364 Self::List(_) => lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32),
1365 Self::Tuple(t) => t
1366 .types
1367 .iter()
1368 .all(|ty| ty.push_wasm_types(types, lowered_types)),
1369 Self::Flags(names) => {
1370 (0..(names.len() + 31) / 32).all(|_| lowered_types.push(ValType::I32))
1371 }
1372 Self::Enum(_) | Self::Own(_) | Self::Borrow(_) => lowered_types.push(ValType::I32),
1373 Self::Option(ty) => {
1374 Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1375 }
1376 Self::Result { ok, err } => {
1377 Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1378 }
1379 }
1380 }
1381
1382 fn push_variant_wasm_types<'a>(
1383 cases: impl Iterator<Item = &'a ComponentValType>,
1384 types: &TypeList,
1385 lowered_types: &mut LoweredTypes,
1386 ) -> bool {
1387 if !lowered_types.push(ValType::I32) {
1389 return false;
1390 }
1391
1392 let start = lowered_types.len();
1393
1394 for ty in cases {
1395 let mut temp = LoweredTypes::new(lowered_types.max);
1396
1397 if !ty.push_wasm_types(types, &mut temp) {
1398 return false;
1399 }
1400
1401 for (i, ty) in temp.iter().enumerate() {
1402 match lowered_types.get_mut(start + i) {
1403 Some(prev) => *prev = Self::join_types(*prev, ty),
1404 None => {
1405 if !lowered_types.push(ty) {
1406 return false;
1407 }
1408 }
1409 }
1410 }
1411 }
1412
1413 true
1414 }
1415
1416 fn join_types(a: ValType, b: ValType) -> ValType {
1417 use ValType::*;
1418
1419 match (a, b) {
1420 (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1421 (I32, F32) | (F32, I32) => I32,
1422 (_, I64 | F64) | (I64 | F64, _) => I64,
1423 _ => panic!("unexpected wasm type for canonical ABI"),
1424 }
1425 }
1426
1427 fn desc(&self) -> &'static str {
1428 match self {
1429 ComponentDefinedType::Record(_) => "record",
1430 ComponentDefinedType::Primitive(_) => "primitive",
1431 ComponentDefinedType::Variant(_) => "variant",
1432 ComponentDefinedType::Tuple(_) => "tuple",
1433 ComponentDefinedType::Enum(_) => "enum",
1434 ComponentDefinedType::Flags(_) => "flags",
1435 ComponentDefinedType::Option(_) => "option",
1436 ComponentDefinedType::List(_) => "list",
1437 ComponentDefinedType::Result { .. } => "result",
1438 ComponentDefinedType::Own(_) => "own",
1439 ComponentDefinedType::Borrow(_) => "borrow",
1440 }
1441 }
1442}
1443
1444#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1447#[repr(packed(4))] pub struct ResourceId {
1449 globally_unique_id: usize,
1459
1460 contextually_unique_id: u32,
1469}
1470
1471#[allow(clippy::large_enum_variant)]
1472enum TypesKind {
1473 Module(Arc<Module>),
1474 Component(ComponentState),
1475}
1476
1477pub struct Types {
1481 list: TypeList,
1482 kind: TypesKind,
1483}
1484
1485#[derive(Clone, Copy)]
1486enum TypesRefKind<'a> {
1487 Module(&'a Module),
1488 Component(&'a ComponentState),
1489}
1490
1491#[derive(Clone, Copy)]
1495pub struct TypesRef<'a> {
1496 list: &'a TypeList,
1497 kind: TypesRefKind<'a>,
1498}
1499
1500impl<'a> TypesRef<'a> {
1501 pub(crate) fn from_module(types: &'a TypeList, module: &'a Module) -> Self {
1502 Self {
1503 list: types,
1504 kind: TypesRefKind::Module(module),
1505 }
1506 }
1507
1508 pub(crate) fn from_component(types: &'a TypeList, component: &'a ComponentState) -> Self {
1509 Self {
1510 list: types,
1511 kind: TypesRefKind::Component(component),
1512 }
1513 }
1514
1515 pub fn get<T>(&self, id: T) -> Option<&'a T::Data>
1519 where
1520 T: TypeIdentifier,
1521 {
1522 self.list.get(id)
1523 }
1524
1525 pub fn core_type_at(&self, index: u32) -> ComponentCoreTypeId {
1534 match &self.kind {
1535 TypesRefKind::Module(module) => ComponentCoreTypeId::Sub(module.types[index as usize]),
1536 TypesRefKind::Component(component) => component.core_types[index as usize],
1537 }
1538 }
1539
1540 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1547 match &self.kind {
1548 TypesRefKind::Module(_) => panic!("not a component"),
1549 TypesRefKind::Component(component) => component.types[index as usize],
1550 }
1551 }
1552
1553 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1560 match self.component_any_type_at(index) {
1561 ComponentAnyTypeId::Component(id) => id,
1562 _ => panic!("not a component type"),
1563 }
1564 }
1565
1566 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1573 match self.component_any_type_at(index) {
1574 ComponentAnyTypeId::Defined(id) => id,
1575 _ => panic!("not a defined type"),
1576 }
1577 }
1578
1579 pub fn core_type_count(&self) -> u32 {
1581 match &self.kind {
1582 TypesRefKind::Module(module) => module.types.len() as u32,
1583 TypesRefKind::Component(component) => component.core_types.len() as u32,
1584 }
1585 }
1586
1587 pub fn component_type_count(&self) -> u32 {
1589 match &self.kind {
1590 TypesRefKind::Module(_module) => 0,
1591 TypesRefKind::Component(component) => component.types.len() as u32,
1592 }
1593 }
1594
1595 pub fn table_at(&self, index: u32) -> TableType {
1601 let tables = match &self.kind {
1602 TypesRefKind::Module(module) => &module.tables,
1603 TypesRefKind::Component(component) => &component.core_tables,
1604 };
1605 tables[index as usize]
1606 }
1607
1608 pub fn table_count(&self) -> u32 {
1610 match &self.kind {
1611 TypesRefKind::Module(module) => module.tables.len() as u32,
1612 TypesRefKind::Component(component) => component.core_tables.len() as u32,
1613 }
1614 }
1615
1616 pub fn memory_at(&self, index: u32) -> MemoryType {
1622 let memories = match &self.kind {
1623 TypesRefKind::Module(module) => &module.memories,
1624 TypesRefKind::Component(component) => &component.core_memories,
1625 };
1626
1627 memories[index as usize]
1628 }
1629
1630 pub fn memory_count(&self) -> u32 {
1632 match &self.kind {
1633 TypesRefKind::Module(module) => module.memories.len() as u32,
1634 TypesRefKind::Component(component) => component.core_memories.len() as u32,
1635 }
1636 }
1637
1638 pub fn global_at(&self, index: u32) -> GlobalType {
1644 let globals = match &self.kind {
1645 TypesRefKind::Module(module) => &module.globals,
1646 TypesRefKind::Component(component) => &component.core_globals,
1647 };
1648
1649 globals[index as usize]
1650 }
1651
1652 pub fn global_count(&self) -> u32 {
1654 match &self.kind {
1655 TypesRefKind::Module(module) => module.globals.len() as u32,
1656 TypesRefKind::Component(component) => component.core_globals.len() as u32,
1657 }
1658 }
1659
1660 pub fn tag_at(&self, index: u32) -> CoreTypeId {
1666 let tags = match &self.kind {
1667 TypesRefKind::Module(module) => &module.tags,
1668 TypesRefKind::Component(component) => &component.core_tags,
1669 };
1670 tags[index as usize]
1671 }
1672
1673 pub fn tag_count(&self) -> u32 {
1675 match &self.kind {
1676 TypesRefKind::Module(module) => module.tags.len() as u32,
1677 TypesRefKind::Component(component) => component.core_tags.len() as u32,
1678 }
1679 }
1680
1681 pub fn core_function_at(&self, index: u32) -> CoreTypeId {
1687 match &self.kind {
1688 TypesRefKind::Module(module) => module.types[module.functions[index as usize] as usize],
1689 TypesRefKind::Component(component) => component.core_funcs[index as usize],
1690 }
1691 }
1692
1693 pub fn function_count(&self) -> u32 {
1698 match &self.kind {
1699 TypesRefKind::Module(module) => module.functions.len() as u32,
1700 TypesRefKind::Component(component) => component.core_funcs.len() as u32,
1701 }
1702 }
1703
1704 pub fn element_at(&self, index: u32) -> RefType {
1710 match &self.kind {
1711 TypesRefKind::Module(module) => module.element_types[index as usize],
1712 TypesRefKind::Component(_) => {
1713 panic!("no elements on a component")
1714 }
1715 }
1716 }
1717
1718 pub fn element_count(&self) -> u32 {
1720 match &self.kind {
1721 TypesRefKind::Module(module) => module.element_types.len() as u32,
1722 TypesRefKind::Component(_) => 0,
1723 }
1724 }
1725
1726 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1733 match &self.kind {
1734 TypesRefKind::Module(_) => panic!("not a component"),
1735 TypesRefKind::Component(component) => component.funcs[index as usize],
1736 }
1737 }
1738
1739 pub fn component_function_count(&self) -> u32 {
1741 match &self.kind {
1742 TypesRefKind::Module(_module) => 0,
1743 TypesRefKind::Component(component) => component.funcs.len() as u32,
1744 }
1745 }
1746
1747 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1754 match &self.kind {
1755 TypesRefKind::Module(_) => panic!("not a component"),
1756 TypesRefKind::Component(component) => component.core_modules[index as usize],
1757 }
1758 }
1759
1760 pub fn module_count(&self) -> u32 {
1762 match &self.kind {
1763 TypesRefKind::Module(_module) => 0,
1764 TypesRefKind::Component(component) => component.core_modules.len() as u32,
1765 }
1766 }
1767
1768 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1775 match &self.kind {
1776 TypesRefKind::Module(_) => panic!("not a component"),
1777 TypesRefKind::Component(component) => component.core_instances[index as usize],
1778 }
1779 }
1780
1781 pub fn core_instance_count(&self) -> u32 {
1783 match &self.kind {
1784 TypesRefKind::Module(_module) => 0,
1785 TypesRefKind::Component(component) => component.core_instances.len() as u32,
1786 }
1787 }
1788
1789 pub fn component_at(&self, index: u32) -> ComponentTypeId {
1796 match &self.kind {
1797 TypesRefKind::Module(_) => panic!("not a component"),
1798 TypesRefKind::Component(component) => component.components[index as usize],
1799 }
1800 }
1801
1802 pub fn component_count(&self) -> u32 {
1804 match &self.kind {
1805 TypesRefKind::Module(_module) => 0,
1806 TypesRefKind::Component(component) => component.components.len() as u32,
1807 }
1808 }
1809
1810 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1817 match &self.kind {
1818 TypesRefKind::Module(_) => panic!("not a component"),
1819 TypesRefKind::Component(component) => component.instances[index as usize],
1820 }
1821 }
1822
1823 pub fn component_instance_count(&self) -> u32 {
1825 match &self.kind {
1826 TypesRefKind::Module(_module) => 0,
1827 TypesRefKind::Component(component) => component.instances.len() as u32,
1828 }
1829 }
1830
1831 pub fn value_at(&self, index: u32) -> ComponentValType {
1838 match &self.kind {
1839 TypesRefKind::Module(_) => panic!("not a component"),
1840 TypesRefKind::Component(component) => component.values[index as usize].0,
1841 }
1842 }
1843
1844 pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
1846 match &self.kind {
1847 TypesRefKind::Module(module) => Some(match import.ty {
1848 TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx as usize)?),
1849 TypeRef::Table(ty) => EntityType::Table(ty),
1850 TypeRef::Memory(ty) => EntityType::Memory(ty),
1851 TypeRef::Global(ty) => EntityType::Global(ty),
1852 TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx as usize)?),
1853 }),
1854 TypesRefKind::Component(_) => None,
1855 }
1856 }
1857
1858 pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
1860 match &self.kind {
1861 TypesRefKind::Module(module) => Some(match export.kind {
1862 ExternalKind::Func => EntityType::Func(
1863 module.types[*module.functions.get(export.index as usize)? as usize],
1864 ),
1865 ExternalKind::Table => {
1866 EntityType::Table(*module.tables.get(export.index as usize)?)
1867 }
1868 ExternalKind::Memory => {
1869 EntityType::Memory(*module.memories.get(export.index as usize)?)
1870 }
1871 ExternalKind::Global => {
1872 EntityType::Global(*module.globals.get(export.index as usize)?)
1873 }
1874 ExternalKind::Tag => EntityType::Tag(
1875 module.types[*module.functions.get(export.index as usize)? as usize],
1876 ),
1877 }),
1878 TypesRefKind::Component(_) => None,
1879 }
1880 }
1881
1882 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
1884 match &self.kind {
1885 TypesRefKind::Module(_) => None,
1886 TypesRefKind::Component(component) => Some(*component.imports.get(name)?),
1887 }
1888 }
1889
1890 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
1892 match &self.kind {
1893 TypesRefKind::Module(_) => None,
1894 TypesRefKind::Component(component) => Some(*component.exports.get(name)?),
1895 }
1896 }
1897
1898 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
1902 where
1903 T: Aliasable,
1904 {
1905 self.list.peel_alias(ty)
1906 }
1907}
1908
1909impl<T> Index<T> for TypesRef<'_>
1910where
1911 T: TypeIdentifier,
1912{
1913 type Output = T::Data;
1914
1915 fn index(&self, index: T) -> &Self::Output {
1916 &self.list[index]
1917 }
1918}
1919
1920impl Types {
1921 pub(crate) fn from_module(types: TypeList, module: Arc<Module>) -> Self {
1922 Self {
1923 list: types,
1924 kind: TypesKind::Module(module),
1925 }
1926 }
1927
1928 pub(crate) fn from_component(types: TypeList, component: ComponentState) -> Self {
1929 Self {
1930 list: types,
1931 kind: TypesKind::Component(component),
1932 }
1933 }
1934
1935 pub fn as_ref(&self) -> TypesRef {
1937 TypesRef {
1938 list: &self.list,
1939 kind: match &self.kind {
1940 TypesKind::Module(module) => TypesRefKind::Module(module),
1941 TypesKind::Component(component) => TypesRefKind::Component(component),
1942 },
1943 }
1944 }
1945
1946 pub fn get<T>(&self, id: T) -> Option<&T::Data>
1950 where
1951 T: TypeIdentifier,
1952 {
1953 self.as_ref().get(id)
1954 }
1955
1956 pub fn core_type_at(&self, index: u32) -> ComponentCoreTypeId {
1965 self.as_ref().core_type_at(index)
1966 }
1967
1968 pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1977 self.as_ref().component_any_type_at(index)
1978 }
1979
1980 pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1986 self.as_ref().component_type_at(index)
1987 }
1988
1989 pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1996 self.as_ref().component_defined_type_at(index)
1997 }
1998
1999 pub fn type_count(&self) -> usize {
2001 match &self.kind {
2002 TypesKind::Module(module) => module.types.len(),
2003 TypesKind::Component(component) => component.core_types.len(),
2004 }
2005 }
2006
2007 pub fn table_at(&self, index: u32) -> TableType {
2013 self.as_ref().table_at(index)
2014 }
2015
2016 pub fn table_count(&self) -> usize {
2018 match &self.kind {
2019 TypesKind::Module(module) => module.tables.len(),
2020 TypesKind::Component(component) => component.core_tables.len(),
2021 }
2022 }
2023
2024 pub fn memory_at(&self, index: u32) -> MemoryType {
2030 self.as_ref().memory_at(index)
2031 }
2032
2033 pub fn memory_count(&self) -> u32 {
2035 self.as_ref().memory_count()
2036 }
2037
2038 pub fn global_at(&self, index: u32) -> GlobalType {
2044 self.as_ref().global_at(index)
2045 }
2046
2047 pub fn global_count(&self) -> u32 {
2049 self.as_ref().global_count()
2050 }
2051
2052 pub fn tag_at(&self, index: u32) -> CoreTypeId {
2058 self.as_ref().tag_at(index)
2059 }
2060
2061 pub fn tag_count(&self) -> u32 {
2063 self.as_ref().tag_count()
2064 }
2065
2066 pub fn core_function_at(&self, index: u32) -> CoreTypeId {
2072 self.as_ref().core_function_at(index)
2073 }
2074
2075 pub fn core_function_count(&self) -> u32 {
2080 self.as_ref().function_count()
2081 }
2082
2083 pub fn element_at(&self, index: u32) -> RefType {
2089 self.as_ref().element_at(index)
2090 }
2091
2092 pub fn element_count(&self) -> u32 {
2094 self.as_ref().element_count()
2095 }
2096
2097 pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2104 self.as_ref().component_function_at(index)
2105 }
2106
2107 pub fn component_function_count(&self) -> u32 {
2109 self.as_ref().component_function_count()
2110 }
2111
2112 pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2119 self.as_ref().module_at(index)
2120 }
2121
2122 pub fn module_count(&self) -> usize {
2124 match &self.kind {
2125 TypesKind::Module(_) => 0,
2126 TypesKind::Component(component) => component.core_modules.len(),
2127 }
2128 }
2129
2130 pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2137 self.as_ref().core_instance_at(index)
2138 }
2139
2140 pub fn core_instance_count(&self) -> usize {
2142 match &self.kind {
2143 TypesKind::Module(_) => 0,
2144 TypesKind::Component(component) => component.core_instances.len(),
2145 }
2146 }
2147
2148 pub fn component_at(&self, index: u32) -> ComponentTypeId {
2155 self.as_ref().component_at(index)
2156 }
2157
2158 pub fn component_count(&self) -> usize {
2160 match &self.kind {
2161 TypesKind::Module(_) => 0,
2162 TypesKind::Component(component) => component.components.len(),
2163 }
2164 }
2165
2166 pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2173 self.as_ref().component_instance_at(index)
2174 }
2175
2176 pub fn component_instance_count(&self) -> usize {
2178 match &self.kind {
2179 TypesKind::Module(_) => 0,
2180 TypesKind::Component(component) => component.instances.len(),
2181 }
2182 }
2183
2184 pub fn value_at(&self, index: u32) -> ComponentValType {
2191 self.as_ref().value_at(index)
2192 }
2193
2194 pub fn value_count(&self) -> usize {
2196 match &self.kind {
2197 TypesKind::Module(_) => 0,
2198 TypesKind::Component(component) => component.values.len(),
2199 }
2200 }
2201
2202 pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
2204 self.as_ref().entity_type_from_import(import)
2205 }
2206
2207 pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
2209 self.as_ref().entity_type_from_export(export)
2210 }
2211
2212 pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2214 self.as_ref().component_entity_type_of_import(name)
2215 }
2216
2217 pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2219 self.as_ref().component_entity_type_of_export(name)
2220 }
2221
2222 pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2226 where
2227 T: Aliasable,
2228 {
2229 self.list.peel_alias(ty)
2230 }
2231}
2232
2233impl<T> Index<T> for Types
2234where
2235 T: TypeIdentifier,
2236{
2237 type Output = T::Data;
2238
2239 fn index(&self, id: T) -> &Self::Output {
2240 &self.list[id]
2241 }
2242}
2243
2244#[doc(hidden)]
2258pub struct SnapshotList<T> {
2259 snapshots: Vec<Arc<Snapshot<T>>>,
2269
2270 snapshots_total: usize,
2272
2273 cur: Vec<T>,
2275}
2276
2277struct Snapshot<T> {
2278 prior_types: usize,
2279 items: Vec<T>,
2280}
2281
2282impl<T> SnapshotList<T> {
2283 pub(crate) fn get(&self, index: usize) -> Option<&T> {
2285 if index >= self.snapshots_total {
2287 return self.cur.get(index - self.snapshots_total);
2288 }
2289 let i = match self
2293 .snapshots
2294 .binary_search_by_key(&index, |snapshot| snapshot.prior_types)
2295 {
2296 Ok(i) => i,
2297 Err(i) => i - 1,
2298 };
2299 let snapshot = &self.snapshots[i];
2300 Some(&snapshot.items[index - snapshot.prior_types])
2301 }
2302
2303 pub(crate) fn push(&mut self, val: T) {
2305 self.cur.push(val);
2306 }
2307
2308 pub(crate) fn len(&self) -> usize {
2310 self.cur.len() + self.snapshots_total
2311 }
2312
2313 pub(crate) fn truncate(&mut self, len: usize) {
2315 assert!(len >= self.snapshots_total);
2316 self.cur.truncate(len - self.snapshots_total);
2317 }
2318
2319 pub(crate) fn commit(&mut self) -> SnapshotList<T> {
2326 let len = self.cur.len();
2331 if len > 0 {
2332 self.cur.shrink_to_fit();
2333 self.snapshots.push(Arc::new(Snapshot {
2334 prior_types: self.snapshots_total,
2335 items: mem::take(&mut self.cur),
2336 }));
2337 self.snapshots_total += len;
2338 }
2339 SnapshotList {
2340 snapshots: self.snapshots.clone(),
2341 snapshots_total: self.snapshots_total,
2342 cur: Vec::new(),
2343 }
2344 }
2345}
2346
2347impl<T> Index<usize> for SnapshotList<T> {
2348 type Output = T;
2349
2350 #[inline]
2351 fn index(&self, index: usize) -> &T {
2352 self.get(index).unwrap()
2353 }
2354}
2355
2356impl<T, U> Index<U> for SnapshotList<T>
2357where
2358 U: TypeIdentifier<Data = T>,
2359{
2360 type Output = T;
2361
2362 #[inline]
2363 fn index(&self, id: U) -> &T {
2364 self.get(id.index()).unwrap()
2365 }
2366}
2367
2368impl<T> Default for SnapshotList<T> {
2369 fn default() -> SnapshotList<T> {
2370 SnapshotList {
2371 snapshots: Vec::new(),
2372 snapshots_total: 0,
2373 cur: Vec::new(),
2374 }
2375 }
2376}
2377
2378#[derive(Default)]
2386#[doc(hidden)]
2388pub struct TypeList {
2389 alias_mappings: HashMap<u32, u32>,
2391 alias_counter: u32,
2393 alias_snapshots: Vec<TypeListAliasSnapshot>,
2395
2396 core_types: SnapshotList<SubType>,
2400 core_type_to_rec_group: SnapshotList<RecGroupId>,
2404 core_type_to_supertype: SnapshotList<Option<CoreTypeId>>,
2408 rec_group_elements: SnapshotList<Range<CoreTypeId>>,
2411 canonical_rec_groups: Option<HashMap<RecGroup, RecGroupId>>,
2416
2417 components: SnapshotList<ComponentType>,
2419 component_defined_types: SnapshotList<ComponentDefinedType>,
2420 component_values: SnapshotList<ComponentValType>,
2421 component_instances: SnapshotList<ComponentInstanceType>,
2422 component_funcs: SnapshotList<ComponentFuncType>,
2423 core_modules: SnapshotList<ModuleType>,
2424 core_instances: SnapshotList<InstanceType>,
2425}
2426
2427#[derive(Clone, Debug)]
2428struct TypeListAliasSnapshot {
2429 alias_counter: u32,
2431
2432 alias_mappings: HashMap<u32, u32>,
2434}
2435
2436struct TypeListCheckpoint {
2437 core_types: usize,
2438 components: usize,
2439 component_defined_types: usize,
2440 component_values: usize,
2441 component_instances: usize,
2442 component_funcs: usize,
2443 core_modules: usize,
2444 core_instances: usize,
2445 core_type_to_rec_group: usize,
2446 core_type_to_supertype: usize,
2447 rec_group_elements: usize,
2448 canonical_rec_groups: usize,
2449}
2450
2451impl TypeList {
2452 pub fn get<T>(&self, id: T) -> Option<&T::Data>
2453 where
2454 T: TypeIdentifier,
2455 {
2456 T::list(self).get(id.index())
2457 }
2458
2459 pub fn push<T>(&mut self, ty: T) -> T::Id
2460 where
2461 T: TypeData,
2462 {
2463 let index = u32::try_from(T::Id::list(self).len()).unwrap();
2464 let id = T::Id::from_index(index);
2465 T::Id::list_mut(self).push(ty);
2466 id
2467 }
2468
2469 pub fn intern_canonical_rec_group(&mut self, rec_group: RecGroup) -> (bool, RecGroupId) {
2473 let canonical_rec_groups = self
2474 .canonical_rec_groups
2475 .as_mut()
2476 .expect("cannot intern into a committed list");
2477 let entry = match canonical_rec_groups.entry(rec_group) {
2478 Entry::Occupied(e) => return (false, *e.get()),
2479 Entry::Vacant(e) => e,
2480 };
2481
2482 let rec_group_id = self.rec_group_elements.len();
2483 let rec_group_id = u32::try_from(rec_group_id).unwrap();
2484 let rec_group_id = RecGroupId::from_index(rec_group_id);
2485
2486 let start = self.core_types.len();
2487 let start = u32::try_from(start).unwrap();
2488 let start = CoreTypeId::from_index(start);
2489
2490 for ty in entry.key().types() {
2491 debug_assert_eq!(self.core_types.len(), self.core_type_to_supertype.len());
2492 debug_assert_eq!(self.core_types.len(), self.core_type_to_rec_group.len());
2493
2494 self.core_type_to_supertype
2495 .push(ty.supertype_idx.map(|idx| match idx.unpack() {
2496 UnpackedIndex::RecGroup(offset) => CoreTypeId::from_index(start.index + offset),
2497 UnpackedIndex::Id(id) => id,
2498 UnpackedIndex::Module(_) => unreachable!("in canonical form"),
2499 }));
2500 let mut ty = ty.clone();
2501 ty.remap_indices(&mut |index| {
2502 match index.unpack() {
2503 UnpackedIndex::Id(_) => {}
2504 UnpackedIndex::Module(_) => unreachable!(),
2505 UnpackedIndex::RecGroup(offset) => {
2506 *index = UnpackedIndex::Id(CoreTypeId::from_index(start.index + offset))
2507 .pack()
2508 .unwrap();
2509 }
2510 };
2511 Ok(())
2512 })
2513 .expect("cannot fail");
2514 self.core_types.push(ty);
2515 self.core_type_to_rec_group.push(rec_group_id);
2516 }
2517
2518 let end = self.core_types.len();
2519 let end = u32::try_from(end).unwrap();
2520 let end = CoreTypeId::from_index(end);
2521
2522 let range = start..end;
2523
2524 self.rec_group_elements.push(range.clone());
2525
2526 entry.insert(rec_group_id);
2527 return (true, rec_group_id);
2528 }
2529
2530 pub fn rec_group_local_id(
2532 &self,
2533 rec_group: RecGroupId,
2534 index: u32,
2535 offset: usize,
2536 ) -> Result<CoreTypeId> {
2537 let elems = &self[rec_group];
2538 let len = elems.end.index() - elems.start.index();
2539 let len = u32::try_from(len).unwrap();
2540 if index < len {
2541 let id = u32::try_from(elems.start.index()).unwrap() + index;
2542 let id = CoreTypeId::from_index(id);
2543 Ok(id)
2544 } else {
2545 bail!(
2546 offset,
2547 "unknown type {index}: type index out of rec group bounds"
2548 )
2549 }
2550 }
2551
2552 pub fn rec_group_id_of(&self, id: CoreTypeId) -> RecGroupId {
2554 self.core_type_to_rec_group[id.index()]
2555 }
2556
2557 pub fn supertype_of(&self, id: CoreTypeId) -> Option<CoreTypeId> {
2559 self.core_type_to_supertype[id.index()]
2560 }
2561
2562 pub fn at_canonicalized_packed_index(
2566 &self,
2567 rec_group: RecGroupId,
2568 index: PackedIndex,
2569 offset: usize,
2570 ) -> Result<CoreTypeId> {
2571 self.at_canonicalized_unpacked_index(rec_group, index.unpack(), offset)
2572 }
2573
2574 pub fn at_canonicalized_unpacked_index(
2578 &self,
2579 rec_group: RecGroupId,
2580 index: UnpackedIndex,
2581 offset: usize,
2582 ) -> Result<CoreTypeId> {
2583 match index {
2584 UnpackedIndex::Module(_) => panic!("not canonicalized"),
2585 UnpackedIndex::Id(id) => Ok(id),
2586 UnpackedIndex::RecGroup(idx) => self.rec_group_local_id(rec_group, idx, offset),
2587 }
2588 }
2589
2590 pub fn matches(&self, a: CoreTypeId, b: CoreTypeId) -> bool {
2592 let a = WithRecGroup::new(self, a);
2593 let a = WithRecGroup::map(a, |a| &self[a]);
2594
2595 let b = WithRecGroup::new(self, b);
2596 let b = WithRecGroup::map(b, |b| &self[b]);
2597
2598 Matches::matches(self, a, b)
2599 }
2600
2601 pub fn id_is_subtype(&self, mut a: CoreTypeId, b: CoreTypeId) -> bool {
2604 loop {
2605 if a == b {
2606 return true;
2607 }
2608
2609 a = match self.supertype_of(a) {
2612 Some(a) => a,
2613 None => return false,
2614 };
2615 }
2616 }
2617
2618 pub fn reftype_is_subtype(&self, a: RefType, b: RefType) -> bool {
2622 self.reftype_is_subtype_impl(a, None, b, None)
2626 }
2627
2628 pub(crate) fn reftype_is_subtype_impl(
2634 &self,
2635 a: RefType,
2636 a_group: Option<RecGroupId>,
2637 b: RefType,
2638 b_group: Option<RecGroupId>,
2639 ) -> bool {
2640 if a == b && a_group == b_group {
2641 return true;
2642 }
2643
2644 if a.is_nullable() && !b.is_nullable() {
2645 return false;
2646 }
2647
2648 let core_type_id = |group: Option<RecGroupId>, index: UnpackedIndex| -> CoreTypeId {
2649 if let Some(id) = index.as_core_type_id() {
2650 id
2651 } else {
2652 self.at_canonicalized_unpacked_index(group.unwrap(), index, usize::MAX)
2653 .expect("type references are checked during canonicalization")
2654 }
2655 };
2656
2657 let subtype = |group, index| -> &SubType {
2658 let id = core_type_id(group, index);
2659 &self[id]
2660 };
2661
2662 use HeapType as HT;
2663 match (a.heap_type(), b.heap_type()) {
2664 (a, b) if a == b => true,
2665
2666 (HT::Eq | HT::I31 | HT::Struct | HT::Array | HT::None, HT::Any) => true,
2667 (HT::I31 | HT::Struct | HT::Array | HT::None, HT::Eq) => true,
2668 (HT::NoExtern, HT::Extern) => true,
2669 (HT::NoFunc, HT::Func) => true,
2670 (HT::None, HT::I31 | HT::Array | HT::Struct) => true,
2671
2672 (HT::Concrete(a), HT::Eq | HT::Any) => matches!(
2673 subtype(a_group, a).composite_type,
2674 CompositeType::Array(_) | CompositeType::Struct(_)
2675 ),
2676
2677 (HT::Concrete(a), HT::Struct) => {
2678 matches!(subtype(a_group, a).composite_type, CompositeType::Struct(_))
2679 }
2680
2681 (HT::Concrete(a), HT::Array) => {
2682 matches!(subtype(a_group, a).composite_type, CompositeType::Array(_))
2683 }
2684
2685 (HT::Concrete(a), HT::Func) => {
2686 matches!(subtype(a_group, a).composite_type, CompositeType::Func(_))
2687 }
2688
2689 (HT::Concrete(a), HT::Concrete(b)) => {
2690 self.id_is_subtype(core_type_id(a_group, a), core_type_id(b_group, b))
2691 }
2692
2693 (HT::None, HT::Concrete(b)) => matches!(
2694 subtype(b_group, b).composite_type,
2695 CompositeType::Array(_) | CompositeType::Struct(_)
2696 ),
2697
2698 (HT::NoFunc, HT::Concrete(b)) => {
2699 matches!(subtype(b_group, b).composite_type, CompositeType::Func(_))
2700 }
2701
2702 (HT::Concrete(_), _)
2705 | (HT::Func, _)
2706 | (HT::Extern, _)
2707 | (HT::Any, _)
2708 | (HT::None, _)
2709 | (HT::NoExtern, _)
2710 | (HT::NoFunc, _)
2711 | (HT::Eq, _)
2712 | (HT::Struct, _)
2713 | (HT::Array, _)
2714 | (HT::I31, _) => false,
2715
2716 (HT::Exn, _) => false,
2719 }
2720 }
2721
2722 pub fn valtype_is_subtype(&self, a: ValType, b: ValType) -> bool {
2726 match (a, b) {
2727 (a, b) if a == b => true,
2728 (ValType::Ref(a), ValType::Ref(b)) => self.reftype_is_subtype(a, b),
2729 (ValType::Ref(_), _)
2730 | (ValType::I32, _)
2731 | (ValType::I64, _)
2732 | (ValType::F32, _)
2733 | (ValType::F64, _)
2734 | (ValType::V128, _) => false,
2735 }
2736 }
2737
2738 pub fn top_type(&self, heap_type: &HeapType) -> HeapType {
2743 match *heap_type {
2744 HeapType::Concrete(idx) => match self[idx.as_core_type_id().unwrap()].composite_type {
2745 CompositeType::Func(_) => HeapType::Func,
2746 CompositeType::Array(_) | CompositeType::Struct(_) => HeapType::Any,
2747 },
2748 HeapType::Func | HeapType::NoFunc => HeapType::Func,
2749 HeapType::Extern | HeapType::NoExtern => HeapType::Extern,
2750 HeapType::Any
2751 | HeapType::Eq
2752 | HeapType::Struct
2753 | HeapType::Array
2754 | HeapType::I31
2755 | HeapType::None => HeapType::Any,
2756 HeapType::Exn => HeapType::Exn,
2757 }
2758 }
2759
2760 fn checkpoint(&self) -> TypeListCheckpoint {
2761 let TypeList {
2762 alias_mappings: _,
2763 alias_counter: _,
2764 alias_snapshots: _,
2765 core_types,
2766 components,
2767 component_defined_types,
2768 component_values,
2769 component_instances,
2770 component_funcs,
2771 core_modules,
2772 core_instances,
2773 core_type_to_rec_group,
2774 core_type_to_supertype,
2775 rec_group_elements,
2776 canonical_rec_groups,
2777 } = self;
2778
2779 TypeListCheckpoint {
2780 core_types: core_types.len(),
2781 components: components.len(),
2782 component_defined_types: component_defined_types.len(),
2783 component_values: component_values.len(),
2784 component_instances: component_instances.len(),
2785 component_funcs: component_funcs.len(),
2786 core_modules: core_modules.len(),
2787 core_instances: core_instances.len(),
2788 core_type_to_rec_group: core_type_to_rec_group.len(),
2789 core_type_to_supertype: core_type_to_supertype.len(),
2790 rec_group_elements: rec_group_elements.len(),
2791 canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
2792 }
2793 }
2794
2795 fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
2796 let TypeList {
2797 alias_mappings: _,
2798 alias_counter: _,
2799 alias_snapshots: _,
2800 core_types,
2801 components,
2802 component_defined_types,
2803 component_values,
2804 component_instances,
2805 component_funcs,
2806 core_modules,
2807 core_instances,
2808 core_type_to_rec_group,
2809 core_type_to_supertype,
2810 rec_group_elements,
2811 canonical_rec_groups,
2812 } = self;
2813
2814 core_types.truncate(checkpoint.core_types);
2815 components.truncate(checkpoint.components);
2816 component_defined_types.truncate(checkpoint.component_defined_types);
2817 component_values.truncate(checkpoint.component_values);
2818 component_instances.truncate(checkpoint.component_instances);
2819 component_funcs.truncate(checkpoint.component_funcs);
2820 core_modules.truncate(checkpoint.core_modules);
2821 core_instances.truncate(checkpoint.core_instances);
2822 core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
2823 core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
2824 rec_group_elements.truncate(checkpoint.rec_group_elements);
2825
2826 if let Some(canonical_rec_groups) = canonical_rec_groups {
2827 assert_eq!(
2828 canonical_rec_groups.len(),
2829 checkpoint.canonical_rec_groups,
2830 "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
2831 proper immutable and persistent hash map) so adding new groups is disallowed"
2832 );
2833 }
2834 }
2835
2836 pub fn commit(&mut self) -> TypeList {
2837 let alias_counter = self.alias_counter;
2841 self.alias_counter += 1;
2842
2843 self.alias_snapshots.push(TypeListAliasSnapshot {
2844 alias_counter,
2845 alias_mappings: mem::take(&mut self.alias_mappings),
2846 });
2847
2848 TypeList {
2849 alias_mappings: HashMap::new(),
2850 alias_counter: self.alias_counter,
2851 alias_snapshots: self.alias_snapshots.clone(),
2852 core_types: self.core_types.commit(),
2853 components: self.components.commit(),
2854 component_defined_types: self.component_defined_types.commit(),
2855 component_values: self.component_values.commit(),
2856 component_instances: self.component_instances.commit(),
2857 component_funcs: self.component_funcs.commit(),
2858 core_modules: self.core_modules.commit(),
2859 core_instances: self.core_instances.commit(),
2860 core_type_to_rec_group: self.core_type_to_rec_group.commit(),
2861 core_type_to_supertype: self.core_type_to_supertype.commit(),
2862 rec_group_elements: self.rec_group_elements.commit(),
2863 canonical_rec_groups: None,
2864 }
2865 }
2866
2867 pub fn with_unique<T>(&mut self, mut ty: T) -> T
2869 where
2870 T: Aliasable,
2871 {
2872 self.alias_mappings
2873 .insert(self.alias_counter, ty.alias_id());
2874 ty.set_alias_id(self.alias_counter);
2875 self.alias_counter += 1;
2876 ty
2877 }
2878
2879 pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
2883 where
2884 T: Aliasable,
2885 {
2886 let alias_id = ty.alias_id();
2887
2888 let i = match self
2895 .alias_snapshots
2896 .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
2897 {
2898 Ok(_) => unreachable!(),
2899 Err(i) => i,
2900 };
2901
2902 ty.set_alias_id(match self.alias_snapshots.get(i) {
2906 Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
2907 None => *self.alias_mappings.get(&alias_id)?,
2908 });
2909 Some(ty)
2910 }
2911}
2912
2913impl<T> Index<T> for TypeList
2914where
2915 T: TypeIdentifier,
2916{
2917 type Output = T::Data;
2918
2919 fn index(&self, id: T) -> &Self::Output {
2920 let arena = T::list(self);
2921 &arena[id.index()]
2922 }
2923}
2924
2925pub(crate) struct TypeAlloc {
2928 list: TypeList,
2929
2930 globally_unique_id: usize,
2933
2934 next_resource_id: u32,
2937}
2938
2939impl Default for TypeAlloc {
2940 fn default() -> TypeAlloc {
2941 static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
2942 let mut ret = TypeAlloc {
2943 list: TypeList::default(),
2944 globally_unique_id: {
2945 let id = NEXT_GLOBAL_ID.fetch_add(1, Ordering::Relaxed);
2946 if id > usize::MAX - 10_000 {
2947 NEXT_GLOBAL_ID.store(usize::MAX - 10_000, Ordering::Relaxed);
2948 panic!("overflow on the global id counter");
2949 }
2950 id
2951 },
2952 next_resource_id: 0,
2953 };
2954 ret.list.canonical_rec_groups = Some(Default::default());
2955 ret
2956 }
2957}
2958
2959impl Deref for TypeAlloc {
2960 type Target = TypeList;
2961 fn deref(&self) -> &TypeList {
2962 &self.list
2963 }
2964}
2965
2966impl DerefMut for TypeAlloc {
2967 fn deref_mut(&mut self) -> &mut TypeList {
2968 &mut self.list
2969 }
2970}
2971
2972impl TypeAlloc {
2973 pub fn push_ty<T>(&mut self, ty: T) -> T::Id
2979 where
2980 T: TypeData,
2981 {
2982 self.list.push(ty)
2983 }
2984
2985 pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
2989 let contextually_unique_id = self.next_resource_id;
2990 self.next_resource_id = self.next_resource_id.checked_add(1).unwrap();
2991 AliasableResourceId {
2992 id: ResourceId {
2993 globally_unique_id: self.globally_unique_id,
2994 contextually_unique_id,
2995 },
2996 alias_id: NO_ALIAS,
2997 }
2998 }
2999
3000 pub fn free_variables_any_type_id(
3007 &self,
3008 id: ComponentAnyTypeId,
3009 set: &mut IndexSet<ResourceId, RandomState>,
3010 ) {
3011 match id {
3012 ComponentAnyTypeId::Resource(r) => {
3013 set.insert(r.resource());
3014 }
3015 ComponentAnyTypeId::Defined(id) => {
3016 self.free_variables_component_defined_type_id(id, set)
3017 }
3018 ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
3019 ComponentAnyTypeId::Instance(id) => {
3020 self.free_variables_component_instance_type_id(id, set)
3021 }
3022 ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
3023 }
3024 }
3025
3026 pub fn free_variables_component_defined_type_id(
3027 &self,
3028 id: ComponentDefinedTypeId,
3029 set: &mut IndexSet<ResourceId, RandomState>,
3030 ) {
3031 match &self[id] {
3032 ComponentDefinedType::Primitive(_)
3033 | ComponentDefinedType::Flags(_)
3034 | ComponentDefinedType::Enum(_) => {}
3035 ComponentDefinedType::Record(r) => {
3036 for ty in r.fields.values() {
3037 self.free_variables_valtype(ty, set);
3038 }
3039 }
3040 ComponentDefinedType::Tuple(r) => {
3041 for ty in r.types.iter() {
3042 self.free_variables_valtype(ty, set);
3043 }
3044 }
3045 ComponentDefinedType::Variant(r) => {
3046 for ty in r.cases.values() {
3047 if let Some(ty) = &ty.ty {
3048 self.free_variables_valtype(ty, set);
3049 }
3050 }
3051 }
3052 ComponentDefinedType::List(ty) | ComponentDefinedType::Option(ty) => {
3053 self.free_variables_valtype(ty, set);
3054 }
3055 ComponentDefinedType::Result { ok, err } => {
3056 if let Some(ok) = ok {
3057 self.free_variables_valtype(ok, set);
3058 }
3059 if let Some(err) = err {
3060 self.free_variables_valtype(err, set);
3061 }
3062 }
3063 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
3064 set.insert(id.resource());
3065 }
3066 }
3067 }
3068
3069 pub fn free_variables_component_type_id(
3070 &self,
3071 id: ComponentTypeId,
3072 set: &mut IndexSet<ResourceId, RandomState>,
3073 ) {
3074 let i = &self[id];
3075 for ty in i.imports.values().chain(i.exports.values()) {
3086 self.free_variables_component_entity(ty, set);
3087 }
3088 for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
3089 set.swap_remove(id);
3090 }
3091 }
3092
3093 pub fn free_variables_component_instance_type_id(
3094 &self,
3095 id: ComponentInstanceTypeId,
3096 set: &mut IndexSet<ResourceId, RandomState>,
3097 ) {
3098 let i = &self[id];
3099 for ty in i.exports.values() {
3103 self.free_variables_component_entity(ty, set);
3104 }
3105 for id in i.defined_resources.iter() {
3106 set.swap_remove(id);
3107 }
3108 }
3109
3110 pub fn free_variables_component_func_type_id(
3111 &self,
3112 id: ComponentFuncTypeId,
3113 set: &mut IndexSet<ResourceId, RandomState>,
3114 ) {
3115 let i = &self[id];
3116 for ty in i
3117 .params
3118 .iter()
3119 .map(|(_, ty)| ty)
3120 .chain(i.results.iter().map(|(_, ty)| ty))
3121 {
3122 self.free_variables_valtype(ty, set);
3123 }
3124 }
3125
3126 pub fn free_variables_component_entity(
3128 &self,
3129 ty: &ComponentEntityType,
3130 set: &mut IndexSet<ResourceId, RandomState>,
3131 ) {
3132 match ty {
3133 ComponentEntityType::Module(_) => {}
3134 ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
3135 ComponentEntityType::Instance(id) => {
3136 self.free_variables_component_instance_type_id(*id, set)
3137 }
3138 ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
3139 ComponentEntityType::Type { created, .. } => {
3140 self.free_variables_any_type_id(*created, set);
3141 }
3142 ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
3143 }
3144 }
3145
3146 fn free_variables_valtype(
3148 &self,
3149 ty: &ComponentValType,
3150 set: &mut IndexSet<ResourceId, RandomState>,
3151 ) {
3152 match ty {
3153 ComponentValType::Primitive(_) => {}
3154 ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
3155 }
3156 }
3157
3158 pub(crate) fn type_named_type_id(
3163 &self,
3164 id: ComponentDefinedTypeId,
3165 set: &HashSet<ComponentAnyTypeId>,
3166 ) -> bool {
3167 let ty = &self[id];
3168 match ty {
3169 ComponentDefinedType::Primitive(_) => true,
3171
3172 ComponentDefinedType::Flags(_)
3175 | ComponentDefinedType::Enum(_)
3176 | ComponentDefinedType::Record(_)
3177 | ComponentDefinedType::Variant(_) => set.contains::<ComponentAnyTypeId>(&id.into()),
3178
3179 ComponentDefinedType::Tuple(r) => {
3182 r.types.iter().all(|t| self.type_named_valtype(t, set))
3183 }
3184 ComponentDefinedType::Result { ok, err } => {
3185 ok.as_ref()
3186 .map(|t| self.type_named_valtype(t, set))
3187 .unwrap_or(true)
3188 && err
3189 .as_ref()
3190 .map(|t| self.type_named_valtype(t, set))
3191 .unwrap_or(true)
3192 }
3193 ComponentDefinedType::List(ty) | ComponentDefinedType::Option(ty) => {
3194 self.type_named_valtype(ty, set)
3195 }
3196
3197 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
3200 set.contains::<ComponentAnyTypeId>(&(*id).into())
3201 }
3202 }
3203 }
3204
3205 pub(crate) fn type_named_valtype(
3206 &self,
3207 ty: &ComponentValType,
3208 set: &HashSet<ComponentAnyTypeId>,
3209 ) -> bool {
3210 match ty {
3211 ComponentValType::Primitive(_) => true,
3212 ComponentValType::Type(id) => self.type_named_type_id(*id, set),
3213 }
3214 }
3215}
3216
3217pub trait Remap
3223where
3224 Self: Index<ComponentTypeId, Output = ComponentType>,
3225 Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
3226 Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
3227 Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
3228{
3229 fn push_ty<T>(&mut self, ty: T) -> T::Id
3232 where
3233 T: TypeData;
3234
3235 fn map_map(
3238 tmp: &mut IndexMap<ResourceId, Vec<usize>, RandomState>,
3239 any_changed: &mut bool,
3240 map: &Remapping,
3241 ) {
3242 for (id, path) in mem::take(tmp) {
3243 let id = match map.resources.get(&id) {
3244 Some(id) => {
3245 *any_changed = true;
3246 *id
3247 }
3248 None => id,
3249 };
3250 tmp.insert(id, path);
3251 }
3252 }
3253
3254 fn insert_if_any_changed<T>(
3258 &mut self,
3259 map: &mut Remapping,
3260 any_changed: bool,
3261 id: &mut T::Id,
3262 ty: T,
3263 ) -> bool
3264 where
3265 T: TypeData,
3266 T::Id: Into<ComponentAnyTypeId>,
3267 {
3268 let new = if any_changed { self.push_ty(ty) } else { *id };
3269 map.types.insert((*id).into(), new.into());
3270 let changed = *id != new;
3271 *id = new;
3272 changed
3273 }
3274
3275 fn remap_component_any_type_id(
3279 &mut self,
3280 id: &mut ComponentAnyTypeId,
3281 map: &mut Remapping,
3282 ) -> bool {
3283 match id {
3284 ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
3285 ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
3286 ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
3287 ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
3288 ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
3289 }
3290 }
3291
3292 fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
3295 if let Some(changed) = map.remap_id(id) {
3296 return changed;
3297 }
3298
3299 match map.resources.get(&id.resource()) {
3300 None => false,
3301 Some(new_id) => {
3302 *id.resource_mut() = *new_id;
3303 true
3304 }
3305 }
3306 }
3307
3308 fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
3312 if let Some(changed) = map.remap_id(id) {
3313 return changed;
3314 }
3315
3316 let mut any_changed = false;
3317 let mut ty = self[*id].clone();
3318 for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
3319 any_changed |= self.remap_component_entity(ty, map);
3320 }
3321 for (id, _) in ty
3322 .imported_resources
3323 .iter_mut()
3324 .chain(&mut ty.defined_resources)
3325 {
3326 if let Some(new) = map.resources.get(id) {
3327 *id = *new;
3328 any_changed = true;
3329 }
3330 }
3331 Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
3332 self.insert_if_any_changed(map, any_changed, id, ty)
3333 }
3334
3335 fn remap_component_defined_type_id(
3339 &mut self,
3340 id: &mut ComponentDefinedTypeId,
3341 map: &mut Remapping,
3342 ) -> bool {
3343 if let Some(changed) = map.remap_id(id) {
3344 return changed;
3345 }
3346
3347 let mut any_changed = false;
3348 let mut tmp = self[*id].clone();
3349 match &mut tmp {
3350 ComponentDefinedType::Primitive(_)
3351 | ComponentDefinedType::Flags(_)
3352 | ComponentDefinedType::Enum(_) => {}
3353 ComponentDefinedType::Record(r) => {
3354 for ty in r.fields.values_mut() {
3355 any_changed |= self.remap_valtype(ty, map);
3356 }
3357 }
3358 ComponentDefinedType::Tuple(r) => {
3359 for ty in r.types.iter_mut() {
3360 any_changed |= self.remap_valtype(ty, map);
3361 }
3362 }
3363 ComponentDefinedType::Variant(r) => {
3364 for ty in r.cases.values_mut() {
3365 if let Some(ty) = &mut ty.ty {
3366 any_changed |= self.remap_valtype(ty, map);
3367 }
3368 }
3369 }
3370 ComponentDefinedType::List(ty) | ComponentDefinedType::Option(ty) => {
3371 any_changed |= self.remap_valtype(ty, map);
3372 }
3373 ComponentDefinedType::Result { ok, err } => {
3374 if let Some(ok) = ok {
3375 any_changed |= self.remap_valtype(ok, map);
3376 }
3377 if let Some(err) = err {
3378 any_changed |= self.remap_valtype(err, map);
3379 }
3380 }
3381 ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
3382 any_changed |= self.remap_resource_id(id, map);
3383 }
3384 }
3385 self.insert_if_any_changed(map, any_changed, id, tmp)
3386 }
3387
3388 fn remap_component_instance_type_id(
3392 &mut self,
3393 id: &mut ComponentInstanceTypeId,
3394 map: &mut Remapping,
3395 ) -> bool {
3396 if let Some(changed) = map.remap_id(id) {
3397 return changed;
3398 }
3399
3400 let mut any_changed = false;
3401 let mut tmp = self[*id].clone();
3402 for ty in tmp.exports.values_mut() {
3403 any_changed |= self.remap_component_entity(ty, map);
3404 }
3405 for id in tmp.defined_resources.iter_mut() {
3406 if let Some(new) = map.resources.get(id) {
3407 *id = *new;
3408 any_changed = true;
3409 }
3410 }
3411 Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
3412 self.insert_if_any_changed(map, any_changed, id, tmp)
3413 }
3414
3415 fn remap_component_func_type_id(
3419 &mut self,
3420 id: &mut ComponentFuncTypeId,
3421 map: &mut Remapping,
3422 ) -> bool {
3423 if let Some(changed) = map.remap_id(id) {
3424 return changed;
3425 }
3426
3427 let mut any_changed = false;
3428 let mut tmp = self[*id].clone();
3429 for ty in tmp
3430 .params
3431 .iter_mut()
3432 .map(|(_, ty)| ty)
3433 .chain(tmp.results.iter_mut().map(|(_, ty)| ty))
3434 {
3435 any_changed |= self.remap_valtype(ty, map);
3436 }
3437 self.insert_if_any_changed(map, any_changed, id, tmp)
3438 }
3439
3440 fn remap_component_entity(
3442 &mut self,
3443 ty: &mut ComponentEntityType,
3444 map: &mut Remapping,
3445 ) -> bool {
3446 match ty {
3447 ComponentEntityType::Module(_) => {
3448 false
3450 }
3451 ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
3452 ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
3453 ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
3454 ComponentEntityType::Type {
3455 referenced,
3456 created,
3457 } => {
3458 let mut changed = self.remap_component_any_type_id(referenced, map);
3459 if *referenced == *created {
3460 *created = *referenced;
3461 } else {
3462 changed |= self.remap_component_any_type_id(created, map);
3463 }
3464 changed
3465 }
3466 ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
3467 }
3468 }
3469
3470 fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
3472 match ty {
3473 ComponentValType::Primitive(_) => false,
3474 ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
3475 }
3476 }
3477}
3478
3479#[derive(Debug, Default)]
3482pub struct Remapping {
3483 pub(crate) resources: HashMap<ResourceId, ResourceId>,
3485
3486 types: HashMap<ComponentAnyTypeId, ComponentAnyTypeId>,
3490}
3491
3492impl Remap for TypeAlloc {
3493 fn push_ty<T>(&mut self, ty: T) -> T::Id
3494 where
3495 T: TypeData,
3496 {
3497 <TypeList>::push(self, ty)
3498 }
3499}
3500
3501impl<T> Index<T> for TypeAlloc
3502where
3503 T: TypeIdentifier,
3504{
3505 type Output = T::Data;
3506
3507 #[inline]
3508 fn index(&self, id: T) -> &T::Data {
3509 &self.list[id]
3510 }
3511}
3512
3513impl Remapping {
3514 pub fn add(&mut self, old: ResourceId, new: ResourceId) {
3516 self.resources.insert(old, new);
3517 }
3518
3519 pub fn reset_type_cache(&mut self) {
3521 self.types.clear()
3522 }
3523
3524 fn remap_id<T>(&self, id: &mut T) -> Option<bool>
3525 where
3526 T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
3527 T::Error: crate::std::fmt::Debug,
3528 {
3529 let old: ComponentAnyTypeId = (*id).into();
3530 let new = self.types.get(&old)?;
3531 if *new == old {
3532 Some(false)
3533 } else {
3534 *id = T::try_from(*new).expect("should never remap across different kinds");
3535 Some(true)
3536 }
3537 }
3538}
3539
3540pub struct SubtypeCx<'a> {
3559 pub a: SubtypeArena<'a>,
3561 pub b: SubtypeArena<'a>,
3563}
3564
3565impl<'a> SubtypeCx<'a> {
3566 pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
3568 Self::new(a.list, b.list)
3569 }
3570
3571 pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
3572 SubtypeCx {
3573 a: SubtypeArena::new(a),
3574 b: SubtypeArena::new(b),
3575 }
3576 }
3577
3578 pub fn swap(&mut self) {
3580 mem::swap(&mut self.a, &mut self.b);
3581 }
3582
3583 fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
3589 let a = self.a.list.checkpoint();
3590 let b = self.b.list.checkpoint();
3591 let result = f(self);
3592 self.a.list.reset_to_checkpoint(a);
3593 self.b.list.reset_to_checkpoint(b);
3594 result
3595 }
3596
3597 pub fn component_entity_type(
3601 &mut self,
3602 a: &ComponentEntityType,
3603 b: &ComponentEntityType,
3604 offset: usize,
3605 ) -> Result<()> {
3606 use ComponentEntityType::*;
3607
3608 match (a, b) {
3609 (Module(a), Module(b)) => self.module_type(*a, *b, offset),
3610 (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
3611
3612 (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
3613 (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3614
3615 (Value(a), Value(b)) => self.component_val_type(a, b, offset),
3616 (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
3617
3618 (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
3619 self.component_any_type_id(*a, *b, offset)
3620 }
3621 (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
3622
3623 (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
3624 (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
3625
3626 (Component(a), Component(b)) => self.component_type(*a, *b, offset),
3627 (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
3628 }
3629 }
3630
3631 pub fn component_type(
3635 &mut self,
3636 a: ComponentTypeId,
3637 b: ComponentTypeId,
3638 offset: usize,
3639 ) -> Result<()> {
3640 let b_imports = self.b[b]
3694 .imports
3695 .iter()
3696 .map(|(name, ty)| (name.clone(), ty.clone()))
3697 .collect();
3698 self.swap();
3699 let mut import_mapping =
3700 self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
3701 self.swap();
3702 self.with_checkpoint(|this| {
3703 let mut a_exports = this.a[a]
3704 .exports
3705 .iter()
3706 .map(|(name, ty)| (name.clone(), ty.clone()))
3707 .collect::<IndexMap<_, _, RandomState>>();
3708 for ty in a_exports.values_mut() {
3709 this.a.remap_component_entity(ty, &mut import_mapping);
3710 }
3711 this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
3712 Ok(())
3713 })
3714 }
3715
3716 pub fn component_instance_type(
3720 &mut self,
3721 a_id: ComponentInstanceTypeId,
3722 b_id: ComponentInstanceTypeId,
3723 offset: usize,
3724 ) -> Result<()> {
3725 let a = &self.a[a_id];
3730 let b = &self.b[b_id];
3731
3732 let mut exports = Vec::with_capacity(b.exports.len());
3733 for (k, b) in b.exports.iter() {
3734 match a.exports.get(k) {
3735 Some(a) => exports.push((*a, *b)),
3736 None => bail!(offset, "missing expected export `{k}`"),
3737 }
3738 }
3739 for (i, (a, b)) in exports.iter().enumerate() {
3740 let err = match self.component_entity_type(a, b, offset) {
3741 Ok(()) => continue,
3742 Err(e) => e,
3743 };
3744 let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
3747 return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
3748 }
3749 Ok(())
3750 }
3751
3752 pub fn component_func_type(
3756 &mut self,
3757 a: ComponentFuncTypeId,
3758 b: ComponentFuncTypeId,
3759 offset: usize,
3760 ) -> Result<()> {
3761 let a = &self.a[a];
3762 let b = &self.b[b];
3763
3764 if a.params.len() != b.params.len() {
3795 bail!(
3796 offset,
3797 "expected {} parameters, found {}",
3798 b.params.len(),
3799 a.params.len(),
3800 );
3801 }
3802 if a.results.len() != b.results.len() {
3803 bail!(
3804 offset,
3805 "expected {} results, found {}",
3806 b.results.len(),
3807 a.results.len(),
3808 );
3809 }
3810 for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
3811 if an != bn {
3812 bail!(offset, "expected parameter named `{bn}`, found `{an}`");
3813 }
3814 self.component_val_type(a, b, offset)
3815 .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
3816 }
3817 for ((an, a), (bn, b)) in a.results.iter().zip(b.results.iter()) {
3818 if an != bn {
3819 bail!(offset, "mismatched result names");
3820 }
3821 self.component_val_type(a, b, offset)
3822 .with_context(|| "type mismatch with result type")?;
3823 }
3824 Ok(())
3825 }
3826
3827 pub fn module_type(
3831 &mut self,
3832 a: ComponentCoreModuleTypeId,
3833 b: ComponentCoreModuleTypeId,
3834 offset: usize,
3835 ) -> Result<()> {
3836 self.swap();
3842 let a_imports = &self.b[a].imports;
3843 let b_imports = &self.a[b].imports;
3844 for (k, a) in a_imports {
3845 match b_imports.get(k) {
3846 Some(b) => self
3847 .entity_type(b, a, offset)
3848 .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
3849 None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
3850 }
3851 }
3852 self.swap();
3853 let a = &self.a[a];
3854 let b = &self.b[b];
3855 for (k, b) in b.exports.iter() {
3856 match a.exports.get(k) {
3857 Some(a) => self
3858 .entity_type(a, b, offset)
3859 .with_context(|| format!("type mismatch in export `{k}`"))?,
3860 None => bail!(offset, "missing expected export `{k}`"),
3861 }
3862 }
3863 Ok(())
3864 }
3865
3866 pub fn component_any_type_id(
3870 &mut self,
3871 a: ComponentAnyTypeId,
3872 b: ComponentAnyTypeId,
3873 offset: usize,
3874 ) -> Result<()> {
3875 match (a, b) {
3876 (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
3877 if a.resource() == b.resource() {
3878 Ok(())
3879 } else {
3880 bail!(
3881 offset,
3882 "resource types are not the same ({:?} vs. {:?})",
3883 a.resource(),
3884 b.resource()
3885 )
3886 }
3887 }
3888 (ComponentAnyTypeId::Resource(_), b) => {
3889 bail!(offset, "expected {}, found resource", b.desc())
3890 }
3891 (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
3892 self.component_defined_type(a, b, offset)
3893 }
3894 (ComponentAnyTypeId::Defined(_), b) => {
3895 bail!(offset, "expected {}, found defined type", b.desc())
3896 }
3897
3898 (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
3899 self.component_func_type(a, b, offset)
3900 }
3901 (ComponentAnyTypeId::Func(_), b) => {
3902 bail!(offset, "expected {}, found func type", b.desc())
3903 }
3904
3905 (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
3906 self.component_instance_type(a, b, offset)
3907 }
3908 (ComponentAnyTypeId::Instance(_), b) => {
3909 bail!(offset, "expected {}, found instance type", b.desc())
3910 }
3911
3912 (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
3913 self.component_type(a, b, offset)
3914 }
3915 (ComponentAnyTypeId::Component(_), b) => {
3916 bail!(offset, "expected {}, found component type", b.desc())
3917 }
3918 }
3919 }
3920
3921 pub fn open_instance_type(
3945 &mut self,
3946 a: &IndexMap<String, ComponentEntityType, RandomState>,
3947 b: ComponentTypeId,
3948 kind: ExternKind,
3949 offset: usize,
3950 ) -> Result<Remapping> {
3951 let component_type = &self.b[b];
3981 let entities = match kind {
3982 ExternKind::Import => &component_type.imports,
3983 ExternKind::Export => &component_type.exports,
3984 };
3985 let resources = match kind {
3986 ExternKind::Import => &component_type.imported_resources,
3987 ExternKind::Export => &component_type.defined_resources,
3988 };
3989 let mut mapping = Remapping::default();
3990 'outer: for (resource, path) in resources.iter() {
3991 let (name, ty) = entities.get_index(path[0]).unwrap();
3994 let mut ty = *ty;
3995 let mut arg = a.get(name);
3996
3997 for i in path.iter().skip(1).copied() {
4001 let id = match ty {
4002 ComponentEntityType::Instance(id) => id,
4003 _ => unreachable!(),
4004 };
4005 let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
4006 ty = *next_ty;
4007 arg = match arg {
4008 Some(ComponentEntityType::Instance(id)) => self.a[*id].exports.get(name),
4009 _ => continue 'outer,
4010 };
4011 }
4012
4013 if cfg!(debug_assertions) {
4016 let id = match ty {
4017 ComponentEntityType::Type { created, .. } => match created {
4018 ComponentAnyTypeId::Resource(id) => id.resource(),
4019 _ => unreachable!(),
4020 },
4021 _ => unreachable!(),
4022 };
4023 assert_eq!(id, *resource);
4024 }
4025
4026 if let Some(ComponentEntityType::Type { created, .. }) = arg {
4030 if let ComponentAnyTypeId::Resource(r) = created {
4031 mapping.resources.insert(*resource, r.resource());
4032 }
4033 }
4034 }
4035
4036 let mut to_typecheck = Vec::new();
4048 for (name, expected) in entities.iter() {
4049 match a.get(name) {
4050 Some(arg) => to_typecheck.push((arg.clone(), expected.clone())),
4051 None => bail!(offset, "missing {} named `{name}`", kind.desc()),
4052 }
4053 }
4054 let mut type_map = HashMap::default();
4055 for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
4056 let result = self.with_checkpoint(|this| {
4057 let mut expected = expected;
4058 this.b.remap_component_entity(&mut expected, &mut mapping);
4059 mapping.types.clear();
4060 this.component_entity_type(&actual, &expected, offset)
4061 });
4062 let err = match result {
4063 Ok(()) => {
4064 self.register_type_renamings(actual, expected, &mut type_map);
4070 continue;
4071 }
4072 Err(e) => e,
4073 };
4074
4075 let component_type = &self.b[b];
4078 let entities = match kind {
4079 ExternKind::Import => &component_type.imports,
4080 ExternKind::Export => &component_type.exports,
4081 };
4082 let (name, _) = entities.get_index(i).unwrap();
4083 return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
4084 }
4085 mapping.types = type_map;
4086 Ok(mapping)
4087 }
4088
4089 pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
4090 macro_rules! limits_match {
4091 ($a:expr, $b:expr) => {{
4092 let a = $a;
4093 let b = $b;
4094 a.initial >= b.initial
4095 && match b.maximum {
4096 Some(b_max) => match a.maximum {
4097 Some(a_max) => a_max <= b_max,
4098 None => false,
4099 },
4100 None => true,
4101 }
4102 }};
4103 }
4104
4105 match (a, b) {
4106 (EntityType::Func(a), EntityType::Func(b)) => {
4107 self.core_func_type(self.a[*a].unwrap_func(), self.b[*b].unwrap_func(), offset)
4108 }
4109 (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
4110 (EntityType::Table(a), EntityType::Table(b)) => {
4111 if a.element_type != b.element_type {
4112 bail!(
4113 offset,
4114 "expected table element type {}, found {}",
4115 b.element_type,
4116 a.element_type,
4117 )
4118 }
4119 if limits_match!(a, b) {
4120 Ok(())
4121 } else {
4122 bail!(offset, "mismatch in table limits")
4123 }
4124 }
4125 (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
4126 (EntityType::Memory(a), EntityType::Memory(b)) => {
4127 if a.shared != b.shared {
4128 bail!(offset, "mismatch in the shared flag for memories")
4129 }
4130 if a.memory64 != b.memory64 {
4131 bail!(offset, "mismatch in index type used for memories")
4132 }
4133 if limits_match!(a, b) {
4134 Ok(())
4135 } else {
4136 bail!(offset, "mismatch in memory limits")
4137 }
4138 }
4139 (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
4140 (EntityType::Global(a), EntityType::Global(b)) => {
4141 if a.mutable != b.mutable {
4142 bail!(offset, "global types differ in mutability")
4143 }
4144 if a.content_type == b.content_type {
4145 Ok(())
4146 } else {
4147 bail!(
4148 offset,
4149 "expected global type {}, found {}",
4150 b.content_type,
4151 a.content_type,
4152 )
4153 }
4154 }
4155 (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
4156 (EntityType::Tag(a), EntityType::Tag(b)) => {
4157 self.core_func_type(self.a[*a].unwrap_func(), self.b[*b].unwrap_func(), offset)
4158 }
4159 (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
4160 }
4161 }
4162
4163 fn core_func_type(&self, a: &FuncType, b: &FuncType, offset: usize) -> Result<()> {
4164 if a == b {
4165 Ok(())
4166 } else {
4167 bail!(
4168 offset,
4169 "expected: {}\n\
4170 found: {}",
4171 b.desc(),
4172 a.desc(),
4173 )
4174 }
4175 }
4176
4177 pub(crate) fn component_val_type(
4178 &self,
4179 a: &ComponentValType,
4180 b: &ComponentValType,
4181 offset: usize,
4182 ) -> Result<()> {
4183 match (a, b) {
4184 (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
4185 self.primitive_val_type(*a, *b, offset)
4186 }
4187 (ComponentValType::Type(a), ComponentValType::Type(b)) => {
4188 self.component_defined_type(*a, *b, offset)
4189 }
4190 (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
4191 ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
4192 b => bail!(offset, "expected {}, found {a}", b.desc()),
4193 },
4194 (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
4195 ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
4196 a => bail!(offset, "expected {b}, found {}", a.desc()),
4197 },
4198 }
4199 }
4200
4201 fn component_defined_type(
4202 &self,
4203 a: ComponentDefinedTypeId,
4204 b: ComponentDefinedTypeId,
4205 offset: usize,
4206 ) -> Result<()> {
4207 use ComponentDefinedType::*;
4208
4209 match (&self.a[a], &self.b[b]) {
4213 (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
4214 (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
4215 (Record(a), Record(b)) => {
4216 if a.fields.len() != b.fields.len() {
4217 bail!(
4218 offset,
4219 "expected {} fields, found {}",
4220 b.fields.len(),
4221 a.fields.len(),
4222 );
4223 }
4224
4225 for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
4226 if aname != bname {
4227 bail!(offset, "expected field name `{bname}`, found `{aname}`");
4228 }
4229 self.component_val_type(a, b, offset)
4230 .with_context(|| format!("type mismatch in record field `{aname}`"))?;
4231 }
4232 Ok(())
4233 }
4234 (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
4235 (Variant(a), Variant(b)) => {
4236 if a.cases.len() != b.cases.len() {
4237 bail!(
4238 offset,
4239 "expected {} cases, found {}",
4240 b.cases.len(),
4241 a.cases.len(),
4242 );
4243 }
4244 for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
4245 if aname != bname {
4246 bail!(offset, "expected case named `{bname}`, found `{aname}`");
4247 }
4248 match (&a.ty, &b.ty) {
4249 (Some(a), Some(b)) => self
4250 .component_val_type(a, b, offset)
4251 .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
4252 (None, None) => {}
4253 (None, Some(_)) => {
4254 bail!(offset, "expected case `{aname}` to have a type, found none")
4255 }
4256 (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
4257 }
4258 }
4259 Ok(())
4260 }
4261 (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
4262 (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
4263 (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
4264 (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
4265 (Tuple(a), Tuple(b)) => {
4266 if a.types.len() != b.types.len() {
4267 bail!(
4268 offset,
4269 "expected {} types, found {}",
4270 b.types.len(),
4271 a.types.len(),
4272 );
4273 }
4274 for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
4275 self.component_val_type(a, b, offset)
4276 .with_context(|| format!("type mismatch in tuple field {i}"))?;
4277 }
4278 Ok(())
4279 }
4280 (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
4281 (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
4282 let desc = match at {
4283 Flags(_) => "flags",
4284 _ => "enum",
4285 };
4286 if a.len() == b.len() && a.iter().eq(b.iter()) {
4287 Ok(())
4288 } else {
4289 bail!(offset, "mismatch in {desc} elements")
4290 }
4291 }
4292 (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
4293 (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
4294 (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
4295 match (ao, bo) {
4296 (None, None) => {}
4297 (Some(a), Some(b)) => self
4298 .component_val_type(a, b, offset)
4299 .with_context(|| "type mismatch in ok variant")?,
4300 (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
4301 (Some(_), None) => bail!(offset, "expected ok type to not be present"),
4302 }
4303 match (ae, be) {
4304 (None, None) => {}
4305 (Some(a), Some(b)) => self
4306 .component_val_type(a, b, offset)
4307 .with_context(|| "type mismatch in err variant")?,
4308 (None, Some(_)) => bail!(offset, "expected err type, but found none"),
4309 (Some(_), None) => bail!(offset, "expected err type to not be present"),
4310 }
4311 Ok(())
4312 }
4313 (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
4314 (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
4315 if a.resource() == b.resource() {
4316 Ok(())
4317 } else {
4318 bail!(offset, "resource types are not the same")
4319 }
4320 }
4321 (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
4322 (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
4323 }
4324 }
4325
4326 fn primitive_val_type(
4327 &self,
4328 a: PrimitiveValType,
4329 b: PrimitiveValType,
4330 offset: usize,
4331 ) -> Result<()> {
4332 if a == b {
4339 Ok(())
4340 } else {
4341 bail!(offset, "expected primitive `{b}` found primitive `{a}`")
4342 }
4343 }
4344
4345 fn register_type_renamings(
4346 &self,
4347 actual: ComponentEntityType,
4348 expected: ComponentEntityType,
4349 type_map: &mut HashMap<ComponentAnyTypeId, ComponentAnyTypeId>,
4350 ) {
4351 match (expected, actual) {
4352 (
4353 ComponentEntityType::Type {
4354 created: expected, ..
4355 },
4356 ComponentEntityType::Type {
4357 created: actual, ..
4358 },
4359 ) => {
4360 let prev = type_map.insert(expected, actual);
4361 assert!(prev.is_none());
4362 }
4363 (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
4364 let actual = &self.a[actual];
4365 for (name, expected) in self.b[expected].exports.iter() {
4366 let actual = actual.exports[name];
4367 self.register_type_renamings(actual, *expected, type_map);
4368 }
4369 }
4370 _ => {}
4371 }
4372 }
4373}
4374
4375pub struct SubtypeArena<'a> {
4385 types: &'a TypeList,
4386 list: TypeList,
4387}
4388
4389impl<'a> SubtypeArena<'a> {
4390 fn new(types: &'a TypeList) -> SubtypeArena<'a> {
4391 SubtypeArena {
4392 types,
4393 list: TypeList::default(),
4394 }
4395 }
4396}
4397
4398impl<T> Index<T> for SubtypeArena<'_>
4399where
4400 T: TypeIdentifier,
4401{
4402 type Output = T::Data;
4403
4404 fn index(&self, id: T) -> &T::Data {
4405 let index = id.index();
4406 if index < T::list(self.types).len() {
4407 &self.types[id]
4408 } else {
4409 let temp_index = index - T::list(self.types).len();
4410 let temp_index = u32::try_from(temp_index).unwrap();
4411 let temp_id = T::from_index(temp_index);
4412 &self.list[temp_id]
4413 }
4414 }
4415}
4416
4417impl Remap for SubtypeArena<'_> {
4418 fn push_ty<T>(&mut self, ty: T) -> T::Id
4419 where
4420 T: TypeData,
4421 {
4422 let index = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
4423 let index = u32::try_from(index).unwrap();
4424 self.list.push(ty);
4425 T::Id::from_index(index)
4426 }
4427}
4428
4429pub(crate) trait Context {
4432 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4433 where
4434 S: Into<String>;
4435}
4436
4437impl<T> Context for Result<T> {
4438 fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4439 where
4440 S: Into<String>,
4441 {
4442 match self {
4443 Ok(val) => Ok(val),
4444 Err(e) => Err(e.with_context(context)),
4445 }
4446 }
4447}
4448
4449impl Context for BinaryReaderError {
4450 fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
4451 where
4452 S: Into<String>,
4453 {
4454 self.add_context(context().into());
4455 self
4456 }
4457}