tinywasm_wasmparser/validator/
types.rs

1//! Types relating to type information provided by validation.
2
3use 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
27/// The maximum number of parameters in the canonical ABI that can be passed by value.
28///
29/// Functions that exceed this limit will instead pass parameters indirectly from
30/// linear memory via a single pointer parameter.
31const MAX_FLAT_FUNC_PARAMS: usize = 16;
32/// The maximum number of results in the canonical ABI that can be returned by a function.
33///
34/// Functions that exceed this limit have their results written to linear memory via an
35/// additional pointer parameter (imports) or return a single pointer value (exports).
36const MAX_FLAT_FUNC_RESULTS: usize = 1;
37
38/// The maximum lowered types, including a possible type for a return pointer parameter.
39const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
40
41/// A simple alloc-free list of types used for calculating lowered function signatures.
42pub(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
97/// Represents information about a component function type lowering.
98pub(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
144/// A trait shared by all type identifiers.
145///
146/// Any id that can be used to get a type from a `Types`.
147//
148// Or, internally, from a `TypeList`.
149pub trait TypeIdentifier: crate::std::fmt::Debug + Copy + Eq + Sized + 'static {
150    /// The data pointed to by this type of id.
151    type Data: TypeData<Id = Self>;
152
153    /// Create a type id from an index.
154    #[doc(hidden)]
155    fn from_index(index: u32) -> Self;
156
157    /// Get a shared reference to the list where this id's type data is stored
158    /// within.
159    #[doc(hidden)]
160    fn list(types: &TypeList) -> &SnapshotList<Self::Data>;
161
162    /// Get an exclusive reference to the list where this id's type data is
163    /// stored within.
164    #[doc(hidden)]
165    fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data>;
166
167    /// The raw index of this id.
168    #[doc(hidden)]
169    fn index(&self) -> usize;
170}
171
172/// A trait shared by all types within a `Types`.
173///
174/// This is the data that can be retreived by indexing with the associated
175/// [`TypeIdentifier`].
176pub trait TypeData: crate::std::fmt::Debug {
177    /// The identifier for this type data.
178    type Id: TypeIdentifier<Data = Self>;
179
180    /// Get the info for this type.
181    #[doc(hidden)]
182    fn type_info(&self, types: &TypeList) -> TypeInfo;
183}
184
185/// A type that can be aliased in the component model.
186pub 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
194/// A fresh alias id that means the entity is not an alias of anything.
195///
196/// Note that the `TypeList::alias_counter` starts at zero, so we can't use that
197/// as this sentinel. The implementation limits are such that we can't ever
198/// generate `u32::MAX` aliases, so we don't need to worryabout running into
199/// this value in practice either.
200const 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)] // Use fixed field layout to ensure minimal size.
209        pub struct $name {
210            /// The index into the associated list of types.
211            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        // The size of type IDs was seen to have a large-ish impact in #844, so
243        // this assert ensures that it stays relatively small.
244        const _: () = {
245            assert!(crate::std::mem::size_of::<$name>() <= 4);
246        };
247    };
248}
249
250/// A core WebAssembly type, in the core WebAssembly types index space.
251pub enum CoreType {
252    /// A sub type.
253    Sub(SubType),
254
255    /// A module type.
256    ///
257    /// Does not actually appear in core Wasm at the moment. Only used for the
258    /// core types index space within components.
259    Module(ModuleType),
260}
261
262/// Represents a unique identifier for a core type type known to a
263/// [`crate::Validator`]
264#[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        // TODO(#1036): calculate actual size for func, array, struct.
299        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    /// Get the underlying `SubType` or panic.
310    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    /// Get the underlying `FuncType` within this `SubType` or panic.
318    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    /// Get the underlying `ModuleType` or panic.
328    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    /// An identifier pointing to any kind of type, component or core.
432    #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
433    pub enum AnyTypeId {
434        #[unwrap = unwrap_component_core_type]
435        /// A core type.
436        Core(ComponentCoreTypeId),
437
438        #[unwrap = unwrap_component_any_type]
439        /// A component type.
440        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    /// Peel off one layer of aliasing from this type and return the aliased
456    /// inner type, or `None` if this type is not aliasing anything.
457    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    /// An identifier for a core type or a core module's type.
467    #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
468    pub enum ComponentCoreTypeId {
469        #[unwrap = unwrap_sub]
470        /// A core type.
471        Sub(CoreTypeId),
472
473        #[unwrap = unwrap_module]
474        /// A core module's type.
475        Module(ComponentCoreModuleTypeId),
476    }
477}
478
479impl ComponentCoreTypeId {
480    /// Peel off one layer of aliasing from this type and return the aliased
481    /// inner type, or `None` if this type is not aliasing anything.
482    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/// An aliasable resource identifier.
491#[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    /// Create a new instance with the specified resource ID and `self`'s alias
509    /// ID.
510    pub fn with_resource_id(&self, id: ResourceId) -> Self {
511        Self {
512            id,
513            alias_id: self.alias_id,
514        }
515    }
516
517    /// Get the underlying resource.
518    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    /// An identifier for any kind of component type.
529    #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
530    pub enum ComponentAnyTypeId {
531        #[unwrap = unwrap_resource]
532        /// The type is a resource with the specified id.
533        Resource(AliasableResourceId),
534
535        #[unwrap = unwrap_defined]
536        /// The type is a defined type with the specified id.
537        Defined(ComponentDefinedTypeId),
538
539        #[unwrap = unwrap_func]
540        /// The type is a function type with the specified id.
541        Func(ComponentFuncTypeId),
542
543        #[unwrap = unwrap_instance]
544        /// The type is an instance type with the specified id.
545        Instance(ComponentInstanceTypeId),
546
547        #[unwrap = unwrap_component]
548        /// The type is a component type with the specified id.
549        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/// Represents a unique identifier for a component type type known to a
651/// [`crate::Validator`].
652#[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/// Metadata about a type and its transitive structure.
697///
698/// Currently contains two properties:
699///
700/// * The "size" of a type - a proxy to the recursive size of a type if
701///   everything in the type were unique (e.g. no shared references). Not an
702///   approximation of runtime size, but instead of type-complexity size if
703///   someone were to visit each element of the type individually. For example
704///   `u32` has size 1 and `(list u32)` has size 2 (roughly). Used to prevent
705///   massive trees of types.
706///
707/// * Whether or not a type contains a "borrow" transitively inside of it. For
708///   example `(borrow $t)` and `(list (borrow $t))` both contain borrows, but
709///   `(list u32)` does not. Used to validate that component function results do
710///   not contain borrows.
711///
712/// Currently this is represented as a compact 32-bit integer to ensure that
713/// `TypeId`, which this is stored in, remains relatively small. The maximum
714/// type size allowed in wasmparser is 1M at this time which is 20 bits of
715/// information, and then one more bit is used for whether or not a borrow is
716/// used. Currently this uses the low 24 bits for the type size and the MSB for
717/// the borrow bit.
718#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
719// Only public because it shows up in a public trait's `doc(hidden)` method.
720#[doc(hidden)]
721pub struct TypeInfo(u32);
722
723impl TypeInfo {
724    /// Creates a new blank set of type information.
725    ///
726    /// Defaults to size 1 to ensure that this consumes space in the final type
727    /// structure.
728    pub(crate) fn new() -> TypeInfo {
729        TypeInfo::_new(1, false)
730    }
731
732    /// Creates a new blank set of information about a leaf "borrow" type which
733    /// has size 1.
734    pub(crate) fn borrow() -> TypeInfo {
735        TypeInfo::_new(1, true)
736    }
737
738    /// Creates type information corresponding to a core type of the `size`
739    /// specified, meaning no borrows are contained within.
740    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    /// Combines another set of type information into this one, for example if
750    /// this is a record which has `other` as a field.
751    ///
752    /// Updates the size of `self` and whether or not this type contains a
753    /// borrow based on whether `other` contains a borrow.
754    ///
755    /// Returns an error if the type size would exceed this crate's static limit
756    /// of a type size.
757    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/// A component value type.
775#[derive(Debug, Clone, Copy)]
776pub enum ComponentValType {
777    /// The value type is one of the primitive types.
778    Primitive(PrimitiveValType),
779    /// The type is represented with the given type identifier.
780    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/// The entity type for imports and exports of a module.
818#[derive(Debug, Clone, Copy)]
819pub enum EntityType {
820    /// The entity is a function.
821    Func(CoreTypeId),
822    /// The entity is a table.
823    Table(TableType),
824    /// The entity is a memory.
825    Memory(MemoryType),
826    /// The entity is a global.
827    Global(GlobalType),
828    /// The entity is a tag.
829    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/// Represents a core module type.
898#[derive(Debug, Clone)]
899pub struct ModuleType {
900    /// Metadata about this module type
901    pub(crate) info: TypeInfo,
902    /// The imports of the module type.
903    pub imports: IndexMap<(String, String), EntityType, RandomState>,
904    /// The exports of the module type.
905    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    /// Looks up an import by its module and name.
918    ///
919    /// Returns `None` if the import was not found.
920    pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
921        self.imports.get(&(module, name) as &dyn ModuleImportKey)
922    }
923}
924
925/// Represents the kind of module instance type.
926#[derive(Debug, Clone)]
927pub enum CoreInstanceTypeKind {
928    /// The instance type is the result of instantiating a module type.
929    Instantiated(ComponentCoreModuleTypeId),
930
931    /// The instance type is the result of instantiating from exported items.
932    Exports(IndexMap<String, EntityType, RandomState>),
933}
934
935/// Represents a module instance type.
936#[derive(Debug, Clone)]
937pub struct InstanceType {
938    /// Metadata about this instance type
939    pub(crate) info: TypeInfo,
940    /// The kind of module instance type.
941    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    /// Gets the exports of the instance type.
954    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/// The entity type for imports and exports of a component.
973#[derive(Debug, Clone, Copy)]
974pub enum ComponentEntityType {
975    /// The entity is a core module.
976    Module(ComponentCoreModuleTypeId),
977    /// The entity is a function.
978    Func(ComponentFuncTypeId),
979    /// The entity is a value.
980    Value(ComponentValType),
981    /// The entity is a type.
982    Type {
983        /// This is the identifier of the type that was referenced when this
984        /// entity was created.
985        referenced: ComponentAnyTypeId,
986        /// This is the identifier of the type that was created when this type
987        /// was imported or exported from the component.
988        ///
989        /// Note that the underlying type information for the `referenced`
990        /// field and for this `created` field is the same, but these two types
991        /// will hash to different values.
992        created: ComponentAnyTypeId,
993    },
994    /// The entity is a component instance.
995    Instance(ComponentInstanceTypeId),
996    /// The entity is a component.
997    Component(ComponentTypeId),
998}
999
1000impl ComponentEntityType {
1001    /// Determines if component entity type `a` is a subtype of `b`.
1002    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/// Represents a type of a component.
1032#[derive(Debug, Clone)]
1033pub struct ComponentType {
1034    /// Metadata about this component type
1035    pub(crate) info: TypeInfo,
1036
1037    /// The imports of the component type.
1038    ///
1039    /// Each import has its own kebab-name and an optional URL listed. Note that
1040    /// the set of import names is disjoint with the set of export names.
1041    pub imports: IndexMap<String, ComponentEntityType, RandomState>,
1042
1043    /// The exports of the component type.
1044    ///
1045    /// Each export has its own kebab-name and an optional URL listed. Note that
1046    /// the set of export names is disjoint with the set of import names.
1047    pub exports: IndexMap<String, ComponentEntityType, RandomState>,
1048
1049    /// Universally quantified resources required to be provided when
1050    /// instantiating this component type.
1051    ///
1052    /// Each resource in this map is explicitly imported somewhere in the
1053    /// `imports` map. The "path" to where it's imported is specified by the
1054    /// `Vec<usize>` payload here. For more information about the indexes see
1055    /// the documentation on `ComponentState::imported_resources`.
1056    ///
1057    /// This should technically be inferrable from the structure of `imports`,
1058    /// but it's stored as an auxiliary set for subtype checking and
1059    /// instantiation.
1060    ///
1061    /// Note that this is not a set of all resources referred to by the
1062    /// `imports`. Instead it's only those created, relative to the internals of
1063    /// this component, by the imports.
1064    pub imported_resources: Vec<(ResourceId, Vec<usize>)>,
1065
1066    /// The dual of the `imported_resources`, or the set of defined
1067    /// resources -- those created through the instantiation process which are
1068    /// unique to this component.
1069    ///
1070    /// This set is similar to the `imported_resources` set but it's those
1071    /// contained within the `exports`. Instantiating this component will
1072    /// create fresh new versions of all of these resources. The path here is
1073    /// within the `exports` array.
1074    pub defined_resources: Vec<(ResourceId, Vec<usize>)>,
1075
1076    /// The set of all resources which are explicitly exported by this
1077    /// component, and where they're exported.
1078    ///
1079    /// This mapping is stored separately from `defined_resources` to ensure
1080    /// that it contains all exported resources, not just those which are
1081    /// defined. That means that this can cover reexports of imported
1082    /// resources, exports of local resources, or exports of closed-over
1083    /// resources for example.
1084    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/// Represents a type of a component instance.
1096#[derive(Debug, Clone)]
1097pub struct ComponentInstanceType {
1098    /// Metadata about this instance type
1099    pub(crate) info: TypeInfo,
1100
1101    /// The list of exports, keyed by name, that this instance has.
1102    ///
1103    /// An optional URL and type of each export is provided as well.
1104    pub exports: IndexMap<String, ComponentEntityType, RandomState>,
1105
1106    /// The list of "defined resources" or those which are closed over in
1107    /// this instance type.
1108    ///
1109    /// This list is populated, for example, when the type of an instance is
1110    /// declared and it contains its own resource type exports defined
1111    /// internally. For example:
1112    ///
1113    /// ```wasm
1114    /// (component
1115    ///     (type (instance
1116    ///         (export "x" (type sub resource)) ;; one `defined_resources` entry
1117    ///     ))
1118    /// )
1119    /// ```
1120    ///
1121    /// This list is also a bit of an oddity, however, because the type of a
1122    /// concrete instance will always have this as empty. For example:
1123    ///
1124    /// ```wasm
1125    /// (component
1126    ///     (type $t (instance (export "x" (type sub resource))))
1127    ///
1128    ///     ;; the type of this instance has no defined resources
1129    ///     (import "i" (instance (type $t)))
1130    /// )
1131    /// ```
1132    ///
1133    /// This list ends up only being populated for instance types declared in a
1134    /// module which aren't yet "attached" to anything. Once something is
1135    /// instantiated, imported, exported, or otherwise refers to a concrete
1136    /// instance then this list is always empty. For concrete instances
1137    /// defined resources are tracked in the component state or component type.
1138    pub defined_resources: Vec<ResourceId>,
1139
1140    /// The list of all resources that are explicitly exported from this
1141    /// instance type along with the path they're exported at.
1142    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/// Represents a type of a component function.
1154#[derive(Debug, Clone)]
1155pub struct ComponentFuncType {
1156    /// Metadata about this function type.
1157    pub(crate) info: TypeInfo,
1158    /// The function parameters.
1159    pub params: Box<[(KebabString, ComponentValType)]>,
1160    /// The function's results.
1161    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    /// Lowers the component function type to core parameter and result types for the
1174    /// canonical ABI.
1175    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            // Check to see if `ty` has a pointer somewhere in it, needed for
1180            // any type that transitively contains either a string or a list.
1181            // In this situation lowered functions must specify `memory`, and
1182            // lifted functions must specify `realloc` as well. Lifted functions
1183            // gain their memory requirement through the final clause of this
1184            // function.
1185            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                // Too many parameters to pass directly
1197                // Function will have a single pointer parameter to pass the arguments
1198                // via linear memory
1199                info.params.clear();
1200                assert!(info.params.push(ValType::I32));
1201                info.requires_memory = true;
1202
1203                // We need realloc as well when lifting a function
1204                if !is_lower {
1205                    info.requires_realloc = true;
1206                }
1207                break;
1208            }
1209        }
1210
1211        for (_, ty) in self.results.iter() {
1212            // Results of lowered functions that contains pointers must be
1213            // allocated by the callee meaning that realloc is required.
1214            // Results of lifted function are allocated by the guest which
1215            // means that no realloc option is necessary.
1216            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                // Too many results to return directly, either a retptr parameter will be used (import)
1222                // or a single pointer will be returned (export)
1223                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        // Memory is always required when realloc is required
1236        info.requires_memory |= info.requires_realloc;
1237
1238        info
1239    }
1240}
1241
1242/// Represents a variant case.
1243#[derive(Debug, Clone)]
1244pub struct VariantCase {
1245    /// The variant case type.
1246    pub ty: Option<ComponentValType>,
1247    /// The name of the variant case refined by this one.
1248    pub refines: Option<KebabString>,
1249}
1250
1251/// Represents a record type.
1252#[derive(Debug, Clone)]
1253pub struct RecordType {
1254    /// Metadata about this record type.
1255    pub(crate) info: TypeInfo,
1256    /// The map of record fields.
1257    pub fields: IndexMap<KebabString, ComponentValType, RandomState>,
1258}
1259
1260/// Represents a variant type.
1261#[derive(Debug, Clone)]
1262pub struct VariantType {
1263    /// Metadata about this variant type.
1264    pub(crate) info: TypeInfo,
1265    /// The map of variant cases.
1266    pub cases: IndexMap<KebabString, VariantCase, RandomState>,
1267}
1268
1269/// Represents a tuple type.
1270#[derive(Debug, Clone)]
1271pub struct TupleType {
1272    /// Metadata about this tuple type.
1273    pub(crate) info: TypeInfo,
1274    /// The types of the tuple.
1275    pub types: Box<[ComponentValType]>,
1276}
1277
1278/// Represents a component defined type.
1279#[derive(Debug, Clone)]
1280pub enum ComponentDefinedType {
1281    /// The type is a primitive value type.
1282    Primitive(PrimitiveValType),
1283    /// The type is a record.
1284    Record(RecordType),
1285    /// The type is a variant.
1286    Variant(VariantType),
1287    /// The type is a list.
1288    List(ComponentValType),
1289    /// The type is a tuple.
1290    Tuple(TupleType),
1291    /// The type is a set of flags.
1292    Flags(IndexSet<KebabString, RandomState>),
1293    /// The type is an enumeration.
1294    Enum(IndexSet<KebabString, RandomState>),
1295    /// The type is an `option`.
1296    Option(ComponentValType),
1297    /// The type is a `result`.
1298    Result {
1299        /// The `ok` type.
1300        ok: Option<ComponentValType>,
1301        /// The `error` type.
1302        err: Option<ComponentValType>,
1303    },
1304    /// The type is an owned handle to the specified resource.
1305    Own(AliasableResourceId),
1306    /// The type is a borrowed handle to the specified resource.
1307    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        // Push the discriminant
1388        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/// An opaque identifier intended to be used to distinguish whether two
1445/// resource types are equivalent or not.
1446#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1447#[repr(packed(4))] // try to not waste 4 bytes in padding
1448pub struct ResourceId {
1449    // This is a globally unique identifier which is assigned once per
1450    // `TypeAlloc`. This ensures that resource identifiers from different
1451    // instances of `Types`, for example, are considered unique.
1452    //
1453    // Technically 64-bits should be enough for all resource ids ever, but
1454    // they're allocated so often it's predicted that an atomic increment
1455    // per resource id is probably too expensive. To amortize that cost each
1456    // top-level wasm component gets a single globally unique identifier, and
1457    // then within a component contextually unique identifiers are handed out.
1458    globally_unique_id: usize,
1459
1460    // A contextually unique id within the globally unique id above. This is
1461    // allocated within a `TypeAlloc` with its own counter, and allocations of
1462    // this are cheap as nothing atomic is required.
1463    //
1464    // The 32-bit storage here should ideally be enough for any component
1465    // containing resources. If memory usage becomes an issue (this struct is
1466    // 12 bytes instead of 8 or 4) then this could get folded into the globally
1467    // unique id with everything using an atomic increment perhaps.
1468    contextually_unique_id: u32,
1469}
1470
1471#[allow(clippy::large_enum_variant)]
1472enum TypesKind {
1473    Module(Arc<Module>),
1474    Component(ComponentState),
1475}
1476
1477/// Represents the types known to a [`crate::Validator`] once validation has completed.
1478///
1479/// The type information is returned via the [`crate::Validator::end`] method.
1480pub 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/// Represents the types known to a [`crate::Validator`] during validation.
1492///
1493/// Retrieved via the [`crate::Validator::types`] method.
1494#[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    /// Gets a type based on its type id.
1516    ///
1517    /// Returns `None` if the type id is unknown.
1518    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    /// Gets a core WebAssembly type id from a type index.
1526    ///
1527    /// Note that this is in contrast to [`TypesRef::component_type_at`] which
1528    /// gets a component type from its index.
1529    ///
1530    /// # Panics
1531    ///
1532    /// This will panic if the `index` provided is out of bounds.
1533    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    /// Gets a type id from a type index.
1541    ///
1542    /// # Panics
1543    ///
1544    /// Panics if `index` is not a valid type index or if this type information
1545    /// represents a core module.
1546    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    /// Gets a component type id from a type index.
1554    ///
1555    /// # Panics
1556    ///
1557    /// Panics if `index` is not a valid component type index or if this type
1558    /// information represents a core module.
1559    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    /// Gets a type id from a type index.
1567    ///
1568    /// # Panics
1569    ///
1570    /// Panics if `index` is not a valid function index or if this type
1571    /// information represents a core module.
1572    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    /// Returns the number of core types defined so far.
1580    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    /// Returns the number of component types defined so far.
1588    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    /// Gets the type of a table at the given table index.
1596    ///
1597    /// # Panics
1598    ///
1599    /// This will panic if the `index` provided is out of bounds.
1600    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    /// Returns the number of tables defined so far.
1609    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    /// Gets the type of a memory at the given memory index.
1617    ///
1618    /// # Panics
1619    ///
1620    /// This will panic if the `index` provided is out of bounds.
1621    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    /// Returns the number of memories defined so far.
1631    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    /// Gets the type of a global at the given global index.
1639    ///
1640    /// # Panics
1641    ///
1642    /// This will panic if the `index` provided is out of bounds.
1643    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    /// Returns the number of globals defined so far.
1653    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    /// Gets the type of a tag at the given tag index.
1661    ///
1662    /// # Panics
1663    ///
1664    /// This will panic if the `index` provided is out of bounds.
1665    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    /// Returns the number of tags defined so far.
1674    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    /// Gets the type of a core function at the given function index.
1682    ///
1683    /// # Panics
1684    ///
1685    /// This will panic if the `index` provided is out of bounds.
1686    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    /// Gets the count of core functions defined so far.
1694    ///
1695    /// Note that this includes imported functions, defined functions, and for
1696    /// components lowered/aliased functions.
1697    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    /// Gets the type of an element segment at the given element segment index.
1705    ///
1706    /// # Panics
1707    ///
1708    /// This will panic if the `index` provided is out of bounds.
1709    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    /// Returns the number of elements defined so far.
1719    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    /// Gets the type of a component function at the given function index.
1727    ///
1728    /// # Panics
1729    ///
1730    /// This will panic if the `index` provided is out of bounds or if this type
1731    /// information represents a core module.
1732    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    /// Returns the number of component functions defined so far.
1740    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    /// Gets the type of a module at the given module index.
1748    ///
1749    /// # Panics
1750    ///
1751    /// This will panic if the `index` provided is out of bounds or if this type
1752    /// information represents a core module.
1753    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    /// Returns the number of core wasm modules defined so far.
1761    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    /// Gets the type of a module instance at the given module instance index.
1769    ///
1770    /// # Panics
1771    ///
1772    /// This will panic if the `index` provided is out of bounds or if this type
1773    /// information represents a core module.
1774    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    /// Returns the number of core wasm instances defined so far.
1782    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    /// Gets the type of a component at the given component index.
1790    ///
1791    /// # Panics
1792    ///
1793    /// This will panic if the `index` provided is out of bounds or if this type
1794    /// information represents a core module.
1795    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    /// Returns the number of components defined so far.
1803    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    /// Gets the type of an component instance at the given component instance index.
1811    ///
1812    /// # Panics
1813    ///
1814    /// This will panic if the `index` provided is out of bounds or if this type
1815    /// information represents a core module.
1816    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    /// Returns the number of component instances defined so far.
1824    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    /// Gets the type of a value at the given value index.
1832    ///
1833    /// # Panics
1834    ///
1835    /// This will panic if the `index` provided is out of bounds or if this type
1836    /// information represents a core module.
1837    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    /// Gets the entity type for the given import.
1845    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    /// Gets the entity type from the given export.
1859    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    /// Gets the component entity type for the given component import.
1883    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    /// Gets the component entity type for the given component export.
1891    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    /// Attempts to lookup the type id that `ty` is an alias of.
1899    ///
1900    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
1901    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    /// Gets a reference to this validation type information.
1936    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    /// Gets a type based on its type id.
1947    ///
1948    /// Returns `None` if the type id is unknown.
1949    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    /// Gets a core WebAssembly type at the given type index.
1957    ///
1958    /// Note that this is in contrast to [`TypesRef::component_type_at`] which
1959    /// gets a component type from its index.
1960    ///
1961    /// # Panics
1962    ///
1963    /// Panics if `index` is not a valid function index.
1964    pub fn core_type_at(&self, index: u32) -> ComponentCoreTypeId {
1965        self.as_ref().core_type_at(index)
1966    }
1967
1968    /// Gets a component WebAssembly type at the given type index.
1969    ///
1970    /// Note that this is in contrast to [`TypesRef::core_type_at`] which gets a
1971    /// core type from its index.
1972    ///
1973    /// # Panics
1974    ///
1975    /// Panics if `index` is not a valid type index.
1976    pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1977        self.as_ref().component_any_type_at(index)
1978    }
1979
1980    /// Gets a component type at the given type index.
1981    ///
1982    /// # Panics
1983    ///
1984    /// Panics if `index` is not a valid component type index.
1985    pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1986        self.as_ref().component_type_at(index)
1987    }
1988
1989    /// Gets a component type from the given component type index.
1990    ///
1991    /// # Panics
1992    ///
1993    /// Panics if `index` is not a valid defined type index or if this type
1994    /// information represents a core module.
1995    pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1996        self.as_ref().component_defined_type_at(index)
1997    }
1998
1999    /// Gets the count of core types.
2000    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    /// Gets the type of a table at the given table index.
2008    ///
2009    /// # Panics
2010    ///
2011    /// Panics if `index` is not a valid function index.
2012    pub fn table_at(&self, index: u32) -> TableType {
2013        self.as_ref().table_at(index)
2014    }
2015
2016    /// Gets the count of imported and defined tables.
2017    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    /// Gets the type of a memory at the given memory index.
2025    ///
2026    /// # Panics
2027    ///
2028    /// Panics if `index` is not a valid function index.
2029    pub fn memory_at(&self, index: u32) -> MemoryType {
2030        self.as_ref().memory_at(index)
2031    }
2032
2033    /// Gets the count of imported and defined memories.
2034    pub fn memory_count(&self) -> u32 {
2035        self.as_ref().memory_count()
2036    }
2037
2038    /// Gets the type of a global at the given global index.
2039    ///
2040    /// # Panics
2041    ///
2042    /// Panics if `index` is not a valid function index.
2043    pub fn global_at(&self, index: u32) -> GlobalType {
2044        self.as_ref().global_at(index)
2045    }
2046
2047    /// Gets the count of imported and defined globals.
2048    pub fn global_count(&self) -> u32 {
2049        self.as_ref().global_count()
2050    }
2051
2052    /// Gets the type of a tag at the given tag index.
2053    ///
2054    /// # Panics
2055    ///
2056    /// Panics if `index` is not a valid function index.
2057    pub fn tag_at(&self, index: u32) -> CoreTypeId {
2058        self.as_ref().tag_at(index)
2059    }
2060
2061    /// Gets the count of imported and defined tags.
2062    pub fn tag_count(&self) -> u32 {
2063        self.as_ref().tag_count()
2064    }
2065
2066    /// Gets the type of a core function at the given function index.
2067    ///
2068    /// # Panics
2069    ///
2070    /// Panics if `index` is not a valid function index.
2071    pub fn core_function_at(&self, index: u32) -> CoreTypeId {
2072        self.as_ref().core_function_at(index)
2073    }
2074
2075    /// Gets the count of core functions defined so far.
2076    ///
2077    /// Note that this includes imported functions, defined functions, and for
2078    /// components lowered/aliased functions.
2079    pub fn core_function_count(&self) -> u32 {
2080        self.as_ref().function_count()
2081    }
2082
2083    /// Gets the type of an element segment at the given element segment index.
2084    ///
2085    /// # Panics
2086    ///
2087    /// This will panic if the `index` provided is out of bounds.
2088    pub fn element_at(&self, index: u32) -> RefType {
2089        self.as_ref().element_at(index)
2090    }
2091
2092    /// Gets the count of element segments.
2093    pub fn element_count(&self) -> u32 {
2094        self.as_ref().element_count()
2095    }
2096
2097    /// Gets the type of a component function at the given function index.
2098    ///
2099    /// # Panics
2100    ///
2101    /// This will panic if the `index` provided is out of bounds or if this type
2102    /// information represents a core module.
2103    pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2104        self.as_ref().component_function_at(index)
2105    }
2106
2107    /// Gets the count of imported, exported, or aliased component functions.
2108    pub fn component_function_count(&self) -> u32 {
2109        self.as_ref().component_function_count()
2110    }
2111
2112    /// Gets the type of a module at the given module index.
2113    ///
2114    /// # Panics
2115    ///
2116    /// This will panic if the `index` provided is out of bounds or if this type
2117    /// information represents a core module.
2118    pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2119        self.as_ref().module_at(index)
2120    }
2121
2122    /// Gets the count of imported, exported, or aliased modules.
2123    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    /// Gets the type of a module instance at the given module instance index.
2131    ///
2132    /// # Panics
2133    ///
2134    /// This will panic if the `index` provided is out of bounds or if this type
2135    /// information represents a core module.
2136    pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2137        self.as_ref().core_instance_at(index)
2138    }
2139
2140    /// Gets the count of imported, exported, or aliased core module instances.
2141    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    /// Gets the type of a component at the given component index.
2149    ///
2150    /// # Panics
2151    ///
2152    /// This will panic if the `index` provided is out of bounds or if this type
2153    /// information represents a core module.
2154    pub fn component_at(&self, index: u32) -> ComponentTypeId {
2155        self.as_ref().component_at(index)
2156    }
2157
2158    /// Gets the count of imported, exported, or aliased components.
2159    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    /// Gets the type of an component instance at the given component instance index.
2167    ///
2168    /// # Panics
2169    ///
2170    /// This will panic if the `index` provided is out of bounds or if this type
2171    /// information represents a core module.
2172    pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2173        self.as_ref().component_instance_at(index)
2174    }
2175
2176    /// Gets the count of imported, exported, or aliased component instances.
2177    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    /// Gets the type of a value at the given value index.
2185    ///
2186    /// # Panics
2187    ///
2188    /// This will panic if the `index` provided is out of bounds or if this type
2189    /// information represents a core module.
2190    pub fn value_at(&self, index: u32) -> ComponentValType {
2191        self.as_ref().value_at(index)
2192    }
2193
2194    /// Gets the count of imported, exported, or aliased values.
2195    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    /// Gets the entity type from the given import.
2203    pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
2204        self.as_ref().entity_type_from_import(import)
2205    }
2206
2207    /// Gets the entity type from the given export.
2208    pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
2209        self.as_ref().entity_type_from_export(export)
2210    }
2211
2212    /// Gets the component entity type for the given component import name.
2213    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    /// Gets the component entity type for the given component export name.
2218    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    /// Attempts to lookup the type id that `ty` is an alias of.
2223    ///
2224    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
2225    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/// This is a type which mirrors a subset of the `Vec<T>` API, but is intended
2245/// to be able to be cheaply snapshotted and cloned.
2246///
2247/// When each module's code sections start we "commit" the current list of types
2248/// in the global list of types. This means that the temporary `cur` vec here is
2249/// pushed onto `snapshots` and wrapped up in an `Arc`. At that point we clone
2250/// this entire list (which is then O(modules), not O(types in all modules)) and
2251/// pass out as a context to each function validator.
2252///
2253/// Otherwise, though, this type behaves as if it were a large `Vec<T>`, but
2254/// it's represented by lists of contiguous chunks.
2255//
2256// Only public because it shows up in a public trait's `doc(hidden)` method.
2257#[doc(hidden)]
2258pub struct SnapshotList<T> {
2259    // All previous snapshots, the "head" of the list that this type represents.
2260    // The first entry in this pair is the starting index for all elements
2261    // contained in the list, and the second element is the list itself. Note
2262    // the `Arc` wrapper around sub-lists, which makes cloning time for this
2263    // `SnapshotList` O(snapshots) rather than O(snapshots_total), which for
2264    // us in this context means the number of modules, not types.
2265    //
2266    // Note that this list is sorted least-to-greatest in order of the index for
2267    // binary searching.
2268    snapshots: Vec<Arc<Snapshot<T>>>,
2269
2270    // This is the total length of all lists in the `snapshots` array.
2271    snapshots_total: usize,
2272
2273    // The current list of types for the current snapshot that are being built.
2274    cur: Vec<T>,
2275}
2276
2277struct Snapshot<T> {
2278    prior_types: usize,
2279    items: Vec<T>,
2280}
2281
2282impl<T> SnapshotList<T> {
2283    /// Same as `<&[T]>::get`
2284    pub(crate) fn get(&self, index: usize) -> Option<&T> {
2285        // Check to see if this index falls on our local list
2286        if index >= self.snapshots_total {
2287            return self.cur.get(index - self.snapshots_total);
2288        }
2289        // ... and failing that we do a binary search to figure out which bucket
2290        // it's in. Note the `i-1` in the `Err` case because if we don't find an
2291        // exact match the type is located in the previous bucket.
2292        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    /// Same as `Vec::push`
2304    pub(crate) fn push(&mut self, val: T) {
2305        self.cur.push(val);
2306    }
2307
2308    /// Same as `<[T]>::len`
2309    pub(crate) fn len(&self) -> usize {
2310        self.cur.len() + self.snapshots_total
2311    }
2312
2313    /// Same as `Vec::truncate` but can only truncate uncommitted elements.
2314    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    /// Commits previously pushed types into this snapshot vector, and returns a
2320    /// clone of this list.
2321    ///
2322    /// The returned `SnapshotList` can be used to access all the same types as
2323    /// this list itself. This list also is not changed (from an external
2324    /// perspective) and can continue to access all the same types.
2325    pub(crate) fn commit(&mut self) -> SnapshotList<T> {
2326        // If the current chunk has new elements, commit them in to an
2327        // `Arc`-wrapped vector in the snapshots list. Note the `shrink_to_fit`
2328        // ahead of time to hopefully keep memory usage lower than it would
2329        // otherwise be.
2330        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/// A snapshot list of types.
2379///
2380/// Note that the snapshot lists below do not correspond with index spaces. Many
2381/// different kinds of types are in the same index space (e.g. all of the
2382/// component model's {component, instance, defined, func} types are in the same
2383/// index space). However, we store each of them in their own type-specific
2384/// snapshot list and give each of them their own identifier type.
2385#[derive(Default)]
2386// Only public because it shows up in a public trait's `doc(hidden)` method.
2387#[doc(hidden)]
2388pub struct TypeList {
2389    // Keeps track of which `alias_id` is an alias of which other `alias_id`.
2390    alias_mappings: HashMap<u32, u32>,
2391    // Counter for generating new `alias_id`s.
2392    alias_counter: u32,
2393    // Snapshots of previously committed `TypeList`s' aliases.
2394    alias_snapshots: Vec<TypeListAliasSnapshot>,
2395
2396    // Core Wasm types.
2397    //
2398    // A primary map from `CoreTypeId` to `SubType`.
2399    core_types: SnapshotList<SubType>,
2400    // The id of each core Wasm type's rec group.
2401    //
2402    // A secondary map from `CoreTypeId` to `RecGroupId`.
2403    core_type_to_rec_group: SnapshotList<RecGroupId>,
2404    // The supertype of each core type.
2405    //
2406    // A secondary map from `coreTypeId` to `Option<CoreTypeId>`.
2407    core_type_to_supertype: SnapshotList<Option<CoreTypeId>>,
2408    // A primary map from `RecGroupId` to the range of the rec group's elements
2409    // within `core_types`.
2410    rec_group_elements: SnapshotList<Range<CoreTypeId>>,
2411    // A hash map from rec group elements to their canonical `RecGroupId`.
2412    //
2413    // This is `None` when a list is "committed" meaning that no more insertions
2414    // can happen.
2415    canonical_rec_groups: Option<HashMap<RecGroup, RecGroupId>>,
2416
2417    // Component model types.
2418    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    // The `alias_counter` at the time that this snapshot was taken.
2430    alias_counter: u32,
2431
2432    // The alias mappings in this snapshot.
2433    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    /// Intern the given recursion group (that has already been canonicalized)
2470    /// and return its associated id and whether this was a new recursion group
2471    /// or not.
2472    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    /// Get the `CoreTypeId` for a local index into a rec group.
2531    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    /// Get the id of the rec group that the given type id was defined within.
2553    pub fn rec_group_id_of(&self, id: CoreTypeId) -> RecGroupId {
2554        self.core_type_to_rec_group[id.index()]
2555    }
2556
2557    /// Get the super type of the given type id, if any.
2558    pub fn supertype_of(&self, id: CoreTypeId) -> Option<CoreTypeId> {
2559        self.core_type_to_supertype[id.index()]
2560    }
2561
2562    /// Get the `CoreTypeId` for a canonicalized `PackedIndex`.
2563    ///
2564    /// Panics when given a non-canonicalized `PackedIndex`.
2565    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    /// Get the `CoreTypeId` for a canonicalized `UnpackedIndex`.
2575    ///
2576    /// Panics when given a non-canonicalized `PackedIndex`.
2577    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    /// Does `a` structurally match `b`?
2591    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    /// Is `a == b` or was `a` declared (potentially transitively) to be a
2602    /// subtype of `b`?
2603    pub fn id_is_subtype(&self, mut a: CoreTypeId, b: CoreTypeId) -> bool {
2604        loop {
2605            if a == b {
2606                return true;
2607            }
2608
2609            // TODO: maintain supertype vectors and implement this check in O(1)
2610            // instead of O(n) time.
2611            a = match self.supertype_of(a) {
2612                Some(a) => a,
2613                None => return false,
2614            };
2615        }
2616    }
2617
2618    /// Like `id_is_subtype` but for `RefType`s.
2619    ///
2620    /// Both `a` and `b` must be canonicalized already.
2621    pub fn reftype_is_subtype(&self, a: RefType, b: RefType) -> bool {
2622        // NB: Don't need `RecGroupId`s since we are calling from outside of the
2623        // rec group, and so any `PackedIndex`es we encounter have already been
2624        // canonicalized to `CoreTypeId`s directly.
2625        self.reftype_is_subtype_impl(a, None, b, None)
2626    }
2627
2628    /// Implementation of `RefType` and `HeapType` subtyping.
2629    ///
2630    /// Panics if we need rec groups but aren't given them. Rec groups only need
2631    /// to be passed in when checking subtyping of `RefType`s that we encounter
2632    /// while validating a rec group itself.
2633    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            // Nothing else matches. (Avoid full wildcard matches so that
2703            // adding/modifying variants is easier in the future.)
2704            (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            // TODO: this probably isn't right, this is probably related to some
2717            // gc type.
2718            (HT::Exn, _) => false,
2719        }
2720    }
2721
2722    /// Like `id_is_subtype` but for `RefType`s.
2723    ///
2724    /// Both `a` and `b` must be canonicalized already.
2725    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    /// Get the top type of the given heap type.
2739    ///
2740    /// Concrete types must have had their indices canonicalized to core type
2741    /// ids, otherwise this method will panic.
2742    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        // Note that the `alias_counter` is bumped here to ensure that the
2838        // previous value of the unique counter is never used for an actual type
2839        // so it's suitable for lookup via a binary search.
2840        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    /// See `SnapshotList::with_unique`.
2868    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    /// Attempts to lookup the type id that `ty` is an alias of.
2880    ///
2881    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
2882    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        // The unique counter in each snapshot is the unique counter at the
2889        // time of the snapshot so it's guaranteed to never be used, meaning
2890        // that `Ok` should never show up here. With an `Err` it's where the
2891        // index would be placed meaning that the index in question is the
2892        // smallest value over the unique id's value, meaning that slot has the
2893        // mapping we're interested in.
2894        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        // If the `i` index is beyond the snapshot array then lookup in the
2903        // current mappings instead since it may refer to a type not snapshot
2904        // yet.
2905        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
2925/// Thin wrapper around `TypeList` which provides an allocator of unique ids for
2926/// types contained within this list.
2927pub(crate) struct TypeAlloc {
2928    list: TypeList,
2929
2930    // This is assigned at creation of a `TypeAlloc` and then never changed.
2931    // It's used in one entry for all `ResourceId`s contained within.
2932    globally_unique_id: usize,
2933
2934    // This is a counter that's incremeneted each time `alloc_resource_id` is
2935    // called.
2936    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    /// Pushes a new type into this list, returning an identifier which can be
2974    /// used to later retrieve it.
2975    ///
2976    /// The returned identifier is unique within this `TypeAlloc` and won't be
2977    /// hash-equivalent to anything else.
2978    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    /// Allocates a new unique resource identifier.
2986    ///
2987    /// Note that uniqueness is only a property within this `TypeAlloc`.
2988    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    /// Adds the set of "free variables" of the `id` provided to the `set`
3001    /// provided.
3002    ///
3003    /// Free variables are defined as resources. Any resource, perhaps
3004    /// transitively, referred to but not defined by `id` is added to the `set`
3005    /// and returned.
3006    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        // Recurse on the imports/exports of components, but remove the
3076        // imported and defined resources within the component itself.
3077        //
3078        // Technically this needs to add all the free variables of the
3079        // exports, remove the defined resources, then add the free
3080        // variables of imports, then remove the imported resources. Given
3081        // prior validation of component types, however, the defined
3082        // and imported resources are disjoint and imports can't refer to
3083        // defined resources, so doing this all in one go should be
3084        // equivalent.
3085        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        // Like components, add in all the free variables of referenced
3100        // types but then remove those defined by this component instance
3101        // itself.
3102        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    /// Same as `free_variables_type_id`, but for `ComponentEntityType`.
3127    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    /// Same as `free_variables_type_id`, but for `ComponentValType`.
3147    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    /// Returns whether the type `id` is "named" where named types are presented
3159    /// via the provided `set`.
3160    ///
3161    /// This requires that `id` is a `Defined` type.
3162    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            // Primitives are always considered named
3170            ComponentDefinedType::Primitive(_) => true,
3171
3172            // These structures are never allowed to be anonymous, so they
3173            // themselves must be named.
3174            ComponentDefinedType::Flags(_)
3175            | ComponentDefinedType::Enum(_)
3176            | ComponentDefinedType::Record(_)
3177            | ComponentDefinedType::Variant(_) => set.contains::<ComponentAnyTypeId>(&id.into()),
3178
3179            // All types below here are allowed to be anonymous, but their
3180            // own components must be appropriately named.
3181            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            // own/borrow themselves don't have to be named, but the resource
3198            // they refer to must be named.
3199            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
3217/// A helper trait to provide the functionality necessary to resources within a
3218/// type.
3219///
3220/// This currently exists to abstract over `TypeAlloc` and `SubtypeArena` which
3221/// both need to perform remapping operations.
3222pub 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    /// Pushes a new anonymous type within this object, returning an identifier
3230    /// which can be used to refer to it.
3231    fn push_ty<T>(&mut self, ty: T) -> T::Id
3232    where
3233        T: TypeData;
3234
3235    /// Apply `map` to the keys of `tmp`, setting `*any_changed = true` if any
3236    /// keys were remapped.
3237    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    /// If `any_changed` is true, push `ty`, update `map` to point `id` to the
3255    /// new type ID, set `id` equal to the new type ID, and return `true`.
3256    /// Otherwise, update `map` to point `id` to itself and return `false`.
3257    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    /// Recursively search for any resource types reachable from `id`, updating
3276    /// it and `map` if any are found and remapped, returning `true` iff at last
3277    /// one is remapped.
3278    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    /// If `map` indicates `id` should be remapped, update it and return `true`.
3293    /// Otherwise, do nothing and return `false`.
3294    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    /// Recursively search for any resource types reachable from `id`, updating
3309    /// it and `map` if any are found and remapped, returning `true` iff at last
3310    /// one is remapped.
3311    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    /// Recursively search for any resource types reachable from `id`, updating
3336    /// it and `map` if any are found and remapped, returning `true` iff at last
3337    /// one is remapped.
3338    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    /// Recursively search for any resource types reachable from `id`, updating
3389    /// it and `map` if any are found and remapped, returning `true` iff at last
3390    /// one is remapped.
3391    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    /// Recursively search for any resource types reachable from `id`, updating
3416    /// it and `map` if any are found and remapped, returning `true` iff at last
3417    /// one is remapped.
3418    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    /// Same as `remap_type_id`, but works with `ComponentEntityType`.
3441    fn remap_component_entity(
3442        &mut self,
3443        ty: &mut ComponentEntityType,
3444        map: &mut Remapping,
3445    ) -> bool {
3446        match ty {
3447            ComponentEntityType::Module(_) => {
3448                // Can't reference resources.
3449                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    /// Same as `remap_type_id`, but works with `ComponentValType`.
3471    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/// Utility for mapping equivalent `ResourceId`s to each other and (when paired with the `Remap` trait)
3480/// non-destructively edit type lists to reflect those mappings.
3481#[derive(Debug, Default)]
3482pub struct Remapping {
3483    /// A mapping from old resource ID to new resource ID.
3484    pub(crate) resources: HashMap<ResourceId, ResourceId>,
3485
3486    /// A mapping filled in during the remapping process which records how a
3487    /// type was remapped, if applicable. This avoids remapping multiple
3488    /// references to the same type and instead only processing it once.
3489    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    /// Add a mapping from the specified old resource ID to the new resource ID
3515    pub fn add(&mut self, old: ResourceId, new: ResourceId) {
3516        self.resources.insert(old, new);
3517    }
3518
3519    /// Clear the type cache while leaving the resource mappings intact.
3520    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
3540/// Helper structure used to perform subtyping computations.
3541///
3542/// This type is used whenever a subtype needs to be tested in one direction or
3543/// the other. The methods of this type are the various entry points for
3544/// subtyping.
3545///
3546/// Internally this contains arenas for two lists of types. The `a` arena is
3547/// intended to be used for lookup of the first argument to all of the methods
3548/// below, and the `b` arena is used for lookup of the second argument.
3549///
3550/// Arenas here are used specifically for component-based subtyping queries. In
3551/// these situations new types must be created based on substitution mappings,
3552/// but the types all have temporary lifetimes. Everything in these arenas is
3553/// thrown away once the subtyping computation has finished.
3554///
3555/// Note that this subtyping context also explicitly supports being created
3556/// from to different lists `a` and `b` originally, for testing subtyping
3557/// between two different components for example.
3558pub struct SubtypeCx<'a> {
3559    /// Lookup arena for first type argument
3560    pub a: SubtypeArena<'a>,
3561    /// Lookup arena for second type argument
3562    pub b: SubtypeArena<'a>,
3563}
3564
3565impl<'a> SubtypeCx<'a> {
3566    /// Create a new instance with the specified type lists
3567    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    /// Swap the type lists
3579    pub fn swap(&mut self) {
3580        mem::swap(&mut self.a, &mut self.b);
3581    }
3582
3583    /// Executes the closure `f`, resetting the internal arenas to their
3584    /// original size after the closure finishes.
3585    ///
3586    /// This enables `f` to modify the internal arenas while relying on all
3587    /// changes being discarded after the closure finishes.
3588    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    /// Tests whether `a` is a subtype of `b`.
3598    ///
3599    /// Errors are reported at the `offset` specified.
3600    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    /// Tests whether `a` is a subtype of `b`.
3632    ///
3633    /// Errors are reported at the `offset` specified.
3634    pub fn component_type(
3635        &mut self,
3636        a: ComponentTypeId,
3637        b: ComponentTypeId,
3638        offset: usize,
3639    ) -> Result<()> {
3640        // Components are ... tricky. They follow the same basic
3641        // structure as core wasm modules, but they also have extra
3642        // logic to handle resource types. Resources are effectively
3643        // abstract types so this is sort of where an ML module system
3644        // in the component model becomes a reality.
3645        //
3646        // This also leverages the `open_instance_type` method below
3647        // heavily which internally has its own quite large suite of
3648        // logic. More-or-less what's happening here is:
3649        //
3650        // 1. Pretend that the imports of B are given as values to the
3651        //    imports of A. If A didn't import anything, for example,
3652        //    that's great and the subtyping definitely passes there.
3653        //    This operation produces a mapping of all the resources of
3654        //    A's imports to resources in B's imports.
3655        //
3656        // 2. This mapping is applied to all of A's exports. This means
3657        //    that all exports of A referring to A's imported resources
3658        //    now instead refer to B's. Note, though that A's exports
3659        //    still refer to its own defined resources.
3660        //
3661        // 3. The same `open_instance_type` method used during the
3662        //    first step is used again, but this time on the exports
3663        //    in the reverse direction. This performs a similar
3664        //    operation, though, by creating a mapping from B's
3665        //    defined resources to A's defined resources. The map
3666        //    itself is discarded as it's not needed.
3667        //
3668        // The order that everything passed here is intentional, but
3669        // also subtle. I personally think of it as
3670        // `open_instance_type` takes a list of things to satisfy a
3671        // signature and produces a mapping of resources in the
3672        // signature to those provided in the list of things. The
3673        // order of operations then goes:
3674        //
3675        // * Someone thinks they have a component of type B, but they
3676        //   actually have a component of type A (e.g. due to this
3677        //   subtype check passing).
3678        // * This person provides the imports of B and that must be
3679        //   sufficient to satisfy the imports of A. This is the first
3680        //   `open_instance_type` check.
3681        // * Now though the resources provided by B are substituted
3682        //   into A's exports since that's what was provided.
3683        // * A's exports are then handed back to the original person,
3684        //   and these exports must satisfy the signature required by B
3685        //   since that's what they're expecting.
3686        // * This is the second `open_instance_type` which, to get
3687        //   resource types to line up, will map from A's defined
3688        //   resources to B's defined resources.
3689        //
3690        // If all that passes then the resources should all line up
3691        // perfectly. Any misalignment is reported as a subtyping
3692        // error.
3693        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    /// Tests whether `a` is a subtype of `b`.
3717    ///
3718    /// Errors are reported at the `offset` specified.
3719    pub fn component_instance_type(
3720        &mut self,
3721        a_id: ComponentInstanceTypeId,
3722        b_id: ComponentInstanceTypeId,
3723        offset: usize,
3724    ) -> Result<()> {
3725        // For instance type subtyping, all exports in the other
3726        // instance type must be present in this instance type's
3727        // exports (i.e. it can export *more* than what this instance
3728        // type needs).
3729        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            // On failure attach the name of this export as context to
3745            // the error message to leave a breadcrumb trail.
3746            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    /// Tests whether `a` is a subtype of `b`.
3753    ///
3754    /// Errors are reported at the `offset` specified.
3755    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        // Note that this intentionally diverges from the upstream
3765        // specification in terms of subtyping. This is a full
3766        // type-equality check which ensures that the structure of `a`
3767        // exactly matches the structure of `b`. The rationale for this
3768        // is:
3769        //
3770        // * Primarily in Wasmtime subtyping based on function types is
3771        //   not implemented. This includes both subtyping a host
3772        //   import and additionally handling subtyping as functions
3773        //   cross component boundaries. The host import subtyping (or
3774        //   component export subtyping) is not clear how to handle at
3775        //   all at this time. The subtyping of functions between
3776        //   components can more easily be handled by extending the
3777        //   `fact` compiler, but that hasn't been done yet.
3778        //
3779        // * The upstream specification is currently pretty
3780        //   intentionally vague precisely what subtyping is allowed.
3781        //   Implementing a strict check here is intended to be a
3782        //   conservative starting point for the component model which
3783        //   can be extended in the future if necessary.
3784        //
3785        // * The interaction with subtyping on bindings generation, for
3786        //   example, is a tricky problem that doesn't have a clear
3787        //   answer at this time.  Effectively this is more rationale
3788        //   for being conservative in the first pass of the component
3789        //   model.
3790        //
3791        // So, in conclusion, the test here (and other places that
3792        // reference this comment) is for exact type equality with no
3793        // differences.
3794        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    /// Tests whether `a` is a subtype of `b`.
3828    ///
3829    /// Errors are reported at the `offset` specified.
3830    pub fn module_type(
3831        &mut self,
3832        a: ComponentCoreModuleTypeId,
3833        b: ComponentCoreModuleTypeId,
3834        offset: usize,
3835    ) -> Result<()> {
3836        // For module type subtyping, all exports in the other module
3837        // type must be present in this module type's exports (i.e. it
3838        // can export *more* than what this module type needs).
3839        // However, for imports, the check is reversed (i.e. it is okay
3840        // to import *less* than what this module type needs).
3841        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    /// Tests whether `a` is a subtype of `b`.
3867    ///
3868    /// Errors are reported at the `offset` specified.
3869    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    /// The building block for subtyping checks when components are
3922    /// instantiated and when components are tested if they're subtypes of each
3923    /// other.
3924    ///
3925    /// This method takes a number of arguments:
3926    ///
3927    /// * `a` - this is a list of typed items which can be thought of as
3928    ///   concrete values to test against `b`.
3929    /// * `b` - this `TypeId` must point to `Type::Component`.
3930    /// * `kind` - indicates whether the `imports` or `exports` of `b` are
3931    ///   being tested against for the values in `a`.
3932    /// * `offset` - the binary offset at which to report errors if one happens.
3933    ///
3934    /// This will attempt to determine if the items in `a` satisfy the
3935    /// signature required by the `kind` items of `b`. For example component
3936    /// instantiation will have `a` as the list of arguments provided to
3937    /// instantiation, `b` is the component being instantiated, and `kind` is
3938    /// `ExternKind::Import`.
3939    ///
3940    /// This function, if successful, will return a mapping of the resources in
3941    /// `b` to the resources in `a` provided. This mapping is guaranteed to
3942    /// contain all the resources for `b` (all imported resources for
3943    /// `ExternKind::Import` or all defined resources for `ExternKind::Export`).
3944    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        // First, determine the mapping from resources in `b` to those supplied
3952        // by arguments in `a`.
3953        //
3954        // This loop will iterate over all the appropriate resources in `b`
3955        // and find the corresponding resource in `args`. The exact lists
3956        // in use here depend on the `kind` provided. This necessarily requires
3957        // a sequence of string lookups to find the corresponding items in each
3958        // list.
3959        //
3960        // The path to each resource in `resources` is precomputed as a list of
3961        // indexes. The first index is into `b`'s list of `entities`, and gives
3962        // the name that `b` assigns to the resource.  Each subsequent index,
3963        // if present, means that this resource was present through a layer of
3964        // an instance type, and the index is into the instance type's exports.
3965        // More information about this can be found on
3966        // `ComponentState::imported_resources`.
3967        //
3968        // This loop will follow the list of indices for each resource and, at
3969        // the same time, walk through the arguments supplied to instantiating
3970        // the `component_type`. This means that within `component_type`
3971        // index-based lookups are performed while in `args` name-based
3972        // lookups are performed.
3973        //
3974        // Note that here it's possible that `args` doesn't actually supply the
3975        // correct type of import for each item since argument checking has
3976        // not proceeded yet. These type errors, however, aren't handled by
3977        // this loop and are deferred below to the main subtyping check. That
3978        // means that `mapping` won't necessarily have a mapping for all
3979        // imported resources into `component_type`, but that should be ok.
3980        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            // Lookup the first path item in `imports` and the corresponding
3992            // entry in `args` by name.
3993            let (name, ty) = entities.get_index(path[0]).unwrap();
3994            let mut ty = *ty;
3995            let mut arg = a.get(name);
3996
3997            // Lookup all the subsequent `path` entries, if any, by index in
3998            // `ty` and by name in `arg`. Type errors in `arg` are skipped over
3999            // entirely.
4000            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            // Double-check that `ty`, the leaf type of `component_type`, is
4014            // indeed the expected resource.
4015            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            // The leaf of `arg` should be a type which is a resource. If not
4027            // it's skipped and this'll wind up generating an error later on in
4028            // subtype checking below.
4029            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        // Now that a mapping from the resources in `b` to the resources in `a`
4037        // has been determined it's possible to perform the actual subtype
4038        // check.
4039        //
4040        // This subtype check notably needs to ensure that all resource types
4041        // line up. To achieve this the `mapping` previously calculated is used
4042        // to perform a substitution on each component entity type.
4043        //
4044        // The first loop here performs a name lookup to create a list of
4045        // values from `a` to expected items in `b`. Once the list is created
4046        // the substitution check is performed on each element.
4047        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                    // On a successful type-check record a mapping of
4065                    // type-to-type in `type_map` for any type imports that were
4066                    // satisfied. This is then used afterwards when performing
4067                    // type substitution to remap all component-local types to
4068                    // those that were provided in the imports.
4069                    self.register_type_renamings(actual, expected, &mut type_map);
4070                    continue;
4071                }
4072                Err(e) => e,
4073            };
4074
4075            // If an error happens then attach the name of the entity to the
4076            // error message using the `i` iteration counter.
4077            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        // Note that the implementation of subtyping here diverges from the
4210        // upstream specification intentionally, see the documentation on
4211        // function subtyping for more information.
4212        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        // Note that this intentionally diverges from the upstream specification
4333        // at this time and only considers exact equality for subtyping
4334        // relationships.
4335        //
4336        // More information can be found in the subtyping implementation for
4337        // component functions.
4338        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
4375/// A helper typed used purely during subtyping as part of `SubtypeCx`.
4376///
4377/// This takes a `types` list as input which is the "base" of the ids that can
4378/// be indexed through this arena. All future types pushed into this, if any,
4379/// are stored in `self.list`.
4380///
4381/// This is intended to have arena-like behavior where everything pushed onto
4382/// `self.list` is thrown away after a subtyping computation is performed. All
4383/// new types pushed into this arena are purely temporary.
4384pub 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
4429/// Helper trait for adding contextual information to an error, modeled after
4430/// `anyhow::Context`.
4431pub(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}