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::{collections::map::Entry, AbstractHeapType};
8use crate::{prelude::*, CompositeInnerType};
9use crate::{validator::names::KebabString, HeapType, ValidatorId};
10use crate::{
11    BinaryReaderError, Export, ExternalKind, FuncType, GlobalType, Import, Matches, MemoryType,
12    PackedIndex, PrimitiveValType, RecGroup, RefType, Result, SubType, TableType, TypeRef,
13    UnpackedIndex, ValType, WithRecGroup,
14};
15use alloc::sync::Arc;
16use core::ops::{Deref, DerefMut, Index, Range};
17use core::sync::atomic::{AtomicUsize, Ordering};
18use core::{
19    borrow::Borrow,
20    hash::{Hash, Hasher},
21    mem,
22};
23
24/// The maximum number of parameters in the canonical ABI that can be passed by value.
25///
26/// Functions that exceed this limit will instead pass parameters indirectly from
27/// linear memory via a single pointer parameter.
28const MAX_FLAT_FUNC_PARAMS: usize = 16;
29/// The maximum number of results in the canonical ABI that can be returned by a function.
30///
31/// Functions that exceed this limit have their results written to linear memory via an
32/// additional pointer parameter (imports) or return a single pointer value (exports).
33const MAX_FLAT_FUNC_RESULTS: usize = 1;
34
35/// The maximum lowered types, including a possible type for a return pointer parameter.
36const MAX_LOWERED_TYPES: usize = MAX_FLAT_FUNC_PARAMS + 1;
37
38/// A simple alloc-free list of types used for calculating lowered function signatures.
39pub(crate) struct LoweredTypes {
40    types: [ValType; MAX_LOWERED_TYPES],
41    len: usize,
42    max: usize,
43}
44
45impl LoweredTypes {
46    fn new(max: usize) -> Self {
47        assert!(max <= MAX_LOWERED_TYPES);
48        Self {
49            types: [ValType::I32; MAX_LOWERED_TYPES],
50            len: 0,
51            max,
52        }
53    }
54
55    fn len(&self) -> usize {
56        self.len
57    }
58
59    fn maxed(&self) -> bool {
60        self.len == self.max
61    }
62
63    fn get_mut(&mut self, index: usize) -> Option<&mut ValType> {
64        if index < self.len {
65            Some(&mut self.types[index])
66        } else {
67            None
68        }
69    }
70
71    fn push(&mut self, ty: ValType) -> bool {
72        if self.maxed() {
73            return false;
74        }
75
76        self.types[self.len] = ty;
77        self.len += 1;
78        true
79    }
80
81    fn clear(&mut self) {
82        self.len = 0;
83    }
84
85    pub fn as_slice(&self) -> &[ValType] {
86        &self.types[..self.len]
87    }
88
89    pub fn iter(&self) -> impl Iterator<Item = ValType> + '_ {
90        self.as_slice().iter().copied()
91    }
92}
93
94/// Represents information about a component function type lowering.
95pub(crate) struct LoweringInfo {
96    pub(crate) params: LoweredTypes,
97    pub(crate) results: LoweredTypes,
98    pub(crate) requires_memory: bool,
99    pub(crate) requires_realloc: bool,
100}
101
102impl LoweringInfo {
103    pub(crate) fn into_func_type(self) -> FuncType {
104        FuncType::new(
105            self.params.as_slice().iter().copied(),
106            self.results.as_slice().iter().copied(),
107        )
108    }
109}
110
111impl Default for LoweringInfo {
112    fn default() -> Self {
113        Self {
114            params: LoweredTypes::new(MAX_FLAT_FUNC_PARAMS),
115            results: LoweredTypes::new(MAX_FLAT_FUNC_RESULTS),
116            requires_memory: false,
117            requires_realloc: false,
118        }
119    }
120}
121
122fn push_primitive_wasm_types(ty: &PrimitiveValType, lowered_types: &mut LoweredTypes) -> bool {
123    match ty {
124        PrimitiveValType::Bool
125        | PrimitiveValType::S8
126        | PrimitiveValType::U8
127        | PrimitiveValType::S16
128        | PrimitiveValType::U16
129        | PrimitiveValType::S32
130        | PrimitiveValType::U32
131        | PrimitiveValType::Char => lowered_types.push(ValType::I32),
132        PrimitiveValType::S64 | PrimitiveValType::U64 => lowered_types.push(ValType::I64),
133        PrimitiveValType::F32 => lowered_types.push(ValType::F32),
134        PrimitiveValType::F64 => lowered_types.push(ValType::F64),
135        PrimitiveValType::String => {
136            lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32)
137        }
138    }
139}
140
141/// A trait shared by all type identifiers.
142///
143/// Any id that can be used to get a type from a `Types`.
144//
145// Or, internally, from a `TypeList`.
146pub trait TypeIdentifier: core::fmt::Debug + Copy + Eq + Sized + 'static {
147    /// The data pointed to by this type of id.
148    type Data: TypeData<Id = Self>;
149
150    /// Create a type id from an index.
151    #[doc(hidden)]
152    fn from_index(index: u32) -> Self;
153
154    /// Get a shared reference to the list where this id's type data is stored
155    /// within.
156    #[doc(hidden)]
157    fn list(types: &TypeList) -> &SnapshotList<Self::Data>;
158
159    /// Get an exclusive reference to the list where this id's type data is
160    /// stored within.
161    #[doc(hidden)]
162    fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data>;
163
164    /// The raw index of this id.
165    #[doc(hidden)]
166    fn index(&self) -> usize;
167}
168
169/// A trait shared by all types within a `Types`.
170///
171/// This is the data that can be retreived by indexing with the associated
172/// [`TypeIdentifier`].
173pub trait TypeData: core::fmt::Debug {
174    /// The identifier for this type data.
175    type Id: TypeIdentifier<Data = Self>;
176
177    /// Get the info for this type.
178    #[doc(hidden)]
179    fn type_info(&self, types: &TypeList) -> TypeInfo;
180}
181
182/// A type that can be aliased in the component model.
183pub trait Aliasable {
184    #[doc(hidden)]
185    fn alias_id(&self) -> u32;
186
187    #[doc(hidden)]
188    fn set_alias_id(&mut self, alias_id: u32);
189}
190
191/// A fresh alias id that means the entity is not an alias of anything.
192///
193/// Note that the `TypeList::alias_counter` starts at zero, so we can't use that
194/// as this sentinel. The implementation limits are such that we can't ever
195/// generate `u32::MAX` aliases, so we don't need to worryabout running into
196/// this value in practice either.
197const NO_ALIAS: u32 = u32::MAX;
198
199macro_rules! define_type_id {
200    ($name:ident, $data:ty, $list:ident, $type_str:expr) => {
201        #[doc = "Represents a unique identifier for a "]
202        #[doc = $type_str]
203        #[doc = " type known to a [`crate::Validator`]."]
204        #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
205        #[repr(C)] // Use fixed field layout to ensure minimal size.
206        pub struct $name {
207            /// The index into the associated list of types.
208            index: u32,
209        }
210
211        impl TypeIdentifier for $name {
212            type Data = $data;
213
214            fn from_index(index: u32) -> Self {
215                $name { index }
216            }
217
218            fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
219                &types.$list
220            }
221
222            fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
223                &mut types.$list
224            }
225
226            fn index(&self) -> usize {
227                usize::try_from(self.index).unwrap()
228            }
229        }
230
231        impl Aliasable for $name {
232            fn alias_id(&self) -> u32 {
233                NO_ALIAS
234            }
235
236            fn set_alias_id(&mut self, _: u32) {}
237        }
238
239        // The size of type IDs was seen to have a large-ish impact in #844, so
240        // this assert ensures that it stays relatively small.
241        const _: () = {
242            assert!(core::mem::size_of::<$name>() <= 4);
243        };
244    };
245}
246
247/// A core WebAssembly type, in the core WebAssembly types index space.
248pub enum CoreType {
249    /// A sub type.
250    Sub(SubType),
251
252    /// A module type.
253    ///
254    /// Does not actually appear in core Wasm at the moment. Only used for the
255    /// core types index space within components.
256    Module(ModuleType),
257}
258
259/// Represents a unique identifier for a core type type known to a
260/// [`crate::Validator`]
261#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
262#[repr(C)]
263pub struct CoreTypeId {
264    index: u32,
265}
266
267const _: () = {
268    assert!(core::mem::size_of::<CoreTypeId>() <= 4);
269};
270
271impl TypeIdentifier for CoreTypeId {
272    type Data = SubType;
273
274    fn from_index(index: u32) -> Self {
275        CoreTypeId { index }
276    }
277
278    fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
279        &types.core_types
280    }
281
282    fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
283        &mut types.core_types
284    }
285
286    fn index(&self) -> usize {
287        usize::try_from(self.index).unwrap()
288    }
289}
290
291impl TypeData for SubType {
292    type Id = CoreTypeId;
293
294    fn type_info(&self, _types: &TypeList) -> TypeInfo {
295        // TODO(#1036): calculate actual size for func, array, struct.
296        let size = 1 + match &self.composite_type.inner {
297            CompositeInnerType::Func(ty) => 1 + (ty.params().len() + ty.results().len()) as u32,
298            CompositeInnerType::Array(_) => 2,
299            CompositeInnerType::Struct(ty) => 1 + 2 * ty.fields.len() as u32,
300        };
301        TypeInfo::core(size)
302    }
303}
304
305impl CoreType {
306    /// Get the underlying `SubType` or panic.
307    pub fn unwrap_sub(&self) -> &SubType {
308        match self {
309            CoreType::Sub(s) => s,
310            CoreType::Module(_) => panic!("`unwrap_sub` on module type"),
311        }
312    }
313
314    /// Get the underlying `FuncType` within this `SubType` or panic.
315    pub fn unwrap_func(&self) -> &FuncType {
316        match &self.unwrap_sub().composite_type.inner {
317            CompositeInnerType::Func(f) => f,
318            CompositeInnerType::Array(_) | CompositeInnerType::Struct(_) => {
319                panic!("`unwrap_func` on non-func composite type")
320            }
321        }
322    }
323
324    /// Get the underlying `ModuleType` or panic.
325    pub fn unwrap_module(&self) -> &ModuleType {
326        match self {
327            CoreType::Module(m) => m,
328            CoreType::Sub(_) => panic!("`unwrap_module` on a subtype"),
329        }
330    }
331}
332
333macro_rules! define_wrapper_id {
334    (
335        $(#[$outer_attrs:meta])*
336        pub enum $name:ident {
337            $(
338                #[unwrap = $unwrap:ident]
339                $(#[$inner_attrs:meta])*
340                $variant:ident ( $inner:ty ) ,
341            )*
342        }
343    ) => {
344        $(#[$outer_attrs])*
345        pub enum $name {
346            $(
347                $(#[$inner_attrs])*
348                $variant ( $inner ) ,
349            )*
350        }
351
352        $(
353            impl From<$inner> for $name {
354                #[inline]
355                fn from(x: $inner) -> Self {
356                    Self::$variant(x)
357                }
358            }
359
360            impl TryFrom<$name> for $inner {
361                type Error = ();
362
363                #[inline]
364                fn try_from(x: $name) -> Result<Self, Self::Error> {
365                    match x {
366                        $name::$variant(x) => Ok(x),
367                        _ => Err(())
368                    }
369                }
370            }
371        )*
372
373        impl $name {
374            $(
375                #[doc = "Unwrap a `"]
376                #[doc = stringify!($inner)]
377                #[doc = "` or panic."]
378                #[inline]
379                pub fn $unwrap(self) -> $inner {
380                    <$inner>::try_from(self).unwrap()
381                }
382            )*
383        }
384    };
385}
386
387macro_rules! define_transitive_conversions {
388    (
389        $(
390            $outer:ty,
391            $middle:ty,
392            $inner:ty,
393            $unwrap:ident;
394        )*
395    ) => {
396        $(
397            impl From<$inner> for $outer {
398                #[inline]
399                fn from(x: $inner) -> Self {
400                    <$middle>::from(x).into()
401                }
402            }
403
404            impl TryFrom<$outer> for $inner {
405                type Error = ();
406
407                #[inline]
408                fn try_from(x: $outer) -> Result<Self, Self::Error> {
409                    let middle = <$middle>::try_from(x)?;
410                    <$inner>::try_from(middle)
411                }
412            }
413
414            impl $outer {
415                #[doc = "Unwrap a `"]
416                #[doc = stringify!($inner)]
417                #[doc = "` or panic."]
418                #[inline]
419                pub fn $unwrap(self) -> $inner {
420                    <$inner>::try_from(self).unwrap()
421                }
422            }
423        )*
424    };
425}
426
427define_wrapper_id! {
428    /// An identifier pointing to any kind of type, component or core.
429    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
430    pub enum AnyTypeId {
431        #[unwrap = unwrap_component_core_type]
432        /// A core type.
433        Core(ComponentCoreTypeId),
434
435        #[unwrap = unwrap_component_any_type]
436        /// A component type.
437        Component(ComponentAnyTypeId),
438    }
439}
440
441define_transitive_conversions! {
442    AnyTypeId, ComponentCoreTypeId, CoreTypeId, unwrap_core_type;
443    AnyTypeId, ComponentCoreTypeId, ComponentCoreModuleTypeId, unwrap_component_core_module_type;
444    AnyTypeId, ComponentAnyTypeId, AliasableResourceId, unwrap_aliasable_resource;
445    AnyTypeId, ComponentAnyTypeId, ComponentDefinedTypeId, unwrap_component_defined_type;
446    AnyTypeId, ComponentAnyTypeId, ComponentFuncTypeId, unwrap_component_func_type;
447    AnyTypeId, ComponentAnyTypeId, ComponentInstanceTypeId, unwrap_component_instance_type;
448    AnyTypeId, ComponentAnyTypeId, ComponentTypeId, unwrap_component_type;
449}
450
451impl AnyTypeId {
452    /// Peel off one layer of aliasing from this type and return the aliased
453    /// inner type, or `None` if this type is not aliasing anything.
454    pub fn peel_alias(&self, types: &Types) -> Option<Self> {
455        match *self {
456            Self::Core(id) => id.peel_alias(types).map(Self::Core),
457            Self::Component(id) => types.peel_alias(id).map(Self::Component),
458        }
459    }
460}
461
462define_wrapper_id! {
463    /// An identifier for a core type or a core module's type.
464    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
465    pub enum ComponentCoreTypeId {
466        #[unwrap = unwrap_sub]
467        /// A core type.
468        Sub(CoreTypeId),
469
470        #[unwrap = unwrap_module]
471        /// A core module's type.
472        Module(ComponentCoreModuleTypeId),
473    }
474}
475
476impl ComponentCoreTypeId {
477    /// Peel off one layer of aliasing from this type and return the aliased
478    /// inner type, or `None` if this type is not aliasing anything.
479    pub fn peel_alias(&self, types: &Types) -> Option<Self> {
480        match *self {
481            Self::Sub(_) => None,
482            Self::Module(id) => types.peel_alias(id).map(Self::Module),
483        }
484    }
485}
486
487/// An aliasable resource identifier.
488#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
489pub struct AliasableResourceId {
490    id: ResourceId,
491    alias_id: u32,
492}
493
494impl Aliasable for AliasableResourceId {
495    fn alias_id(&self) -> u32 {
496        self.alias_id
497    }
498
499    fn set_alias_id(&mut self, alias_id: u32) {
500        self.alias_id = alias_id;
501    }
502}
503
504impl AliasableResourceId {
505    /// Create a new instance with the specified resource ID and `self`'s alias
506    /// ID.
507    pub fn with_resource_id(&self, id: ResourceId) -> Self {
508        Self {
509            id,
510            alias_id: self.alias_id,
511        }
512    }
513
514    /// Get the underlying resource.
515    pub fn resource(&self) -> ResourceId {
516        self.id
517    }
518
519    pub(crate) fn resource_mut(&mut self) -> &mut ResourceId {
520        &mut self.id
521    }
522}
523
524define_wrapper_id! {
525    /// An identifier for any kind of component type.
526    #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
527    pub enum ComponentAnyTypeId {
528        #[unwrap = unwrap_resource]
529        /// The type is a resource with the specified id.
530        Resource(AliasableResourceId),
531
532        #[unwrap = unwrap_defined]
533        /// The type is a defined type with the specified id.
534        Defined(ComponentDefinedTypeId),
535
536        #[unwrap = unwrap_func]
537        /// The type is a function type with the specified id.
538        Func(ComponentFuncTypeId),
539
540        #[unwrap = unwrap_instance]
541        /// The type is an instance type with the specified id.
542        Instance(ComponentInstanceTypeId),
543
544        #[unwrap = unwrap_component]
545        /// The type is a component type with the specified id.
546        Component(ComponentTypeId),
547    }
548}
549
550impl Aliasable for ComponentAnyTypeId {
551    fn alias_id(&self) -> u32 {
552        match self {
553            ComponentAnyTypeId::Resource(x) => x.alias_id(),
554            ComponentAnyTypeId::Defined(x) => x.alias_id(),
555            ComponentAnyTypeId::Func(x) => x.alias_id(),
556            ComponentAnyTypeId::Instance(x) => x.alias_id(),
557            ComponentAnyTypeId::Component(x) => x.alias_id(),
558        }
559    }
560
561    fn set_alias_id(&mut self, alias_id: u32) {
562        match self {
563            ComponentAnyTypeId::Resource(x) => x.set_alias_id(alias_id),
564            ComponentAnyTypeId::Defined(x) => x.set_alias_id(alias_id),
565            ComponentAnyTypeId::Func(x) => x.set_alias_id(alias_id),
566            ComponentAnyTypeId::Instance(x) => x.set_alias_id(alias_id),
567            ComponentAnyTypeId::Component(x) => x.set_alias_id(alias_id),
568        }
569    }
570}
571
572impl ComponentAnyTypeId {
573    pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
574        match *self {
575            Self::Resource(_) => TypeInfo::new(),
576            Self::Defined(id) => types[id].type_info(types),
577            Self::Func(id) => types[id].type_info(types),
578            Self::Instance(id) => types[id].type_info(types),
579            Self::Component(id) => types[id].type_info(types),
580        }
581    }
582
583    pub(crate) fn desc(&self) -> &'static str {
584        match self {
585            Self::Resource(_) => "resource",
586            Self::Defined(_) => "defined type",
587            Self::Func(_) => "func",
588            Self::Instance(_) => "instance",
589            Self::Component(_) => "component",
590        }
591    }
592}
593
594define_type_id!(
595    RecGroupId,
596    Range<CoreTypeId>,
597    rec_group_elements,
598    "recursion group"
599);
600
601impl TypeData for Range<CoreTypeId> {
602    type Id = RecGroupId;
603
604    fn type_info(&self, _types: &TypeList) -> TypeInfo {
605        let size = self.end.index() - self.start.index();
606        TypeInfo::core(u32::try_from(size).unwrap())
607    }
608}
609
610define_type_id!(ComponentTypeId, ComponentType, components, "component");
611
612define_type_id!(
613    ComponentValueTypeId,
614    ComponentValType,
615    component_values,
616    "component value"
617);
618
619define_type_id!(
620    ComponentInstanceTypeId,
621    ComponentInstanceType,
622    component_instances,
623    "component instance"
624);
625
626define_type_id!(
627    ComponentFuncTypeId,
628    ComponentFuncType,
629    component_funcs,
630    "component function"
631);
632
633define_type_id!(
634    ComponentCoreInstanceTypeId,
635    InstanceType,
636    core_instances,
637    "component's core instance"
638);
639
640define_type_id!(
641    ComponentCoreModuleTypeId,
642    ModuleType,
643    core_modules,
644    "component's core module"
645);
646
647/// Represents a unique identifier for a component type type known to a
648/// [`crate::Validator`].
649#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
650#[repr(C)]
651pub struct ComponentDefinedTypeId {
652    index: u32,
653    alias_id: u32,
654}
655
656const _: () = {
657    assert!(core::mem::size_of::<ComponentDefinedTypeId>() <= 8);
658};
659
660impl TypeIdentifier for ComponentDefinedTypeId {
661    type Data = ComponentDefinedType;
662
663    fn from_index(index: u32) -> Self {
664        ComponentDefinedTypeId {
665            index,
666            alias_id: NO_ALIAS,
667        }
668    }
669
670    fn list(types: &TypeList) -> &SnapshotList<Self::Data> {
671        &types.component_defined_types
672    }
673
674    fn list_mut(types: &mut TypeList) -> &mut SnapshotList<Self::Data> {
675        &mut types.component_defined_types
676    }
677
678    fn index(&self) -> usize {
679        usize::try_from(self.index).unwrap()
680    }
681}
682
683impl Aliasable for ComponentDefinedTypeId {
684    fn alias_id(&self) -> u32 {
685        self.alias_id
686    }
687
688    fn set_alias_id(&mut self, alias_id: u32) {
689        self.alias_id = alias_id;
690    }
691}
692
693/// Metadata about a type and its transitive structure.
694///
695/// Currently contains two properties:
696///
697/// * The "size" of a type - a proxy to the recursive size of a type if
698///   everything in the type were unique (e.g. no shared references). Not an
699///   approximation of runtime size, but instead of type-complexity size if
700///   someone were to visit each element of the type individually. For example
701///   `u32` has size 1 and `(list u32)` has size 2 (roughly). Used to prevent
702///   massive trees of types.
703///
704/// * Whether or not a type contains a "borrow" transitively inside of it. For
705///   example `(borrow $t)` and `(list (borrow $t))` both contain borrows, but
706///   `(list u32)` does not. Used to validate that component function results do
707///   not contain borrows.
708///
709/// Currently this is represented as a compact 32-bit integer to ensure that
710/// `TypeId`, which this is stored in, remains relatively small. The maximum
711/// type size allowed in wasmparser is 1M at this time which is 20 bits of
712/// information, and then one more bit is used for whether or not a borrow is
713/// used. Currently this uses the low 24 bits for the type size and the MSB for
714/// the borrow bit.
715#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
716// Only public because it shows up in a public trait's `doc(hidden)` method.
717#[doc(hidden)]
718pub struct TypeInfo(u32);
719
720impl TypeInfo {
721    /// Creates a new blank set of type information.
722    ///
723    /// Defaults to size 1 to ensure that this consumes space in the final type
724    /// structure.
725    pub(crate) fn new() -> TypeInfo {
726        TypeInfo::_new(1, false)
727    }
728
729    /// Creates a new blank set of information about a leaf "borrow" type which
730    /// has size 1.
731    pub(crate) fn borrow() -> TypeInfo {
732        TypeInfo::_new(1, true)
733    }
734
735    /// Creates type information corresponding to a core type of the `size`
736    /// specified, meaning no borrows are contained within.
737    pub(crate) fn core(size: u32) -> TypeInfo {
738        TypeInfo::_new(size, false)
739    }
740
741    fn _new(size: u32, contains_borrow: bool) -> TypeInfo {
742        assert!(size < (1 << 24));
743        TypeInfo(size | ((contains_borrow as u32) << 31))
744    }
745
746    /// Combines another set of type information into this one, for example if
747    /// this is a record which has `other` as a field.
748    ///
749    /// Updates the size of `self` and whether or not this type contains a
750    /// borrow based on whether `other` contains a borrow.
751    ///
752    /// Returns an error if the type size would exceed this crate's static limit
753    /// of a type size.
754    pub(crate) fn combine(&mut self, other: TypeInfo, offset: usize) -> Result<()> {
755        *self = TypeInfo::_new(
756            super::combine_type_sizes(self.size(), other.size(), offset)?,
757            self.contains_borrow() || other.contains_borrow(),
758        );
759        Ok(())
760    }
761
762    pub(crate) fn size(&self) -> u32 {
763        self.0 & 0xffffff
764    }
765
766    pub(crate) fn contains_borrow(&self) -> bool {
767        (self.0 >> 31) != 0
768    }
769}
770
771/// A component value type.
772#[derive(Debug, Clone, Copy)]
773pub enum ComponentValType {
774    /// The value type is one of the primitive types.
775    Primitive(PrimitiveValType),
776    /// The type is represented with the given type identifier.
777    Type(ComponentDefinedTypeId),
778}
779
780impl TypeData for ComponentValType {
781    type Id = ComponentValueTypeId;
782
783    fn type_info(&self, types: &TypeList) -> TypeInfo {
784        match self {
785            ComponentValType::Primitive(_) => TypeInfo::new(),
786            ComponentValType::Type(id) => types[*id].type_info(types),
787        }
788    }
789}
790
791impl ComponentValType {
792    pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
793        match self {
794            ComponentValType::Primitive(ty) => ty.contains_ptr(),
795            ComponentValType::Type(ty) => types[*ty].contains_ptr(types),
796        }
797    }
798
799    fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
800        match self {
801            Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
802            Self::Type(id) => types[*id].push_wasm_types(types, lowered_types),
803        }
804    }
805
806    pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
807        match self {
808            Self::Primitive(_) => TypeInfo::new(),
809            Self::Type(id) => types[*id].type_info(types),
810        }
811    }
812}
813
814/// The entity type for imports and exports of a module.
815#[derive(Debug, Clone, Copy)]
816pub enum EntityType {
817    /// The entity is a function.
818    Func(CoreTypeId),
819    /// The entity is a table.
820    Table(TableType),
821    /// The entity is a memory.
822    Memory(MemoryType),
823    /// The entity is a global.
824    Global(GlobalType),
825    /// The entity is a tag.
826    Tag(CoreTypeId),
827}
828
829impl EntityType {
830    pub(crate) fn desc(&self) -> &'static str {
831        match self {
832            Self::Func(_) => "func",
833            Self::Table(_) => "table",
834            Self::Memory(_) => "memory",
835            Self::Global(_) => "global",
836            Self::Tag(_) => "tag",
837        }
838    }
839
840    pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
841        match self {
842            Self::Func(id) | Self::Tag(id) => types[*id].type_info(types),
843            Self::Table(_) | Self::Memory(_) | Self::Global(_) => TypeInfo::new(),
844        }
845    }
846}
847
848trait ModuleImportKey {
849    fn module(&self) -> &str;
850    fn name(&self) -> &str;
851}
852
853impl<'a> Borrow<dyn ModuleImportKey + 'a> for (String, String) {
854    fn borrow(&self) -> &(dyn ModuleImportKey + 'a) {
855        self
856    }
857}
858
859impl Hash for (dyn ModuleImportKey + '_) {
860    fn hash<H: Hasher>(&self, state: &mut H) {
861        self.module().hash(state);
862        self.name().hash(state);
863    }
864}
865
866impl PartialEq for (dyn ModuleImportKey + '_) {
867    fn eq(&self, other: &Self) -> bool {
868        self.module() == other.module() && self.name() == other.name()
869    }
870}
871
872impl Eq for (dyn ModuleImportKey + '_) {}
873
874impl Ord for (dyn ModuleImportKey + '_) {
875    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
876        match self.module().cmp(other.module()) {
877            core::cmp::Ordering::Equal => (),
878            order => return order,
879        };
880        self.name().cmp(other.name())
881    }
882}
883
884impl PartialOrd for (dyn ModuleImportKey + '_) {
885    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
886        Some(self.cmp(other))
887    }
888}
889
890impl ModuleImportKey for (String, String) {
891    fn module(&self) -> &str {
892        &self.0
893    }
894
895    fn name(&self) -> &str {
896        &self.1
897    }
898}
899
900impl ModuleImportKey for (&str, &str) {
901    fn module(&self) -> &str {
902        self.0
903    }
904
905    fn name(&self) -> &str {
906        self.1
907    }
908}
909
910/// Represents a core module type.
911#[derive(Debug, Clone)]
912pub struct ModuleType {
913    /// Metadata about this module type
914    pub(crate) info: TypeInfo,
915    /// The imports of the module type.
916    pub imports: IndexMap<(String, String), EntityType>,
917    /// The exports of the module type.
918    pub exports: IndexMap<String, EntityType>,
919}
920
921impl TypeData for ModuleType {
922    type Id = ComponentCoreModuleTypeId;
923
924    fn type_info(&self, _types: &TypeList) -> TypeInfo {
925        self.info
926    }
927}
928
929impl ModuleType {
930    /// Looks up an import by its module and name.
931    ///
932    /// Returns `None` if the import was not found.
933    pub fn lookup_import(&self, module: &str, name: &str) -> Option<&EntityType> {
934        self.imports.get(&(module, name) as &dyn ModuleImportKey)
935    }
936}
937
938/// Represents the kind of module instance type.
939#[derive(Debug, Clone)]
940pub enum CoreInstanceTypeKind {
941    /// The instance type is the result of instantiating a module type.
942    Instantiated(ComponentCoreModuleTypeId),
943
944    /// The instance type is the result of instantiating from exported items.
945    Exports(IndexMap<String, EntityType>),
946}
947
948/// Represents a module instance type.
949#[derive(Debug, Clone)]
950pub struct InstanceType {
951    /// Metadata about this instance type
952    pub(crate) info: TypeInfo,
953    /// The kind of module instance type.
954    pub kind: CoreInstanceTypeKind,
955}
956
957impl TypeData for InstanceType {
958    type Id = ComponentCoreInstanceTypeId;
959
960    fn type_info(&self, _types: &TypeList) -> TypeInfo {
961        self.info
962    }
963}
964
965impl InstanceType {
966    /// Gets the exports of the instance type.
967    pub fn exports<'a>(&'a self, types: TypesRef<'a>) -> &'a IndexMap<String, EntityType> {
968        self.internal_exports(types.list)
969    }
970
971    pub(crate) fn internal_exports<'a>(
972        &'a self,
973        types: &'a TypeList,
974    ) -> &'a IndexMap<String, EntityType> {
975        match &self.kind {
976            CoreInstanceTypeKind::Instantiated(id) => &types[*id].exports,
977            CoreInstanceTypeKind::Exports(exports) => exports,
978        }
979    }
980}
981
982/// The entity type for imports and exports of a component.
983#[derive(Debug, Clone, Copy)]
984pub enum ComponentEntityType {
985    /// The entity is a core module.
986    Module(ComponentCoreModuleTypeId),
987    /// The entity is a function.
988    Func(ComponentFuncTypeId),
989    /// The entity is a value.
990    Value(ComponentValType),
991    /// The entity is a type.
992    Type {
993        /// This is the identifier of the type that was referenced when this
994        /// entity was created.
995        referenced: ComponentAnyTypeId,
996        /// This is the identifier of the type that was created when this type
997        /// was imported or exported from the component.
998        ///
999        /// Note that the underlying type information for the `referenced`
1000        /// field and for this `created` field is the same, but these two types
1001        /// will hash to different values.
1002        created: ComponentAnyTypeId,
1003    },
1004    /// The entity is a component instance.
1005    Instance(ComponentInstanceTypeId),
1006    /// The entity is a component.
1007    Component(ComponentTypeId),
1008}
1009
1010impl ComponentEntityType {
1011    /// Determines if component entity type `a` is a subtype of `b`.
1012    pub fn is_subtype_of(a: &Self, at: TypesRef, b: &Self, bt: TypesRef) -> bool {
1013        SubtypeCx::new(at.list, bt.list)
1014            .component_entity_type(a, b, 0)
1015            .is_ok()
1016    }
1017
1018    pub(crate) fn desc(&self) -> &'static str {
1019        match self {
1020            Self::Module(_) => "module",
1021            Self::Func(_) => "func",
1022            Self::Value(_) => "value",
1023            Self::Type { .. } => "type",
1024            Self::Instance(_) => "instance",
1025            Self::Component(_) => "component",
1026        }
1027    }
1028
1029    pub(crate) fn info(&self, types: &TypeList) -> TypeInfo {
1030        match self {
1031            Self::Module(ty) => types[*ty].type_info(types),
1032            Self::Func(ty) => types[*ty].type_info(types),
1033            Self::Type { referenced: ty, .. } => ty.info(types),
1034            Self::Instance(ty) => types[*ty].type_info(types),
1035            Self::Component(ty) => types[*ty].type_info(types),
1036            Self::Value(ty) => ty.info(types),
1037        }
1038    }
1039}
1040
1041/// Represents a type of a component.
1042#[derive(Debug, Clone)]
1043pub struct ComponentType {
1044    /// Metadata about this component type
1045    pub(crate) info: TypeInfo,
1046
1047    /// The imports of the component type.
1048    ///
1049    /// Each import has its own kebab-name and an optional URL listed. Note that
1050    /// the set of import names is disjoint with the set of export names.
1051    pub imports: IndexMap<String, ComponentEntityType>,
1052
1053    /// The exports of the component type.
1054    ///
1055    /// Each export has its own kebab-name and an optional URL listed. Note that
1056    /// the set of export names is disjoint with the set of import names.
1057    pub exports: IndexMap<String, ComponentEntityType>,
1058
1059    /// Universally quantified resources required to be provided when
1060    /// instantiating this component type.
1061    ///
1062    /// Each resource in this map is explicitly imported somewhere in the
1063    /// `imports` map. The "path" to where it's imported is specified by the
1064    /// `Vec<usize>` payload here. For more information about the indexes see
1065    /// the documentation on `ComponentState::imported_resources`.
1066    ///
1067    /// This should technically be inferrable from the structure of `imports`,
1068    /// but it's stored as an auxiliary set for subtype checking and
1069    /// instantiation.
1070    ///
1071    /// Note that this is not a set of all resources referred to by the
1072    /// `imports`. Instead it's only those created, relative to the internals of
1073    /// this component, by the imports.
1074    pub imported_resources: Vec<(ResourceId, Vec<usize>)>,
1075
1076    /// The dual of the `imported_resources`, or the set of defined
1077    /// resources -- those created through the instantiation process which are
1078    /// unique to this component.
1079    ///
1080    /// This set is similar to the `imported_resources` set but it's those
1081    /// contained within the `exports`. Instantiating this component will
1082    /// create fresh new versions of all of these resources. The path here is
1083    /// within the `exports` array.
1084    pub defined_resources: Vec<(ResourceId, Vec<usize>)>,
1085
1086    /// The set of all resources which are explicitly exported by this
1087    /// component, and where they're exported.
1088    ///
1089    /// This mapping is stored separately from `defined_resources` to ensure
1090    /// that it contains all exported resources, not just those which are
1091    /// defined. That means that this can cover reexports of imported
1092    /// resources, exports of local resources, or exports of closed-over
1093    /// resources for example.
1094    pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
1095}
1096
1097impl TypeData for ComponentType {
1098    type Id = ComponentTypeId;
1099
1100    fn type_info(&self, _types: &TypeList) -> TypeInfo {
1101        self.info
1102    }
1103}
1104
1105/// Represents a type of a component instance.
1106#[derive(Debug, Clone)]
1107pub struct ComponentInstanceType {
1108    /// Metadata about this instance type
1109    pub(crate) info: TypeInfo,
1110
1111    /// The list of exports, keyed by name, that this instance has.
1112    ///
1113    /// An optional URL and type of each export is provided as well.
1114    pub exports: IndexMap<String, ComponentEntityType>,
1115
1116    /// The list of "defined resources" or those which are closed over in
1117    /// this instance type.
1118    ///
1119    /// This list is populated, for example, when the type of an instance is
1120    /// declared and it contains its own resource type exports defined
1121    /// internally. For example:
1122    ///
1123    /// ```wasm
1124    /// (component
1125    ///     (type (instance
1126    ///         (export "x" (type sub resource)) ;; one `defined_resources` entry
1127    ///     ))
1128    /// )
1129    /// ```
1130    ///
1131    /// This list is also a bit of an oddity, however, because the type of a
1132    /// concrete instance will always have this as empty. For example:
1133    ///
1134    /// ```wasm
1135    /// (component
1136    ///     (type $t (instance (export "x" (type sub resource))))
1137    ///
1138    ///     ;; the type of this instance has no defined resources
1139    ///     (import "i" (instance (type $t)))
1140    /// )
1141    /// ```
1142    ///
1143    /// This list ends up only being populated for instance types declared in a
1144    /// module which aren't yet "attached" to anything. Once something is
1145    /// instantiated, imported, exported, or otherwise refers to a concrete
1146    /// instance then this list is always empty. For concrete instances
1147    /// defined resources are tracked in the component state or component type.
1148    pub defined_resources: Vec<ResourceId>,
1149
1150    /// The list of all resources that are explicitly exported from this
1151    /// instance type along with the path they're exported at.
1152    pub explicit_resources: IndexMap<ResourceId, Vec<usize>>,
1153}
1154
1155impl TypeData for ComponentInstanceType {
1156    type Id = ComponentInstanceTypeId;
1157
1158    fn type_info(&self, _types: &TypeList) -> TypeInfo {
1159        self.info
1160    }
1161}
1162
1163/// Represents a type of a component function.
1164#[derive(Debug, Clone)]
1165pub struct ComponentFuncType {
1166    /// Metadata about this function type.
1167    pub(crate) info: TypeInfo,
1168    /// The function parameters.
1169    pub params: Box<[(KebabString, ComponentValType)]>,
1170    /// The function's results.
1171    pub results: Box<[(Option<KebabString>, ComponentValType)]>,
1172}
1173
1174impl TypeData for ComponentFuncType {
1175    type Id = ComponentFuncTypeId;
1176
1177    fn type_info(&self, _types: &TypeList) -> TypeInfo {
1178        self.info
1179    }
1180}
1181
1182impl ComponentFuncType {
1183    /// Lowers the component function type to core parameter and result types for the
1184    /// canonical ABI.
1185    pub(crate) fn lower(&self, types: &TypeList, is_lower: bool) -> LoweringInfo {
1186        let mut info = LoweringInfo::default();
1187
1188        for (_, ty) in self.params.iter() {
1189            // Check to see if `ty` has a pointer somewhere in it, needed for
1190            // any type that transitively contains either a string or a list.
1191            // In this situation lowered functions must specify `memory`, and
1192            // lifted functions must specify `realloc` as well. Lifted functions
1193            // gain their memory requirement through the final clause of this
1194            // function.
1195            if is_lower {
1196                if !info.requires_memory {
1197                    info.requires_memory = ty.contains_ptr(types);
1198                }
1199            } else {
1200                if !info.requires_realloc {
1201                    info.requires_realloc = ty.contains_ptr(types);
1202                }
1203            }
1204
1205            if !ty.push_wasm_types(types, &mut info.params) {
1206                // Too many parameters to pass directly
1207                // Function will have a single pointer parameter to pass the arguments
1208                // via linear memory
1209                info.params.clear();
1210                assert!(info.params.push(ValType::I32));
1211                info.requires_memory = true;
1212
1213                // We need realloc as well when lifting a function
1214                if !is_lower {
1215                    info.requires_realloc = true;
1216                }
1217                break;
1218            }
1219        }
1220
1221        for (_, ty) in self.results.iter() {
1222            // Results of lowered functions that contains pointers must be
1223            // allocated by the callee meaning that realloc is required.
1224            // Results of lifted function are allocated by the guest which
1225            // means that no realloc option is necessary.
1226            if is_lower && !info.requires_realloc {
1227                info.requires_realloc = ty.contains_ptr(types);
1228            }
1229
1230            if !ty.push_wasm_types(types, &mut info.results) {
1231                // Too many results to return directly, either a retptr parameter will be used (import)
1232                // or a single pointer will be returned (export)
1233                info.results.clear();
1234                if is_lower {
1235                    info.params.max = MAX_LOWERED_TYPES;
1236                    assert!(info.params.push(ValType::I32));
1237                } else {
1238                    assert!(info.results.push(ValType::I32));
1239                }
1240                info.requires_memory = true;
1241                break;
1242            }
1243        }
1244
1245        // Memory is always required when realloc is required
1246        info.requires_memory |= info.requires_realloc;
1247
1248        info
1249    }
1250}
1251
1252/// Represents a variant case.
1253#[derive(Debug, Clone)]
1254pub struct VariantCase {
1255    /// The variant case type.
1256    pub ty: Option<ComponentValType>,
1257    /// The name of the variant case refined by this one.
1258    pub refines: Option<KebabString>,
1259}
1260
1261/// Represents a record type.
1262#[derive(Debug, Clone)]
1263pub struct RecordType {
1264    /// Metadata about this record type.
1265    pub(crate) info: TypeInfo,
1266    /// The map of record fields.
1267    pub fields: IndexMap<KebabString, ComponentValType>,
1268}
1269
1270/// Represents a variant type.
1271#[derive(Debug, Clone)]
1272pub struct VariantType {
1273    /// Metadata about this variant type.
1274    pub(crate) info: TypeInfo,
1275    /// The map of variant cases.
1276    pub cases: IndexMap<KebabString, VariantCase>,
1277}
1278
1279/// Represents a tuple type.
1280#[derive(Debug, Clone)]
1281pub struct TupleType {
1282    /// Metadata about this tuple type.
1283    pub(crate) info: TypeInfo,
1284    /// The types of the tuple.
1285    pub types: Box<[ComponentValType]>,
1286}
1287
1288/// Represents a component defined type.
1289#[derive(Debug, Clone)]
1290pub enum ComponentDefinedType {
1291    /// The type is a primitive value type.
1292    Primitive(PrimitiveValType),
1293    /// The type is a record.
1294    Record(RecordType),
1295    /// The type is a variant.
1296    Variant(VariantType),
1297    /// The type is a list.
1298    List(ComponentValType),
1299    /// The type is a tuple.
1300    Tuple(TupleType),
1301    /// The type is a set of flags.
1302    Flags(IndexSet<KebabString>),
1303    /// The type is an enumeration.
1304    Enum(IndexSet<KebabString>),
1305    /// The type is an `option`.
1306    Option(ComponentValType),
1307    /// The type is a `result`.
1308    Result {
1309        /// The `ok` type.
1310        ok: Option<ComponentValType>,
1311        /// The `error` type.
1312        err: Option<ComponentValType>,
1313    },
1314    /// The type is an owned handle to the specified resource.
1315    Own(AliasableResourceId),
1316    /// The type is a borrowed handle to the specified resource.
1317    Borrow(AliasableResourceId),
1318}
1319
1320impl TypeData for ComponentDefinedType {
1321    type Id = ComponentDefinedTypeId;
1322
1323    fn type_info(&self, types: &TypeList) -> TypeInfo {
1324        match self {
1325            Self::Primitive(_) | Self::Flags(_) | Self::Enum(_) | Self::Own(_) => TypeInfo::new(),
1326            Self::Borrow(_) => TypeInfo::borrow(),
1327            Self::Record(r) => r.info,
1328            Self::Variant(v) => v.info,
1329            Self::Tuple(t) => t.info,
1330            Self::List(ty) | Self::Option(ty) => ty.info(types),
1331            Self::Result { ok, err } => {
1332                let default = TypeInfo::new();
1333                let mut info = ok.map(|ty| ty.type_info(types)).unwrap_or(default);
1334                info.combine(err.map(|ty| ty.type_info(types)).unwrap_or(default), 0)
1335                    .unwrap();
1336                info
1337            }
1338        }
1339    }
1340}
1341
1342impl ComponentDefinedType {
1343    pub(crate) fn contains_ptr(&self, types: &TypeList) -> bool {
1344        match self {
1345            Self::Primitive(ty) => ty.contains_ptr(),
1346            Self::Record(r) => r.fields.values().any(|ty| ty.contains_ptr(types)),
1347            Self::Variant(v) => v
1348                .cases
1349                .values()
1350                .any(|case| case.ty.map(|ty| ty.contains_ptr(types)).unwrap_or(false)),
1351            Self::List(_) => true,
1352            Self::Tuple(t) => t.types.iter().any(|ty| ty.contains_ptr(types)),
1353            Self::Flags(_) | Self::Enum(_) | Self::Own(_) | Self::Borrow(_) => false,
1354            Self::Option(ty) => ty.contains_ptr(types),
1355            Self::Result { ok, err } => {
1356                ok.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1357                    || err.map(|ty| ty.contains_ptr(types)).unwrap_or(false)
1358            }
1359        }
1360    }
1361
1362    fn push_wasm_types(&self, types: &TypeList, lowered_types: &mut LoweredTypes) -> bool {
1363        match self {
1364            Self::Primitive(ty) => push_primitive_wasm_types(ty, lowered_types),
1365            Self::Record(r) => r
1366                .fields
1367                .iter()
1368                .all(|(_, ty)| ty.push_wasm_types(types, lowered_types)),
1369            Self::Variant(v) => Self::push_variant_wasm_types(
1370                v.cases.iter().filter_map(|(_, case)| case.ty.as_ref()),
1371                types,
1372                lowered_types,
1373            ),
1374            Self::List(_) => lowered_types.push(ValType::I32) && lowered_types.push(ValType::I32),
1375            Self::Tuple(t) => t
1376                .types
1377                .iter()
1378                .all(|ty| ty.push_wasm_types(types, lowered_types)),
1379            Self::Flags(names) => {
1380                (0..(names.len() + 31) / 32).all(|_| lowered_types.push(ValType::I32))
1381            }
1382            Self::Enum(_) | Self::Own(_) | Self::Borrow(_) => lowered_types.push(ValType::I32),
1383            Self::Option(ty) => {
1384                Self::push_variant_wasm_types([ty].into_iter(), types, lowered_types)
1385            }
1386            Self::Result { ok, err } => {
1387                Self::push_variant_wasm_types(ok.iter().chain(err.iter()), types, lowered_types)
1388            }
1389        }
1390    }
1391
1392    fn push_variant_wasm_types<'a>(
1393        cases: impl Iterator<Item = &'a ComponentValType>,
1394        types: &TypeList,
1395        lowered_types: &mut LoweredTypes,
1396    ) -> bool {
1397        // Push the discriminant
1398        if !lowered_types.push(ValType::I32) {
1399            return false;
1400        }
1401
1402        let start = lowered_types.len();
1403
1404        for ty in cases {
1405            let mut temp = LoweredTypes::new(lowered_types.max);
1406
1407            if !ty.push_wasm_types(types, &mut temp) {
1408                return false;
1409            }
1410
1411            for (i, ty) in temp.iter().enumerate() {
1412                match lowered_types.get_mut(start + i) {
1413                    Some(prev) => *prev = Self::join_types(*prev, ty),
1414                    None => {
1415                        if !lowered_types.push(ty) {
1416                            return false;
1417                        }
1418                    }
1419                }
1420            }
1421        }
1422
1423        true
1424    }
1425
1426    fn join_types(a: ValType, b: ValType) -> ValType {
1427        use ValType::*;
1428
1429        match (a, b) {
1430            (I32, I32) | (I64, I64) | (F32, F32) | (F64, F64) => a,
1431            (I32, F32) | (F32, I32) => I32,
1432            (_, I64 | F64) | (I64 | F64, _) => I64,
1433            _ => panic!("unexpected wasm type for canonical ABI"),
1434        }
1435    }
1436
1437    fn desc(&self) -> &'static str {
1438        match self {
1439            ComponentDefinedType::Record(_) => "record",
1440            ComponentDefinedType::Primitive(_) => "primitive",
1441            ComponentDefinedType::Variant(_) => "variant",
1442            ComponentDefinedType::Tuple(_) => "tuple",
1443            ComponentDefinedType::Enum(_) => "enum",
1444            ComponentDefinedType::Flags(_) => "flags",
1445            ComponentDefinedType::Option(_) => "option",
1446            ComponentDefinedType::List(_) => "list",
1447            ComponentDefinedType::Result { .. } => "result",
1448            ComponentDefinedType::Own(_) => "own",
1449            ComponentDefinedType::Borrow(_) => "borrow",
1450        }
1451    }
1452}
1453
1454/// An opaque identifier intended to be used to distinguish whether two
1455/// resource types are equivalent or not.
1456#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Copy)]
1457#[repr(packed(4))] // try to not waste 4 bytes in padding
1458pub struct ResourceId {
1459    // This is a globally unique identifier which is assigned once per
1460    // `TypeAlloc`. This ensures that resource identifiers from different
1461    // instances of `Types`, for example, are considered unique.
1462    //
1463    // Technically 64-bits should be enough for all resource ids ever, but
1464    // they're allocated so often it's predicted that an atomic increment
1465    // per resource id is probably too expensive. To amortize that cost each
1466    // top-level wasm component gets a single globally unique identifier, and
1467    // then within a component contextually unique identifiers are handed out.
1468    globally_unique_id: usize,
1469
1470    // A contextually unique id within the globally unique id above. This is
1471    // allocated within a `TypeAlloc` with its own counter, and allocations of
1472    // this are cheap as nothing atomic is required.
1473    //
1474    // The 32-bit storage here should ideally be enough for any component
1475    // containing resources. If memory usage becomes an issue (this struct is
1476    // 12 bytes instead of 8 or 4) then this could get folded into the globally
1477    // unique id with everything using an atomic increment perhaps.
1478    contextually_unique_id: u32,
1479}
1480
1481#[allow(clippy::large_enum_variant)]
1482enum TypesKind {
1483    Module(Arc<Module>),
1484    Component(ComponentState),
1485}
1486
1487/// Represents the types known to a [`crate::Validator`] once validation has completed.
1488///
1489/// The type information is returned via the [`crate::Validator::end`] method.
1490pub struct Types {
1491    id: ValidatorId,
1492    list: TypeList,
1493    kind: TypesKind,
1494}
1495
1496#[derive(Clone, Copy)]
1497enum TypesRefKind<'a> {
1498    Module(&'a Module),
1499    Component(&'a ComponentState),
1500}
1501
1502/// Represents the types known to a [`crate::Validator`] during validation.
1503///
1504/// Retrieved via the [`crate::Validator::types`] method.
1505#[derive(Clone, Copy)]
1506pub struct TypesRef<'a> {
1507    id: ValidatorId,
1508    list: &'a TypeList,
1509    kind: TypesRefKind<'a>,
1510}
1511
1512impl<'a> TypesRef<'a> {
1513    pub(crate) fn from_module(id: ValidatorId, types: &'a TypeList, module: &'a Module) -> Self {
1514        Self {
1515            id,
1516            list: types,
1517            kind: TypesRefKind::Module(module),
1518        }
1519    }
1520
1521    pub(crate) fn from_component(
1522        id: ValidatorId,
1523        types: &'a TypeList,
1524        component: &'a ComponentState,
1525    ) -> Self {
1526        Self {
1527            id,
1528            list: types,
1529            kind: TypesRefKind::Component(component),
1530        }
1531    }
1532
1533    /// Get the id of the validator that these types are associated with.
1534    #[inline]
1535    pub fn id(&self) -> ValidatorId {
1536        self.id
1537    }
1538
1539    /// Gets a type based on its type id.
1540    ///
1541    /// Returns `None` if the type id is unknown.
1542    pub fn get<T>(&self, id: T) -> Option<&'a T::Data>
1543    where
1544        T: TypeIdentifier,
1545    {
1546        self.list.get(id)
1547    }
1548
1549    /// Get the id of the rec group that the given type id was defined within.
1550    pub fn rec_group_id_of(&self, id: CoreTypeId) -> RecGroupId {
1551        self.list.rec_group_id_of(id)
1552    }
1553
1554    /// Get the types within a rec group.
1555    pub fn rec_group_elements(&self, id: RecGroupId) -> impl ExactSizeIterator<Item = CoreTypeId> {
1556        let range = &self.list.rec_group_elements[id];
1557        (range.start.index..range.end.index).map(|index| CoreTypeId { index })
1558    }
1559
1560    /// Get the super type of the given type id, if any.
1561    pub fn supertype_of(&self, id: CoreTypeId) -> Option<CoreTypeId> {
1562        self.list.supertype_of(id)
1563    }
1564
1565    /// Gets a core WebAssembly type id from a type index.
1566    ///
1567    /// Note that this is in contrast to [`TypesRef::component_type_at`] which
1568    /// gets a component type from its index.
1569    ///
1570    /// # Panics
1571    ///
1572    /// This will panic if the `index` provided is out of bounds.
1573    pub fn core_type_at(&self, index: u32) -> ComponentCoreTypeId {
1574        match &self.kind {
1575            TypesRefKind::Module(module) => ComponentCoreTypeId::Sub(module.types[index as usize]),
1576            TypesRefKind::Component(component) => component.core_types[index as usize],
1577        }
1578    }
1579
1580    /// Gets a type id from a type index.
1581    ///
1582    /// # Panics
1583    ///
1584    /// Panics if `index` is not a valid type index or if this type information
1585    /// represents a core module.
1586    pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
1587        match &self.kind {
1588            TypesRefKind::Module(_) => panic!("not a component"),
1589            TypesRefKind::Component(component) => component.types[index as usize],
1590        }
1591    }
1592
1593    /// Gets a component type id from a type index.
1594    ///
1595    /// # Panics
1596    ///
1597    /// Panics if `index` is not a valid component type index or if this type
1598    /// information represents a core module.
1599    pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
1600        match self.component_any_type_at(index) {
1601            ComponentAnyTypeId::Component(id) => id,
1602            _ => panic!("not a component type"),
1603        }
1604    }
1605
1606    /// Gets a type id from a type index.
1607    ///
1608    /// # Panics
1609    ///
1610    /// Panics if `index` is not a valid function index or if this type
1611    /// information represents a core module.
1612    pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
1613        match self.component_any_type_at(index) {
1614            ComponentAnyTypeId::Defined(id) => id,
1615            _ => panic!("not a defined type"),
1616        }
1617    }
1618
1619    /// Returns the number of core types defined so far.
1620    pub fn core_type_count(&self) -> u32 {
1621        match &self.kind {
1622            TypesRefKind::Module(module) => module.types.len() as u32,
1623            TypesRefKind::Component(component) => component.core_types.len() as u32,
1624        }
1625    }
1626
1627    /// Returns the number of component types defined so far.
1628    pub fn component_type_count(&self) -> u32 {
1629        match &self.kind {
1630            TypesRefKind::Module(_module) => 0,
1631            TypesRefKind::Component(component) => component.types.len() as u32,
1632        }
1633    }
1634
1635    /// Gets the type of a table at the given table index.
1636    ///
1637    /// # Panics
1638    ///
1639    /// This will panic if the `index` provided is out of bounds.
1640    pub fn table_at(&self, index: u32) -> TableType {
1641        let tables = match &self.kind {
1642            TypesRefKind::Module(module) => &module.tables,
1643            TypesRefKind::Component(component) => &component.core_tables,
1644        };
1645        tables[index as usize]
1646    }
1647
1648    /// Returns the number of tables defined so far.
1649    pub fn table_count(&self) -> u32 {
1650        match &self.kind {
1651            TypesRefKind::Module(module) => module.tables.len() as u32,
1652            TypesRefKind::Component(component) => component.core_tables.len() as u32,
1653        }
1654    }
1655
1656    /// Gets the type of a memory at the given memory index.
1657    ///
1658    /// # Panics
1659    ///
1660    /// This will panic if the `index` provided is out of bounds.
1661    pub fn memory_at(&self, index: u32) -> MemoryType {
1662        let memories = match &self.kind {
1663            TypesRefKind::Module(module) => &module.memories,
1664            TypesRefKind::Component(component) => &component.core_memories,
1665        };
1666
1667        memories[index as usize]
1668    }
1669
1670    /// Returns the number of memories defined so far.
1671    pub fn memory_count(&self) -> u32 {
1672        match &self.kind {
1673            TypesRefKind::Module(module) => module.memories.len() as u32,
1674            TypesRefKind::Component(component) => component.core_memories.len() as u32,
1675        }
1676    }
1677
1678    /// Gets the type of a global at the given global index.
1679    ///
1680    /// # Panics
1681    ///
1682    /// This will panic if the `index` provided is out of bounds.
1683    pub fn global_at(&self, index: u32) -> GlobalType {
1684        let globals = match &self.kind {
1685            TypesRefKind::Module(module) => &module.globals,
1686            TypesRefKind::Component(component) => &component.core_globals,
1687        };
1688
1689        globals[index as usize]
1690    }
1691
1692    /// Returns the number of globals defined so far.
1693    pub fn global_count(&self) -> u32 {
1694        match &self.kind {
1695            TypesRefKind::Module(module) => module.globals.len() as u32,
1696            TypesRefKind::Component(component) => component.core_globals.len() as u32,
1697        }
1698    }
1699
1700    /// Gets the type of a tag at the given tag index.
1701    ///
1702    /// # Panics
1703    ///
1704    /// This will panic if the `index` provided is out of bounds.
1705    pub fn tag_at(&self, index: u32) -> CoreTypeId {
1706        let tags = match &self.kind {
1707            TypesRefKind::Module(module) => &module.tags,
1708            TypesRefKind::Component(component) => &component.core_tags,
1709        };
1710        tags[index as usize]
1711    }
1712
1713    /// Returns the number of tags defined so far.
1714    pub fn tag_count(&self) -> u32 {
1715        match &self.kind {
1716            TypesRefKind::Module(module) => module.tags.len() as u32,
1717            TypesRefKind::Component(component) => component.core_tags.len() as u32,
1718        }
1719    }
1720
1721    /// Gets the type of a core function at the given function index.
1722    ///
1723    /// # Panics
1724    ///
1725    /// This will panic if the `index` provided is out of bounds.
1726    pub fn core_function_at(&self, index: u32) -> CoreTypeId {
1727        match &self.kind {
1728            TypesRefKind::Module(module) => module.types[module.functions[index as usize] as usize],
1729            TypesRefKind::Component(component) => component.core_funcs[index as usize],
1730        }
1731    }
1732
1733    /// Gets the count of core functions defined so far.
1734    ///
1735    /// Note that this includes imported functions, defined functions, and for
1736    /// components lowered/aliased functions.
1737    pub fn function_count(&self) -> u32 {
1738        match &self.kind {
1739            TypesRefKind::Module(module) => module.functions.len() as u32,
1740            TypesRefKind::Component(component) => component.core_funcs.len() as u32,
1741        }
1742    }
1743
1744    /// Gets the type of an element segment at the given element segment index.
1745    ///
1746    /// # Panics
1747    ///
1748    /// This will panic if the `index` provided is out of bounds.
1749    pub fn element_at(&self, index: u32) -> RefType {
1750        match &self.kind {
1751            TypesRefKind::Module(module) => module.element_types[index as usize],
1752            TypesRefKind::Component(_) => {
1753                panic!("no elements on a component")
1754            }
1755        }
1756    }
1757
1758    /// Returns the number of elements defined so far.
1759    pub fn element_count(&self) -> u32 {
1760        match &self.kind {
1761            TypesRefKind::Module(module) => module.element_types.len() as u32,
1762            TypesRefKind::Component(_) => 0,
1763        }
1764    }
1765
1766    /// Gets the type of a component function at the given function index.
1767    ///
1768    /// # Panics
1769    ///
1770    /// This will panic if the `index` provided is out of bounds or if this type
1771    /// information represents a core module.
1772    pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
1773        match &self.kind {
1774            TypesRefKind::Module(_) => panic!("not a component"),
1775            TypesRefKind::Component(component) => component.funcs[index as usize],
1776        }
1777    }
1778
1779    /// Returns the number of component functions defined so far.
1780    pub fn component_function_count(&self) -> u32 {
1781        match &self.kind {
1782            TypesRefKind::Module(_module) => 0,
1783            TypesRefKind::Component(component) => component.funcs.len() as u32,
1784        }
1785    }
1786
1787    /// Gets the type of a module at the given module index.
1788    ///
1789    /// # Panics
1790    ///
1791    /// This will panic if the `index` provided is out of bounds or if this type
1792    /// information represents a core module.
1793    pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
1794        match &self.kind {
1795            TypesRefKind::Module(_) => panic!("not a component"),
1796            TypesRefKind::Component(component) => component.core_modules[index as usize],
1797        }
1798    }
1799
1800    /// Returns the number of core wasm modules defined so far.
1801    pub fn module_count(&self) -> u32 {
1802        match &self.kind {
1803            TypesRefKind::Module(_module) => 0,
1804            TypesRefKind::Component(component) => component.core_modules.len() as u32,
1805        }
1806    }
1807
1808    /// Gets the type of a module instance at the given module instance index.
1809    ///
1810    /// # Panics
1811    ///
1812    /// This will panic if the `index` provided is out of bounds or if this type
1813    /// information represents a core module.
1814    pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
1815        match &self.kind {
1816            TypesRefKind::Module(_) => panic!("not a component"),
1817            TypesRefKind::Component(component) => component.core_instances[index as usize],
1818        }
1819    }
1820
1821    /// Returns the number of core wasm instances defined so far.
1822    pub fn core_instance_count(&self) -> u32 {
1823        match &self.kind {
1824            TypesRefKind::Module(_module) => 0,
1825            TypesRefKind::Component(component) => component.core_instances.len() as u32,
1826        }
1827    }
1828
1829    /// Gets the type of a component at the given component index.
1830    ///
1831    /// # Panics
1832    ///
1833    /// This will panic if the `index` provided is out of bounds or if this type
1834    /// information represents a core module.
1835    pub fn component_at(&self, index: u32) -> ComponentTypeId {
1836        match &self.kind {
1837            TypesRefKind::Module(_) => panic!("not a component"),
1838            TypesRefKind::Component(component) => component.components[index as usize],
1839        }
1840    }
1841
1842    /// Returns the number of components defined so far.
1843    pub fn component_count(&self) -> u32 {
1844        match &self.kind {
1845            TypesRefKind::Module(_module) => 0,
1846            TypesRefKind::Component(component) => component.components.len() as u32,
1847        }
1848    }
1849
1850    /// Gets the type of an component instance at the given component instance index.
1851    ///
1852    /// # Panics
1853    ///
1854    /// This will panic if the `index` provided is out of bounds or if this type
1855    /// information represents a core module.
1856    pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
1857        match &self.kind {
1858            TypesRefKind::Module(_) => panic!("not a component"),
1859            TypesRefKind::Component(component) => component.instances[index as usize],
1860        }
1861    }
1862
1863    /// Returns the number of component instances defined so far.
1864    pub fn component_instance_count(&self) -> u32 {
1865        match &self.kind {
1866            TypesRefKind::Module(_module) => 0,
1867            TypesRefKind::Component(component) => component.instances.len() as u32,
1868        }
1869    }
1870
1871    /// Gets the type of a value at the given value index.
1872    ///
1873    /// # Panics
1874    ///
1875    /// This will panic if the `index` provided is out of bounds or if this type
1876    /// information represents a core module.
1877    pub fn value_at(&self, index: u32) -> ComponentValType {
1878        match &self.kind {
1879            TypesRefKind::Module(_) => panic!("not a component"),
1880            TypesRefKind::Component(component) => component.values[index as usize].0,
1881        }
1882    }
1883
1884    /// Gets the entity type for the given import.
1885    pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
1886        match &self.kind {
1887            TypesRefKind::Module(module) => Some(match import.ty {
1888                TypeRef::Func(idx) => EntityType::Func(*module.types.get(idx as usize)?),
1889                TypeRef::Table(ty) => EntityType::Table(ty),
1890                TypeRef::Memory(ty) => EntityType::Memory(ty),
1891                TypeRef::Global(ty) => EntityType::Global(ty),
1892                TypeRef::Tag(ty) => EntityType::Tag(*module.types.get(ty.func_type_idx as usize)?),
1893            }),
1894            TypesRefKind::Component(_) => None,
1895        }
1896    }
1897
1898    /// Gets the entity type from the given export.
1899    pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
1900        match &self.kind {
1901            TypesRefKind::Module(module) => Some(match export.kind {
1902                ExternalKind::Func => EntityType::Func(
1903                    module.types[*module.functions.get(export.index as usize)? as usize],
1904                ),
1905                ExternalKind::Table => {
1906                    EntityType::Table(*module.tables.get(export.index as usize)?)
1907                }
1908                ExternalKind::Memory => {
1909                    EntityType::Memory(*module.memories.get(export.index as usize)?)
1910                }
1911                ExternalKind::Global => {
1912                    EntityType::Global(*module.globals.get(export.index as usize)?)
1913                }
1914                ExternalKind::Tag => EntityType::Tag(
1915                    module.types[*module.functions.get(export.index as usize)? as usize],
1916                ),
1917            }),
1918            TypesRefKind::Component(_) => None,
1919        }
1920    }
1921
1922    /// Gets the component entity type for the given component import.
1923    pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
1924        match &self.kind {
1925            TypesRefKind::Module(_) => None,
1926            TypesRefKind::Component(component) => Some(*component.imports.get(name)?),
1927        }
1928    }
1929
1930    /// Gets the component entity type for the given component export.
1931    pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
1932        match &self.kind {
1933            TypesRefKind::Module(_) => None,
1934            TypesRefKind::Component(component) => Some(*component.exports.get(name)?),
1935        }
1936    }
1937
1938    /// Attempts to lookup the type id that `ty` is an alias of.
1939    ///
1940    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
1941    pub fn peel_alias<T>(&self, ty: T) -> Option<T>
1942    where
1943        T: Aliasable,
1944    {
1945        self.list.peel_alias(ty)
1946    }
1947
1948    /// Returns an iterator over the core wasm imports found.
1949    ///
1950    /// Returns `None` if this type information is for a component.
1951    pub fn core_imports(
1952        &self,
1953    ) -> Option<impl Iterator<Item = (&'a str, &'a str, EntityType)> + 'a> {
1954        match &self.kind {
1955            TypesRefKind::Module(module) => Some(
1956                module
1957                    .imports
1958                    .iter()
1959                    .flat_map(|((m, n), t)| t.iter().map(move |t| (m.as_str(), n.as_str(), *t))),
1960            ),
1961            TypesRefKind::Component(_) => None,
1962        }
1963    }
1964
1965    /// Returns an iterator over the core wasm exports found.
1966    ///
1967    /// Returns `None` if this type information is for a component.
1968    pub fn core_exports(&self) -> Option<impl Iterator<Item = (&'a str, EntityType)> + 'a> {
1969        match &self.kind {
1970            TypesRefKind::Module(module) => {
1971                Some(module.exports.iter().map(|(n, t)| (n.as_str(), *t)))
1972            }
1973            TypesRefKind::Component(_) => None,
1974        }
1975    }
1976}
1977
1978impl<T> Index<T> for TypesRef<'_>
1979where
1980    T: TypeIdentifier,
1981{
1982    type Output = T::Data;
1983
1984    fn index(&self, index: T) -> &Self::Output {
1985        &self.list[index]
1986    }
1987}
1988
1989impl Types {
1990    pub(crate) fn from_module(id: ValidatorId, types: TypeList, module: Arc<Module>) -> Self {
1991        Self {
1992            id,
1993            list: types,
1994            kind: TypesKind::Module(module),
1995        }
1996    }
1997
1998    pub(crate) fn from_component(
1999        id: ValidatorId,
2000        types: TypeList,
2001        component: ComponentState,
2002    ) -> Self {
2003        Self {
2004            id,
2005            list: types,
2006            kind: TypesKind::Component(component),
2007        }
2008    }
2009
2010    /// Get the id of the validator that these types are associated with.
2011    #[inline]
2012    pub fn id(&self) -> ValidatorId {
2013        self.id
2014    }
2015
2016    /// Gets a reference to this validation type information.
2017    pub fn as_ref(&self) -> TypesRef {
2018        TypesRef {
2019            id: self.id,
2020            list: &self.list,
2021            kind: match &self.kind {
2022                TypesKind::Module(module) => TypesRefKind::Module(module),
2023                TypesKind::Component(component) => TypesRefKind::Component(component),
2024            },
2025        }
2026    }
2027
2028    /// Gets a type based on its type id.
2029    ///
2030    /// Returns `None` if the type id is unknown.
2031    pub fn get<T>(&self, id: T) -> Option<&T::Data>
2032    where
2033        T: TypeIdentifier,
2034    {
2035        self.as_ref().get(id)
2036    }
2037
2038    /// Gets a core WebAssembly type at the given type index.
2039    ///
2040    /// Note that this is in contrast to [`TypesRef::component_type_at`] which
2041    /// gets a component type from its index.
2042    ///
2043    /// # Panics
2044    ///
2045    /// Panics if `index` is not a valid function index.
2046    pub fn core_type_at(&self, index: u32) -> ComponentCoreTypeId {
2047        self.as_ref().core_type_at(index)
2048    }
2049
2050    /// Gets a component WebAssembly type at the given type index.
2051    ///
2052    /// Note that this is in contrast to [`TypesRef::core_type_at`] which gets a
2053    /// core type from its index.
2054    ///
2055    /// # Panics
2056    ///
2057    /// Panics if `index` is not a valid type index.
2058    pub fn component_any_type_at(&self, index: u32) -> ComponentAnyTypeId {
2059        self.as_ref().component_any_type_at(index)
2060    }
2061
2062    /// Gets a component type at the given type index.
2063    ///
2064    /// # Panics
2065    ///
2066    /// Panics if `index` is not a valid component type index.
2067    pub fn component_type_at(&self, index: u32) -> ComponentTypeId {
2068        self.as_ref().component_type_at(index)
2069    }
2070
2071    /// Gets a component type from the given component type index.
2072    ///
2073    /// # Panics
2074    ///
2075    /// Panics if `index` is not a valid defined type index or if this type
2076    /// information represents a core module.
2077    pub fn component_defined_type_at(&self, index: u32) -> ComponentDefinedTypeId {
2078        self.as_ref().component_defined_type_at(index)
2079    }
2080
2081    /// Gets the count of core types.
2082    pub fn type_count(&self) -> usize {
2083        match &self.kind {
2084            TypesKind::Module(module) => module.types.len(),
2085            TypesKind::Component(component) => component.core_types.len(),
2086        }
2087    }
2088
2089    /// Gets the type of a table at the given table index.
2090    ///
2091    /// # Panics
2092    ///
2093    /// Panics if `index` is not a valid function index.
2094    pub fn table_at(&self, index: u32) -> TableType {
2095        self.as_ref().table_at(index)
2096    }
2097
2098    /// Gets the count of imported and defined tables.
2099    pub fn table_count(&self) -> usize {
2100        match &self.kind {
2101            TypesKind::Module(module) => module.tables.len(),
2102            TypesKind::Component(component) => component.core_tables.len(),
2103        }
2104    }
2105
2106    /// Gets the type of a memory at the given memory index.
2107    ///
2108    /// # Panics
2109    ///
2110    /// Panics if `index` is not a valid function index.
2111    pub fn memory_at(&self, index: u32) -> MemoryType {
2112        self.as_ref().memory_at(index)
2113    }
2114
2115    /// Gets the count of imported and defined memories.
2116    pub fn memory_count(&self) -> u32 {
2117        self.as_ref().memory_count()
2118    }
2119
2120    /// Gets the type of a global at the given global index.
2121    ///
2122    /// # Panics
2123    ///
2124    /// Panics if `index` is not a valid function index.
2125    pub fn global_at(&self, index: u32) -> GlobalType {
2126        self.as_ref().global_at(index)
2127    }
2128
2129    /// Gets the count of imported and defined globals.
2130    pub fn global_count(&self) -> u32 {
2131        self.as_ref().global_count()
2132    }
2133
2134    /// Gets the type of a tag at the given tag index.
2135    ///
2136    /// # Panics
2137    ///
2138    /// Panics if `index` is not a valid function index.
2139    pub fn tag_at(&self, index: u32) -> CoreTypeId {
2140        self.as_ref().tag_at(index)
2141    }
2142
2143    /// Gets the count of imported and defined tags.
2144    pub fn tag_count(&self) -> u32 {
2145        self.as_ref().tag_count()
2146    }
2147
2148    /// Gets the type of a core function at the given function index.
2149    ///
2150    /// # Panics
2151    ///
2152    /// Panics if `index` is not a valid function index.
2153    pub fn core_function_at(&self, index: u32) -> CoreTypeId {
2154        self.as_ref().core_function_at(index)
2155    }
2156
2157    /// Gets the count of core functions defined so far.
2158    ///
2159    /// Note that this includes imported functions, defined functions, and for
2160    /// components lowered/aliased functions.
2161    pub fn core_function_count(&self) -> u32 {
2162        self.as_ref().function_count()
2163    }
2164
2165    /// Gets the type of an element segment at the given element segment index.
2166    ///
2167    /// # Panics
2168    ///
2169    /// This will panic if the `index` provided is out of bounds.
2170    pub fn element_at(&self, index: u32) -> RefType {
2171        self.as_ref().element_at(index)
2172    }
2173
2174    /// Gets the count of element segments.
2175    pub fn element_count(&self) -> u32 {
2176        self.as_ref().element_count()
2177    }
2178
2179    /// Gets the type of a component function at the given function index.
2180    ///
2181    /// # Panics
2182    ///
2183    /// This will panic if the `index` provided is out of bounds or if this type
2184    /// information represents a core module.
2185    pub fn component_function_at(&self, index: u32) -> ComponentFuncTypeId {
2186        self.as_ref().component_function_at(index)
2187    }
2188
2189    /// Gets the count of imported, exported, or aliased component functions.
2190    pub fn component_function_count(&self) -> u32 {
2191        self.as_ref().component_function_count()
2192    }
2193
2194    /// Gets the type of a module at the given module index.
2195    ///
2196    /// # Panics
2197    ///
2198    /// This will panic if the `index` provided is out of bounds or if this type
2199    /// information represents a core module.
2200    pub fn module_at(&self, index: u32) -> ComponentCoreModuleTypeId {
2201        self.as_ref().module_at(index)
2202    }
2203
2204    /// Gets the count of imported, exported, or aliased modules.
2205    pub fn module_count(&self) -> usize {
2206        match &self.kind {
2207            TypesKind::Module(_) => 0,
2208            TypesKind::Component(component) => component.core_modules.len(),
2209        }
2210    }
2211
2212    /// Gets the type of a module instance at the given module instance index.
2213    ///
2214    /// # Panics
2215    ///
2216    /// This will panic if the `index` provided is out of bounds or if this type
2217    /// information represents a core module.
2218    pub fn core_instance_at(&self, index: u32) -> ComponentCoreInstanceTypeId {
2219        self.as_ref().core_instance_at(index)
2220    }
2221
2222    /// Gets the count of imported, exported, or aliased core module instances.
2223    pub fn core_instance_count(&self) -> usize {
2224        match &self.kind {
2225            TypesKind::Module(_) => 0,
2226            TypesKind::Component(component) => component.core_instances.len(),
2227        }
2228    }
2229
2230    /// Gets the type of a component at the given component index.
2231    ///
2232    /// # Panics
2233    ///
2234    /// This will panic if the `index` provided is out of bounds or if this type
2235    /// information represents a core module.
2236    pub fn component_at(&self, index: u32) -> ComponentTypeId {
2237        self.as_ref().component_at(index)
2238    }
2239
2240    /// Gets the count of imported, exported, or aliased components.
2241    pub fn component_count(&self) -> usize {
2242        match &self.kind {
2243            TypesKind::Module(_) => 0,
2244            TypesKind::Component(component) => component.components.len(),
2245        }
2246    }
2247
2248    /// Gets the type of an component instance at the given component instance index.
2249    ///
2250    /// # Panics
2251    ///
2252    /// This will panic if the `index` provided is out of bounds or if this type
2253    /// information represents a core module.
2254    pub fn component_instance_at(&self, index: u32) -> ComponentInstanceTypeId {
2255        self.as_ref().component_instance_at(index)
2256    }
2257
2258    /// Gets the count of imported, exported, or aliased component instances.
2259    pub fn component_instance_count(&self) -> usize {
2260        match &self.kind {
2261            TypesKind::Module(_) => 0,
2262            TypesKind::Component(component) => component.instances.len(),
2263        }
2264    }
2265
2266    /// Gets the type of a value at the given value index.
2267    ///
2268    /// # Panics
2269    ///
2270    /// This will panic if the `index` provided is out of bounds or if this type
2271    /// information represents a core module.
2272    pub fn value_at(&self, index: u32) -> ComponentValType {
2273        self.as_ref().value_at(index)
2274    }
2275
2276    /// Gets the count of imported, exported, or aliased values.
2277    pub fn value_count(&self) -> usize {
2278        match &self.kind {
2279            TypesKind::Module(_) => 0,
2280            TypesKind::Component(component) => component.values.len(),
2281        }
2282    }
2283
2284    /// Gets the entity type from the given import.
2285    pub fn entity_type_from_import(&self, import: &Import) -> Option<EntityType> {
2286        self.as_ref().entity_type_from_import(import)
2287    }
2288
2289    /// Gets the entity type from the given export.
2290    pub fn entity_type_from_export(&self, export: &Export) -> Option<EntityType> {
2291        self.as_ref().entity_type_from_export(export)
2292    }
2293
2294    /// Gets the component entity type for the given component import name.
2295    pub fn component_entity_type_of_import(&self, name: &str) -> Option<ComponentEntityType> {
2296        self.as_ref().component_entity_type_of_import(name)
2297    }
2298
2299    /// Gets the component entity type for the given component export name.
2300    pub fn component_entity_type_of_export(&self, name: &str) -> Option<ComponentEntityType> {
2301        self.as_ref().component_entity_type_of_export(name)
2302    }
2303
2304    /// Attempts to lookup the type id that `ty` is an alias of.
2305    ///
2306    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
2307    pub fn peel_alias<T>(&self, ty: T) -> Option<T>
2308    where
2309        T: Aliasable,
2310    {
2311        self.list.peel_alias(ty)
2312    }
2313
2314    /// Same as [`TypesRef::core_imports`]
2315    pub fn core_imports<'a>(&self) -> Option<impl Iterator<Item = (&str, &str, EntityType)> + '_> {
2316        self.as_ref().core_imports()
2317    }
2318
2319    /// Same as [`TypesRef::core_exports`]
2320    pub fn core_exports(&self) -> Option<impl Iterator<Item = (&str, EntityType)> + '_> {
2321        self.as_ref().core_exports()
2322    }
2323}
2324
2325impl<T> Index<T> for Types
2326where
2327    T: TypeIdentifier,
2328{
2329    type Output = T::Data;
2330
2331    fn index(&self, id: T) -> &Self::Output {
2332        &self.list[id]
2333    }
2334}
2335
2336/// This is a type which mirrors a subset of the `Vec<T>` API, but is intended
2337/// to be able to be cheaply snapshotted and cloned.
2338///
2339/// When each module's code sections start we "commit" the current list of types
2340/// in the global list of types. This means that the temporary `cur` vec here is
2341/// pushed onto `snapshots` and wrapped up in an `Arc`. At that point we clone
2342/// this entire list (which is then O(modules), not O(types in all modules)) and
2343/// pass out as a context to each function validator.
2344///
2345/// Otherwise, though, this type behaves as if it were a large `Vec<T>`, but
2346/// it's represented by lists of contiguous chunks.
2347//
2348// Only public because it shows up in a public trait's `doc(hidden)` method.
2349#[doc(hidden)]
2350#[derive(Debug)]
2351pub struct SnapshotList<T> {
2352    // All previous snapshots, the "head" of the list that this type represents.
2353    // The first entry in this pair is the starting index for all elements
2354    // contained in the list, and the second element is the list itself. Note
2355    // the `Arc` wrapper around sub-lists, which makes cloning time for this
2356    // `SnapshotList` O(snapshots) rather than O(snapshots_total), which for
2357    // us in this context means the number of modules, not types.
2358    //
2359    // Note that this list is sorted least-to-greatest in order of the index for
2360    // binary searching.
2361    snapshots: Vec<Arc<Snapshot<T>>>,
2362
2363    // This is the total length of all lists in the `snapshots` array.
2364    snapshots_total: usize,
2365
2366    // The current list of types for the current snapshot that are being built.
2367    cur: Vec<T>,
2368}
2369
2370#[derive(Debug)]
2371struct Snapshot<T> {
2372    prior_types: usize,
2373    items: Vec<T>,
2374}
2375
2376impl<T> SnapshotList<T> {
2377    /// Same as `<&[T]>::get`
2378    pub(crate) fn get(&self, index: usize) -> Option<&T> {
2379        // Check to see if this index falls on our local list
2380        if index >= self.snapshots_total {
2381            return self.cur.get(index - self.snapshots_total);
2382        }
2383        // ... and failing that we do a binary search to figure out which bucket
2384        // it's in. Note the `i-1` in the `Err` case because if we don't find an
2385        // exact match the type is located in the previous bucket.
2386        let i = match self
2387            .snapshots
2388            .binary_search_by_key(&index, |snapshot| snapshot.prior_types)
2389        {
2390            Ok(i) => i,
2391            Err(i) => i - 1,
2392        };
2393        let snapshot = &self.snapshots[i];
2394        Some(&snapshot.items[index - snapshot.prior_types])
2395    }
2396
2397    /// Same as `Vec::push`
2398    pub(crate) fn push(&mut self, val: T) {
2399        self.cur.push(val);
2400    }
2401
2402    /// Same as `<[T]>::len`
2403    pub(crate) fn len(&self) -> usize {
2404        self.cur.len() + self.snapshots_total
2405    }
2406
2407    /// Same as `Vec::truncate` but can only truncate uncommitted elements.
2408    pub(crate) fn truncate(&mut self, len: usize) {
2409        assert!(len >= self.snapshots_total);
2410        self.cur.truncate(len - self.snapshots_total);
2411    }
2412
2413    /// Commits previously pushed types into this snapshot vector, and returns a
2414    /// clone of this list.
2415    ///
2416    /// The returned `SnapshotList` can be used to access all the same types as
2417    /// this list itself. This list also is not changed (from an external
2418    /// perspective) and can continue to access all the same types.
2419    pub(crate) fn commit(&mut self) -> SnapshotList<T> {
2420        // If the current chunk has new elements, commit them in to an
2421        // `Arc`-wrapped vector in the snapshots list. Note the `shrink_to_fit`
2422        // ahead of time to hopefully keep memory usage lower than it would
2423        // otherwise be.
2424        let len = self.cur.len();
2425        if len > 0 {
2426            self.cur.shrink_to_fit();
2427            self.snapshots.push(Arc::new(Snapshot {
2428                prior_types: self.snapshots_total,
2429                items: mem::take(&mut self.cur),
2430            }));
2431            self.snapshots_total += len;
2432        }
2433        SnapshotList {
2434            snapshots: self.snapshots.clone(),
2435            snapshots_total: self.snapshots_total,
2436            cur: Vec::new(),
2437        }
2438    }
2439}
2440
2441impl<T> Index<usize> for SnapshotList<T> {
2442    type Output = T;
2443
2444    #[inline]
2445    fn index(&self, index: usize) -> &T {
2446        self.get(index).unwrap()
2447    }
2448}
2449
2450impl<T, U> Index<U> for SnapshotList<T>
2451where
2452    U: TypeIdentifier<Data = T>,
2453{
2454    type Output = T;
2455
2456    #[inline]
2457    fn index(&self, id: U) -> &T {
2458        self.get(id.index()).unwrap()
2459    }
2460}
2461
2462impl<T> Default for SnapshotList<T> {
2463    fn default() -> SnapshotList<T> {
2464        SnapshotList {
2465            snapshots: Vec::new(),
2466            snapshots_total: 0,
2467            cur: Vec::new(),
2468        }
2469    }
2470}
2471
2472/// A snapshot list of types.
2473///
2474/// Note that the snapshot lists below do not correspond with index spaces. Many
2475/// different kinds of types are in the same index space (e.g. all of the
2476/// component model's {component, instance, defined, func} types are in the same
2477/// index space). However, we store each of them in their own type-specific
2478/// snapshot list and give each of them their own identifier type.
2479#[derive(Default, Debug)]
2480// Only public because it shows up in a public trait's `doc(hidden)` method.
2481#[doc(hidden)]
2482pub struct TypeList {
2483    // Keeps track of which `alias_id` is an alias of which other `alias_id`.
2484    alias_mappings: Map<u32, u32>,
2485    // Counter for generating new `alias_id`s.
2486    alias_counter: u32,
2487    // Snapshots of previously committed `TypeList`s' aliases.
2488    alias_snapshots: Vec<TypeListAliasSnapshot>,
2489
2490    // Core Wasm types.
2491    //
2492    // A primary map from `CoreTypeId` to `SubType`.
2493    core_types: SnapshotList<SubType>,
2494    // The id of each core Wasm type's rec group.
2495    //
2496    // A secondary map from `CoreTypeId` to `RecGroupId`.
2497    core_type_to_rec_group: SnapshotList<RecGroupId>,
2498    // The supertype of each core type.
2499    //
2500    // A secondary map from `CoreTypeId` to `Option<CoreTypeId>`.
2501    core_type_to_supertype: SnapshotList<Option<CoreTypeId>>,
2502    // The subtyping depth of each core type. We use `u8::MAX` as a sentinel for
2503    // an uninitialized entry.
2504    //
2505    // A secondary map from `CoreTypeId` to `u8`.
2506    core_type_to_depth: Option<IndexMap<CoreTypeId, u8>>,
2507    // A primary map from `RecGroupId` to the range of the rec group's elements
2508    // within `core_types`.
2509    rec_group_elements: SnapshotList<Range<CoreTypeId>>,
2510    // A hash map from rec group elements to their canonical `RecGroupId`.
2511    //
2512    // This is `None` when a list is "committed" meaning that no more insertions
2513    // can happen.
2514    canonical_rec_groups: Option<Map<RecGroup, RecGroupId>>,
2515
2516    // Component model types.
2517    components: SnapshotList<ComponentType>,
2518    component_defined_types: SnapshotList<ComponentDefinedType>,
2519    component_values: SnapshotList<ComponentValType>,
2520    component_instances: SnapshotList<ComponentInstanceType>,
2521    component_funcs: SnapshotList<ComponentFuncType>,
2522    core_modules: SnapshotList<ModuleType>,
2523    core_instances: SnapshotList<InstanceType>,
2524}
2525
2526#[derive(Clone, Debug)]
2527struct TypeListAliasSnapshot {
2528    // The `alias_counter` at the time that this snapshot was taken.
2529    alias_counter: u32,
2530
2531    // The alias mappings in this snapshot.
2532    alias_mappings: Map<u32, u32>,
2533}
2534
2535struct TypeListCheckpoint {
2536    core_types: usize,
2537    components: usize,
2538    component_defined_types: usize,
2539    component_values: usize,
2540    component_instances: usize,
2541    component_funcs: usize,
2542    core_modules: usize,
2543    core_instances: usize,
2544    core_type_to_rec_group: usize,
2545    core_type_to_supertype: usize,
2546    core_type_to_depth: usize,
2547    rec_group_elements: usize,
2548    canonical_rec_groups: usize,
2549}
2550
2551impl TypeList {
2552    pub fn get<T>(&self, id: T) -> Option<&T::Data>
2553    where
2554        T: TypeIdentifier,
2555    {
2556        T::list(self).get(id.index())
2557    }
2558
2559    pub fn push<T>(&mut self, ty: T) -> T::Id
2560    where
2561        T: TypeData,
2562    {
2563        let index = u32::try_from(T::Id::list(self).len()).unwrap();
2564        let id = T::Id::from_index(index);
2565        T::Id::list_mut(self).push(ty);
2566        id
2567    }
2568
2569    /// Intern the given recursion group (that has already been canonicalized)
2570    /// and return its associated id and whether this was a new recursion group
2571    /// or not.
2572    pub fn intern_canonical_rec_group(&mut self, rec_group: RecGroup) -> (bool, RecGroupId) {
2573        let canonical_rec_groups = self
2574            .canonical_rec_groups
2575            .as_mut()
2576            .expect("cannot intern into a committed list");
2577        let entry = match canonical_rec_groups.entry(rec_group) {
2578            Entry::Occupied(e) => return (false, *e.get()),
2579            Entry::Vacant(e) => e,
2580        };
2581
2582        let rec_group_id = self.rec_group_elements.len();
2583        let rec_group_id = u32::try_from(rec_group_id).unwrap();
2584        let rec_group_id = RecGroupId::from_index(rec_group_id);
2585
2586        let start = self.core_types.len();
2587        let start = u32::try_from(start).unwrap();
2588        let start = CoreTypeId::from_index(start);
2589
2590        for ty in entry.key().types() {
2591            debug_assert_eq!(self.core_types.len(), self.core_type_to_supertype.len());
2592            debug_assert_eq!(self.core_types.len(), self.core_type_to_rec_group.len());
2593
2594            self.core_type_to_supertype
2595                .push(ty.supertype_idx.map(|idx| match idx.unpack() {
2596                    UnpackedIndex::RecGroup(offset) => CoreTypeId::from_index(start.index + offset),
2597                    UnpackedIndex::Id(id) => id,
2598                    UnpackedIndex::Module(_) => unreachable!("in canonical form"),
2599                }));
2600            let mut ty = ty.clone();
2601            ty.remap_indices(&mut |index| {
2602                match index.unpack() {
2603                    UnpackedIndex::Id(_) => {}
2604                    UnpackedIndex::Module(_) => unreachable!(),
2605                    UnpackedIndex::RecGroup(offset) => {
2606                        *index = UnpackedIndex::Id(CoreTypeId::from_index(start.index + offset))
2607                            .pack()
2608                            .unwrap();
2609                    }
2610                };
2611                Ok(())
2612            })
2613            .expect("cannot fail");
2614            self.core_types.push(ty);
2615            self.core_type_to_rec_group.push(rec_group_id);
2616        }
2617
2618        let end = self.core_types.len();
2619        let end = u32::try_from(end).unwrap();
2620        let end = CoreTypeId::from_index(end);
2621
2622        let range = start..end;
2623
2624        self.rec_group_elements.push(range.clone());
2625
2626        entry.insert(rec_group_id);
2627        return (true, rec_group_id);
2628    }
2629
2630    /// Get the `CoreTypeId` for a local index into a rec group.
2631    pub fn rec_group_local_id(
2632        &self,
2633        rec_group: RecGroupId,
2634        index: u32,
2635        offset: usize,
2636    ) -> Result<CoreTypeId> {
2637        let elems = &self[rec_group];
2638        let len = elems.end.index() - elems.start.index();
2639        let len = u32::try_from(len).unwrap();
2640        if index < len {
2641            let id = u32::try_from(elems.start.index()).unwrap() + index;
2642            let id = CoreTypeId::from_index(id);
2643            Ok(id)
2644        } else {
2645            bail!(
2646                offset,
2647                "unknown type {index}: type index out of rec group bounds"
2648            )
2649        }
2650    }
2651
2652    /// Get the id of the rec group that the given type id was defined within.
2653    pub fn rec_group_id_of(&self, id: CoreTypeId) -> RecGroupId {
2654        self.core_type_to_rec_group[id.index()]
2655    }
2656
2657    /// Get the super type of the given type id, if any.
2658    pub fn supertype_of(&self, id: CoreTypeId) -> Option<CoreTypeId> {
2659        self.core_type_to_supertype[id.index()]
2660    }
2661
2662    /// Get the subtyping depth of the given type. A type without any supertype
2663    /// has depth 0.
2664    pub fn get_subtyping_depth(&self, id: CoreTypeId) -> u8 {
2665        let depth = self
2666            .core_type_to_depth
2667            .as_ref()
2668            .expect("cannot get subtype depth from a committed list")[id.index()];
2669        debug_assert!(usize::from(depth) <= crate::limits::MAX_WASM_SUBTYPING_DEPTH);
2670        depth
2671    }
2672
2673    /// Set the subtyping depth of the given type. This may only be done once
2674    /// per type.
2675    pub fn set_subtyping_depth(&mut self, id: CoreTypeId, depth: u8) {
2676        debug_assert!(usize::from(depth) <= crate::limits::MAX_WASM_SUBTYPING_DEPTH);
2677        let map = self
2678            .core_type_to_depth
2679            .as_mut()
2680            .expect("cannot set a subtype depth in a committed list");
2681        debug_assert!(!map.contains_key(&id));
2682        map.insert(id, depth);
2683    }
2684
2685    /// Get the `CoreTypeId` for a canonicalized `PackedIndex`.
2686    ///
2687    /// Panics when given a non-canonicalized `PackedIndex`.
2688    pub fn at_canonicalized_packed_index(
2689        &self,
2690        rec_group: RecGroupId,
2691        index: PackedIndex,
2692        offset: usize,
2693    ) -> Result<CoreTypeId> {
2694        self.at_canonicalized_unpacked_index(rec_group, index.unpack(), offset)
2695    }
2696
2697    /// Get the `CoreTypeId` for a canonicalized `UnpackedIndex`.
2698    ///
2699    /// Panics when given a non-canonicalized `PackedIndex`.
2700    pub fn at_canonicalized_unpacked_index(
2701        &self,
2702        rec_group: RecGroupId,
2703        index: UnpackedIndex,
2704        offset: usize,
2705    ) -> Result<CoreTypeId> {
2706        match index {
2707            UnpackedIndex::Module(_) => panic!("not canonicalized"),
2708            UnpackedIndex::Id(id) => Ok(id),
2709            UnpackedIndex::RecGroup(idx) => self.rec_group_local_id(rec_group, idx, offset),
2710        }
2711    }
2712
2713    /// Does `a` structurally match `b`?
2714    pub fn matches(&self, a: CoreTypeId, b: CoreTypeId) -> bool {
2715        let a = WithRecGroup::new(self, a);
2716        let a = WithRecGroup::map(a, |a| &self[a]);
2717
2718        let b = WithRecGroup::new(self, b);
2719        let b = WithRecGroup::map(b, |b| &self[b]);
2720
2721        Matches::matches(self, a, b)
2722    }
2723
2724    /// Is `a == b` or was `a` declared (potentially transitively) to be a
2725    /// subtype of `b`?
2726    pub fn id_is_subtype(&self, mut a: CoreTypeId, b: CoreTypeId) -> bool {
2727        loop {
2728            if a == b {
2729                return true;
2730            }
2731
2732            // TODO: maintain supertype vectors and implement this check in O(1)
2733            // instead of O(n) time.
2734            a = match self.supertype_of(a) {
2735                Some(a) => a,
2736                None => return false,
2737            };
2738        }
2739    }
2740
2741    /// Like `id_is_subtype` but for `RefType`s.
2742    ///
2743    /// Both `a` and `b` must be canonicalized already.
2744    pub fn reftype_is_subtype(&self, a: RefType, b: RefType) -> bool {
2745        // NB: Don't need `RecGroupId`s since we are calling from outside of the
2746        // rec group, and so any `PackedIndex`es we encounter have already been
2747        // canonicalized to `CoreTypeId`s directly.
2748        self.reftype_is_subtype_impl(a, None, b, None)
2749    }
2750
2751    /// Implementation of `RefType` and `HeapType` subtyping.
2752    ///
2753    /// Panics if we need rec groups but aren't given them. Rec groups only need
2754    /// to be passed in when checking subtyping of `RefType`s that we encounter
2755    /// while validating a rec group itself.
2756    pub(crate) fn reftype_is_subtype_impl(
2757        &self,
2758        a: RefType,
2759        a_group: Option<RecGroupId>,
2760        b: RefType,
2761        b_group: Option<RecGroupId>,
2762    ) -> bool {
2763        if a == b && a_group == b_group {
2764            return true;
2765        }
2766
2767        if a.is_nullable() && !b.is_nullable() {
2768            return false;
2769        }
2770
2771        let core_type_id = |group: Option<RecGroupId>, index: UnpackedIndex| -> CoreTypeId {
2772            if let Some(id) = index.as_core_type_id() {
2773                id
2774            } else {
2775                self.at_canonicalized_unpacked_index(group.unwrap(), index, usize::MAX)
2776                    .expect("type references are checked during canonicalization")
2777            }
2778        };
2779
2780        let subtype = |group, index| -> &SubType {
2781            let id = core_type_id(group, index);
2782            &self[id]
2783        };
2784
2785        use AbstractHeapType::*;
2786        use CompositeInnerType as CT;
2787        use HeapType as HT;
2788        match (a.heap_type(), b.heap_type()) {
2789            (a, b) if a == b => true,
2790
2791            (
2792                HT::Abstract {
2793                    shared: a_shared,
2794                    ty: a_ty,
2795                },
2796                HT::Abstract {
2797                    shared: b_shared,
2798                    ty: b_ty,
2799                },
2800            ) => a_shared == b_shared && a_ty.is_subtype_of(b_ty),
2801
2802            (HT::Concrete(a), HT::Abstract { shared, ty }) => {
2803                let a_ty = &subtype(a_group, a).composite_type;
2804                if a_ty.shared != shared {
2805                    return false;
2806                }
2807                match ty {
2808                    Any | Eq => matches!(a_ty.inner, CT::Array(_) | CT::Struct(_)),
2809                    Struct => matches!(a_ty.inner, CT::Struct(_)),
2810                    Array => matches!(a_ty.inner, CT::Array(_)),
2811                    Func => matches!(a_ty.inner, CT::Func(_)),
2812                    // Nothing else matches. (Avoid full wildcard matches so
2813                    // that adding/modifying variants is easier in the future.)
2814                    Extern | Exn | I31 | None | NoFunc | NoExtern | NoExn => false,
2815                }
2816            }
2817
2818            (HT::Abstract { shared, ty }, HT::Concrete(b)) => {
2819                let b_ty = &subtype(b_group, b).composite_type;
2820                if shared != b_ty.shared {
2821                    return false;
2822                }
2823                match ty {
2824                    None => matches!(b_ty.inner, CT::Array(_) | CT::Struct(_)),
2825                    NoFunc => matches!(b_ty.inner, CT::Func(_)),
2826                    // Nothing else matches. (Avoid full wildcard matches so
2827                    // that adding/modifying variants is easier in the future.)
2828                    Func | Extern | Exn | Any | Eq | Array | I31 | Struct | NoExtern | NoExn => {
2829                        false
2830                    }
2831                }
2832            }
2833
2834            (HT::Concrete(a), HT::Concrete(b)) => {
2835                self.id_is_subtype(core_type_id(a_group, a), core_type_id(b_group, b))
2836            }
2837        }
2838    }
2839
2840    /// Like `id_is_subtype` but for `RefType`s.
2841    ///
2842    /// Both `a` and `b` must be canonicalized already.
2843    pub fn valtype_is_subtype(&self, a: ValType, b: ValType) -> bool {
2844        match (a, b) {
2845            (a, b) if a == b => true,
2846            (ValType::Ref(a), ValType::Ref(b)) => self.reftype_is_subtype(a, b),
2847            (ValType::Ref(_), _)
2848            | (ValType::I32, _)
2849            | (ValType::I64, _)
2850            | (ValType::F32, _)
2851            | (ValType::F64, _)
2852            | (ValType::V128, _) => false,
2853        }
2854    }
2855
2856    /// Is `ty` shared?
2857    pub fn valtype_is_shared(&self, ty: ValType) -> bool {
2858        match ty {
2859            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => true,
2860            ValType::Ref(rt) => self.reftype_is_shared(rt),
2861        }
2862    }
2863
2864    /// Is the reference type `ty` shared?
2865    ///
2866    /// This is complicated by concrete heap types whose shared-ness must be
2867    /// checked by looking at the type they point to.
2868    pub fn reftype_is_shared(&self, ty: RefType) -> bool {
2869        match ty.heap_type() {
2870            HeapType::Abstract { shared, .. } => shared,
2871            HeapType::Concrete(index) => {
2872                self[index.as_core_type_id().unwrap()].composite_type.shared
2873            }
2874        }
2875    }
2876
2877    /// Get the top type of the given heap type.
2878    ///
2879    /// Concrete types must have had their indices canonicalized to core type
2880    /// ids, otherwise this method will panic.
2881    pub fn top_type(&self, heap_type: &HeapType) -> HeapType {
2882        use AbstractHeapType::*;
2883        match *heap_type {
2884            HeapType::Concrete(idx) => {
2885                let ty = &self[idx.as_core_type_id().unwrap()].composite_type;
2886                let shared = ty.shared;
2887                match ty.inner {
2888                    CompositeInnerType::Func(_) => HeapType::Abstract { shared, ty: Func },
2889                    CompositeInnerType::Array(_) | CompositeInnerType::Struct(_) => {
2890                        HeapType::Abstract { shared, ty: Any }
2891                    }
2892                }
2893            }
2894            HeapType::Abstract { shared, ty } => {
2895                let ty = match ty {
2896                    Func | NoFunc => Func,
2897                    Extern | NoExtern => Extern,
2898                    Any | Eq | Struct | Array | I31 | None => Any,
2899                    Exn | NoExn => Exn,
2900                };
2901                HeapType::Abstract { shared, ty }
2902            }
2903        }
2904    }
2905
2906    fn checkpoint(&self) -> TypeListCheckpoint {
2907        let TypeList {
2908            alias_mappings: _,
2909            alias_counter: _,
2910            alias_snapshots: _,
2911            core_types,
2912            components,
2913            component_defined_types,
2914            component_values,
2915            component_instances,
2916            component_funcs,
2917            core_modules,
2918            core_instances,
2919            core_type_to_rec_group,
2920            core_type_to_supertype,
2921            core_type_to_depth,
2922            rec_group_elements,
2923            canonical_rec_groups,
2924        } = self;
2925
2926        TypeListCheckpoint {
2927            core_types: core_types.len(),
2928            components: components.len(),
2929            component_defined_types: component_defined_types.len(),
2930            component_values: component_values.len(),
2931            component_instances: component_instances.len(),
2932            component_funcs: component_funcs.len(),
2933            core_modules: core_modules.len(),
2934            core_instances: core_instances.len(),
2935            core_type_to_rec_group: core_type_to_rec_group.len(),
2936            core_type_to_supertype: core_type_to_supertype.len(),
2937            core_type_to_depth: core_type_to_depth.as_ref().map(|m| m.len()).unwrap_or(0),
2938            rec_group_elements: rec_group_elements.len(),
2939            canonical_rec_groups: canonical_rec_groups.as_ref().map(|m| m.len()).unwrap_or(0),
2940        }
2941    }
2942
2943    fn reset_to_checkpoint(&mut self, checkpoint: TypeListCheckpoint) {
2944        let TypeList {
2945            alias_mappings: _,
2946            alias_counter: _,
2947            alias_snapshots: _,
2948            core_types,
2949            components,
2950            component_defined_types,
2951            component_values,
2952            component_instances,
2953            component_funcs,
2954            core_modules,
2955            core_instances,
2956            core_type_to_rec_group,
2957            core_type_to_supertype,
2958            core_type_to_depth,
2959            rec_group_elements,
2960            canonical_rec_groups,
2961        } = self;
2962
2963        core_types.truncate(checkpoint.core_types);
2964        components.truncate(checkpoint.components);
2965        component_defined_types.truncate(checkpoint.component_defined_types);
2966        component_values.truncate(checkpoint.component_values);
2967        component_instances.truncate(checkpoint.component_instances);
2968        component_funcs.truncate(checkpoint.component_funcs);
2969        core_modules.truncate(checkpoint.core_modules);
2970        core_instances.truncate(checkpoint.core_instances);
2971        core_type_to_rec_group.truncate(checkpoint.core_type_to_rec_group);
2972        core_type_to_supertype.truncate(checkpoint.core_type_to_supertype);
2973        rec_group_elements.truncate(checkpoint.rec_group_elements);
2974
2975        if let Some(core_type_to_depth) = core_type_to_depth {
2976            assert_eq!(
2977                core_type_to_depth.len(),
2978                checkpoint.core_type_to_depth,
2979                "checkpointing does not support resetting `core_type_to_depth` (it would require a \
2980                 proper immutable and persistent hash map) so adding new groups is disallowed"
2981            );
2982        }
2983        if let Some(canonical_rec_groups) = canonical_rec_groups {
2984            assert_eq!(
2985                canonical_rec_groups.len(),
2986                checkpoint.canonical_rec_groups,
2987                "checkpointing does not support resetting `canonical_rec_groups` (it would require a \
2988                 proper immutable and persistent hash map) so adding new groups is disallowed"
2989            );
2990        }
2991    }
2992
2993    pub fn commit(&mut self) -> TypeList {
2994        // Note that the `alias_counter` is bumped here to ensure that the
2995        // previous value of the unique counter is never used for an actual type
2996        // so it's suitable for lookup via a binary search.
2997        let alias_counter = self.alias_counter;
2998        self.alias_counter += 1;
2999
3000        self.alias_snapshots.push(TypeListAliasSnapshot {
3001            alias_counter,
3002            alias_mappings: mem::take(&mut self.alias_mappings),
3003        });
3004
3005        TypeList {
3006            alias_mappings: Map::default(),
3007            alias_counter: self.alias_counter,
3008            alias_snapshots: self.alias_snapshots.clone(),
3009            core_types: self.core_types.commit(),
3010            components: self.components.commit(),
3011            component_defined_types: self.component_defined_types.commit(),
3012            component_values: self.component_values.commit(),
3013            component_instances: self.component_instances.commit(),
3014            component_funcs: self.component_funcs.commit(),
3015            core_modules: self.core_modules.commit(),
3016            core_instances: self.core_instances.commit(),
3017            core_type_to_rec_group: self.core_type_to_rec_group.commit(),
3018            core_type_to_supertype: self.core_type_to_supertype.commit(),
3019            core_type_to_depth: None,
3020            rec_group_elements: self.rec_group_elements.commit(),
3021            canonical_rec_groups: None,
3022        }
3023    }
3024
3025    /// See `SnapshotList::with_unique`.
3026    pub fn with_unique<T>(&mut self, mut ty: T) -> T
3027    where
3028        T: Aliasable,
3029    {
3030        self.alias_mappings
3031            .insert(self.alias_counter, ty.alias_id());
3032        ty.set_alias_id(self.alias_counter);
3033        self.alias_counter += 1;
3034        ty
3035    }
3036
3037    /// Attempts to lookup the type id that `ty` is an alias of.
3038    ///
3039    /// Returns `None` if `ty` wasn't listed as aliasing a prior type.
3040    pub fn peel_alias<T>(&self, mut ty: T) -> Option<T>
3041    where
3042        T: Aliasable,
3043    {
3044        let alias_id = ty.alias_id();
3045
3046        // The unique counter in each snapshot is the unique counter at the
3047        // time of the snapshot so it's guaranteed to never be used, meaning
3048        // that `Ok` should never show up here. With an `Err` it's where the
3049        // index would be placed meaning that the index in question is the
3050        // smallest value over the unique id's value, meaning that slot has the
3051        // mapping we're interested in.
3052        let i = match self
3053            .alias_snapshots
3054            .binary_search_by_key(&alias_id, |snapshot| snapshot.alias_counter)
3055        {
3056            Ok(_) => unreachable!(),
3057            Err(i) => i,
3058        };
3059
3060        // If the `i` index is beyond the snapshot array then lookup in the
3061        // current mappings instead since it may refer to a type not snapshot
3062        // yet.
3063        ty.set_alias_id(match self.alias_snapshots.get(i) {
3064            Some(snapshot) => *snapshot.alias_mappings.get(&alias_id)?,
3065            None => *self.alias_mappings.get(&alias_id)?,
3066        });
3067        Some(ty)
3068    }
3069}
3070
3071impl<T> Index<T> for TypeList
3072where
3073    T: TypeIdentifier,
3074{
3075    type Output = T::Data;
3076
3077    fn index(&self, id: T) -> &Self::Output {
3078        let arena = T::list(self);
3079        &arena[id.index()]
3080    }
3081}
3082
3083/// Thin wrapper around `TypeList` which provides an allocator of unique ids for
3084/// types contained within this list.
3085pub(crate) struct TypeAlloc {
3086    list: TypeList,
3087
3088    // This is assigned at creation of a `TypeAlloc` and then never changed.
3089    // It's used in one entry for all `ResourceId`s contained within.
3090    globally_unique_id: usize,
3091
3092    // This is a counter that's incremeneted each time `alloc_resource_id` is
3093    // called.
3094    next_resource_id: u32,
3095}
3096
3097impl Default for TypeAlloc {
3098    fn default() -> TypeAlloc {
3099        static NEXT_GLOBAL_ID: AtomicUsize = AtomicUsize::new(0);
3100        let mut ret = TypeAlloc {
3101            list: TypeList::default(),
3102            globally_unique_id: {
3103                let id = NEXT_GLOBAL_ID.fetch_add(1, Ordering::Relaxed);
3104                if id > usize::MAX - 10_000 {
3105                    NEXT_GLOBAL_ID.store(usize::MAX - 10_000, Ordering::Relaxed);
3106                    panic!("overflow on the global id counter");
3107                }
3108                id
3109            },
3110            next_resource_id: 0,
3111        };
3112        ret.list.core_type_to_depth = Some(Default::default());
3113        ret.list.canonical_rec_groups = Some(Default::default());
3114        ret
3115    }
3116}
3117
3118impl Deref for TypeAlloc {
3119    type Target = TypeList;
3120    fn deref(&self) -> &TypeList {
3121        &self.list
3122    }
3123}
3124
3125impl DerefMut for TypeAlloc {
3126    fn deref_mut(&mut self) -> &mut TypeList {
3127        &mut self.list
3128    }
3129}
3130
3131impl TypeAlloc {
3132    /// Pushes a new type into this list, returning an identifier which can be
3133    /// used to later retrieve it.
3134    ///
3135    /// The returned identifier is unique within this `TypeAlloc` and won't be
3136    /// hash-equivalent to anything else.
3137    pub fn push_ty<T>(&mut self, ty: T) -> T::Id
3138    where
3139        T: TypeData,
3140    {
3141        self.list.push(ty)
3142    }
3143
3144    /// Allocates a new unique resource identifier.
3145    ///
3146    /// Note that uniqueness is only a property within this `TypeAlloc`.
3147    pub fn alloc_resource_id(&mut self) -> AliasableResourceId {
3148        let contextually_unique_id = self.next_resource_id;
3149        self.next_resource_id = self.next_resource_id.checked_add(1).unwrap();
3150        AliasableResourceId {
3151            id: ResourceId {
3152                globally_unique_id: self.globally_unique_id,
3153                contextually_unique_id,
3154            },
3155            alias_id: NO_ALIAS,
3156        }
3157    }
3158
3159    /// Adds the set of "free variables" of the `id` provided to the `set`
3160    /// provided.
3161    ///
3162    /// Free variables are defined as resources. Any resource, perhaps
3163    /// transitively, referred to but not defined by `id` is added to the `set`
3164    /// and returned.
3165    pub fn free_variables_any_type_id(
3166        &self,
3167        id: ComponentAnyTypeId,
3168        set: &mut IndexSet<ResourceId>,
3169    ) {
3170        match id {
3171            ComponentAnyTypeId::Resource(r) => {
3172                set.insert(r.resource());
3173            }
3174            ComponentAnyTypeId::Defined(id) => {
3175                self.free_variables_component_defined_type_id(id, set)
3176            }
3177            ComponentAnyTypeId::Func(id) => self.free_variables_component_func_type_id(id, set),
3178            ComponentAnyTypeId::Instance(id) => {
3179                self.free_variables_component_instance_type_id(id, set)
3180            }
3181            ComponentAnyTypeId::Component(id) => self.free_variables_component_type_id(id, set),
3182        }
3183    }
3184
3185    pub fn free_variables_component_defined_type_id(
3186        &self,
3187        id: ComponentDefinedTypeId,
3188        set: &mut IndexSet<ResourceId>,
3189    ) {
3190        match &self[id] {
3191            ComponentDefinedType::Primitive(_)
3192            | ComponentDefinedType::Flags(_)
3193            | ComponentDefinedType::Enum(_) => {}
3194            ComponentDefinedType::Record(r) => {
3195                for ty in r.fields.values() {
3196                    self.free_variables_valtype(ty, set);
3197                }
3198            }
3199            ComponentDefinedType::Tuple(r) => {
3200                for ty in r.types.iter() {
3201                    self.free_variables_valtype(ty, set);
3202                }
3203            }
3204            ComponentDefinedType::Variant(r) => {
3205                for ty in r.cases.values() {
3206                    if let Some(ty) = &ty.ty {
3207                        self.free_variables_valtype(ty, set);
3208                    }
3209                }
3210            }
3211            ComponentDefinedType::List(ty) | ComponentDefinedType::Option(ty) => {
3212                self.free_variables_valtype(ty, set);
3213            }
3214            ComponentDefinedType::Result { ok, err } => {
3215                if let Some(ok) = ok {
3216                    self.free_variables_valtype(ok, set);
3217                }
3218                if let Some(err) = err {
3219                    self.free_variables_valtype(err, set);
3220                }
3221            }
3222            ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
3223                set.insert(id.resource());
3224            }
3225        }
3226    }
3227
3228    pub fn free_variables_component_type_id(
3229        &self,
3230        id: ComponentTypeId,
3231        set: &mut IndexSet<ResourceId>,
3232    ) {
3233        let i = &self[id];
3234        // Recurse on the imports/exports of components, but remove the
3235        // imported and defined resources within the component itself.
3236        //
3237        // Technically this needs to add all the free variables of the
3238        // exports, remove the defined resources, then add the free
3239        // variables of imports, then remove the imported resources. Given
3240        // prior validation of component types, however, the defined
3241        // and imported resources are disjoint and imports can't refer to
3242        // defined resources, so doing this all in one go should be
3243        // equivalent.
3244        for ty in i.imports.values().chain(i.exports.values()) {
3245            self.free_variables_component_entity(ty, set);
3246        }
3247        for (id, _path) in i.imported_resources.iter().chain(&i.defined_resources) {
3248            set.swap_remove(id);
3249        }
3250    }
3251
3252    pub fn free_variables_component_instance_type_id(
3253        &self,
3254        id: ComponentInstanceTypeId,
3255        set: &mut IndexSet<ResourceId>,
3256    ) {
3257        let i = &self[id];
3258        // Like components, add in all the free variables of referenced
3259        // types but then remove those defined by this component instance
3260        // itself.
3261        for ty in i.exports.values() {
3262            self.free_variables_component_entity(ty, set);
3263        }
3264        for id in i.defined_resources.iter() {
3265            set.swap_remove(id);
3266        }
3267    }
3268
3269    pub fn free_variables_component_func_type_id(
3270        &self,
3271        id: ComponentFuncTypeId,
3272        set: &mut IndexSet<ResourceId>,
3273    ) {
3274        let i = &self[id];
3275        for ty in i
3276            .params
3277            .iter()
3278            .map(|(_, ty)| ty)
3279            .chain(i.results.iter().map(|(_, ty)| ty))
3280        {
3281            self.free_variables_valtype(ty, set);
3282        }
3283    }
3284
3285    /// Same as `free_variables_type_id`, but for `ComponentEntityType`.
3286    pub fn free_variables_component_entity(
3287        &self,
3288        ty: &ComponentEntityType,
3289        set: &mut IndexSet<ResourceId>,
3290    ) {
3291        match ty {
3292            ComponentEntityType::Module(_) => {}
3293            ComponentEntityType::Func(id) => self.free_variables_component_func_type_id(*id, set),
3294            ComponentEntityType::Instance(id) => {
3295                self.free_variables_component_instance_type_id(*id, set)
3296            }
3297            ComponentEntityType::Component(id) => self.free_variables_component_type_id(*id, set),
3298            ComponentEntityType::Type { created, .. } => {
3299                self.free_variables_any_type_id(*created, set);
3300            }
3301            ComponentEntityType::Value(ty) => self.free_variables_valtype(ty, set),
3302        }
3303    }
3304
3305    /// Same as `free_variables_type_id`, but for `ComponentValType`.
3306    fn free_variables_valtype(&self, ty: &ComponentValType, set: &mut IndexSet<ResourceId>) {
3307        match ty {
3308            ComponentValType::Primitive(_) => {}
3309            ComponentValType::Type(id) => self.free_variables_component_defined_type_id(*id, set),
3310        }
3311    }
3312
3313    /// Returns whether the type `id` is "named" where named types are presented
3314    /// via the provided `set`.
3315    ///
3316    /// This requires that `id` is a `Defined` type.
3317    pub(crate) fn type_named_type_id(
3318        &self,
3319        id: ComponentDefinedTypeId,
3320        set: &Set<ComponentAnyTypeId>,
3321    ) -> bool {
3322        let ty = &self[id];
3323        match ty {
3324            // Primitives are always considered named
3325            ComponentDefinedType::Primitive(_) => true,
3326
3327            // These structures are never allowed to be anonymous, so they
3328            // themselves must be named.
3329            ComponentDefinedType::Flags(_)
3330            | ComponentDefinedType::Enum(_)
3331            | ComponentDefinedType::Record(_)
3332            | ComponentDefinedType::Variant(_) => set.contains(&ComponentAnyTypeId::from(id)),
3333
3334            // All types below here are allowed to be anonymous, but their
3335            // own components must be appropriately named.
3336            ComponentDefinedType::Tuple(r) => {
3337                r.types.iter().all(|t| self.type_named_valtype(t, set))
3338            }
3339            ComponentDefinedType::Result { ok, err } => {
3340                ok.as_ref()
3341                    .map(|t| self.type_named_valtype(t, set))
3342                    .unwrap_or(true)
3343                    && err
3344                        .as_ref()
3345                        .map(|t| self.type_named_valtype(t, set))
3346                        .unwrap_or(true)
3347            }
3348            ComponentDefinedType::List(ty) | ComponentDefinedType::Option(ty) => {
3349                self.type_named_valtype(ty, set)
3350            }
3351
3352            // own/borrow themselves don't have to be named, but the resource
3353            // they refer to must be named.
3354            ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
3355                set.contains(&ComponentAnyTypeId::from(*id))
3356            }
3357        }
3358    }
3359
3360    pub(crate) fn type_named_valtype(
3361        &self,
3362        ty: &ComponentValType,
3363        set: &Set<ComponentAnyTypeId>,
3364    ) -> bool {
3365        match ty {
3366            ComponentValType::Primitive(_) => true,
3367            ComponentValType::Type(id) => self.type_named_type_id(*id, set),
3368        }
3369    }
3370}
3371
3372/// A helper trait to provide the functionality necessary to resources within a
3373/// type.
3374///
3375/// This currently exists to abstract over `TypeAlloc` and `SubtypeArena` which
3376/// both need to perform remapping operations.
3377pub trait Remap
3378where
3379    Self: Index<ComponentTypeId, Output = ComponentType>,
3380    Self: Index<ComponentDefinedTypeId, Output = ComponentDefinedType>,
3381    Self: Index<ComponentInstanceTypeId, Output = ComponentInstanceType>,
3382    Self: Index<ComponentFuncTypeId, Output = ComponentFuncType>,
3383{
3384    /// Pushes a new anonymous type within this object, returning an identifier
3385    /// which can be used to refer to it.
3386    fn push_ty<T>(&mut self, ty: T) -> T::Id
3387    where
3388        T: TypeData;
3389
3390    /// Apply `map` to the keys of `tmp`, setting `*any_changed = true` if any
3391    /// keys were remapped.
3392    fn map_map(
3393        tmp: &mut IndexMap<ResourceId, Vec<usize>>,
3394        any_changed: &mut bool,
3395        map: &Remapping,
3396    ) {
3397        for (id, path) in mem::take(tmp) {
3398            let id = match map.resources.get(&id) {
3399                Some(id) => {
3400                    *any_changed = true;
3401                    *id
3402                }
3403                None => id,
3404            };
3405            tmp.insert(id, path);
3406        }
3407    }
3408
3409    /// If `any_changed` is true, push `ty`, update `map` to point `id` to the
3410    /// new type ID, set `id` equal to the new type ID, and return `true`.
3411    /// Otherwise, update `map` to point `id` to itself and return `false`.
3412    fn insert_if_any_changed<T>(
3413        &mut self,
3414        map: &mut Remapping,
3415        any_changed: bool,
3416        id: &mut T::Id,
3417        ty: T,
3418    ) -> bool
3419    where
3420        T: TypeData,
3421        T::Id: Into<ComponentAnyTypeId>,
3422    {
3423        let new = if any_changed { self.push_ty(ty) } else { *id };
3424        map.types.insert((*id).into(), new.into());
3425        let changed = *id != new;
3426        *id = new;
3427        changed
3428    }
3429
3430    /// Recursively search for any resource types reachable from `id`, updating
3431    /// it and `map` if any are found and remapped, returning `true` iff at last
3432    /// one is remapped.
3433    fn remap_component_any_type_id(
3434        &mut self,
3435        id: &mut ComponentAnyTypeId,
3436        map: &mut Remapping,
3437    ) -> bool {
3438        match id {
3439            ComponentAnyTypeId::Resource(id) => self.remap_resource_id(id, map),
3440            ComponentAnyTypeId::Defined(id) => self.remap_component_defined_type_id(id, map),
3441            ComponentAnyTypeId::Func(id) => self.remap_component_func_type_id(id, map),
3442            ComponentAnyTypeId::Instance(id) => self.remap_component_instance_type_id(id, map),
3443            ComponentAnyTypeId::Component(id) => self.remap_component_type_id(id, map),
3444        }
3445    }
3446
3447    /// If `map` indicates `id` should be remapped, update it and return `true`.
3448    /// Otherwise, do nothing and return `false`.
3449    fn remap_resource_id(&mut self, id: &mut AliasableResourceId, map: &Remapping) -> bool {
3450        if let Some(changed) = map.remap_id(id) {
3451            return changed;
3452        }
3453
3454        match map.resources.get(&id.resource()) {
3455            None => false,
3456            Some(new_id) => {
3457                *id.resource_mut() = *new_id;
3458                true
3459            }
3460        }
3461    }
3462
3463    /// Recursively search for any resource types reachable from `id`, updating
3464    /// it and `map` if any are found and remapped, returning `true` iff at last
3465    /// one is remapped.
3466    fn remap_component_type_id(&mut self, id: &mut ComponentTypeId, map: &mut Remapping) -> bool {
3467        if let Some(changed) = map.remap_id(id) {
3468            return changed;
3469        }
3470
3471        let mut any_changed = false;
3472        let mut ty = self[*id].clone();
3473        for ty in ty.imports.values_mut().chain(ty.exports.values_mut()) {
3474            any_changed |= self.remap_component_entity(ty, map);
3475        }
3476        for (id, _) in ty
3477            .imported_resources
3478            .iter_mut()
3479            .chain(&mut ty.defined_resources)
3480        {
3481            if let Some(new) = map.resources.get(id) {
3482                *id = *new;
3483                any_changed = true;
3484            }
3485        }
3486        Self::map_map(&mut ty.explicit_resources, &mut any_changed, map);
3487        self.insert_if_any_changed(map, any_changed, id, ty)
3488    }
3489
3490    /// Recursively search for any resource types reachable from `id`, updating
3491    /// it and `map` if any are found and remapped, returning `true` iff at last
3492    /// one is remapped.
3493    fn remap_component_defined_type_id(
3494        &mut self,
3495        id: &mut ComponentDefinedTypeId,
3496        map: &mut Remapping,
3497    ) -> bool {
3498        if let Some(changed) = map.remap_id(id) {
3499            return changed;
3500        }
3501
3502        let mut any_changed = false;
3503        let mut tmp = self[*id].clone();
3504        match &mut tmp {
3505            ComponentDefinedType::Primitive(_)
3506            | ComponentDefinedType::Flags(_)
3507            | ComponentDefinedType::Enum(_) => {}
3508            ComponentDefinedType::Record(r) => {
3509                for ty in r.fields.values_mut() {
3510                    any_changed |= self.remap_valtype(ty, map);
3511                }
3512            }
3513            ComponentDefinedType::Tuple(r) => {
3514                for ty in r.types.iter_mut() {
3515                    any_changed |= self.remap_valtype(ty, map);
3516                }
3517            }
3518            ComponentDefinedType::Variant(r) => {
3519                for ty in r.cases.values_mut() {
3520                    if let Some(ty) = &mut ty.ty {
3521                        any_changed |= self.remap_valtype(ty, map);
3522                    }
3523                }
3524            }
3525            ComponentDefinedType::List(ty) | ComponentDefinedType::Option(ty) => {
3526                any_changed |= self.remap_valtype(ty, map);
3527            }
3528            ComponentDefinedType::Result { ok, err } => {
3529                if let Some(ok) = ok {
3530                    any_changed |= self.remap_valtype(ok, map);
3531                }
3532                if let Some(err) = err {
3533                    any_changed |= self.remap_valtype(err, map);
3534                }
3535            }
3536            ComponentDefinedType::Own(id) | ComponentDefinedType::Borrow(id) => {
3537                any_changed |= self.remap_resource_id(id, map);
3538            }
3539        }
3540        self.insert_if_any_changed(map, any_changed, id, tmp)
3541    }
3542
3543    /// Recursively search for any resource types reachable from `id`, updating
3544    /// it and `map` if any are found and remapped, returning `true` iff at last
3545    /// one is remapped.
3546    fn remap_component_instance_type_id(
3547        &mut self,
3548        id: &mut ComponentInstanceTypeId,
3549        map: &mut Remapping,
3550    ) -> bool {
3551        if let Some(changed) = map.remap_id(id) {
3552            return changed;
3553        }
3554
3555        let mut any_changed = false;
3556        let mut tmp = self[*id].clone();
3557        for ty in tmp.exports.values_mut() {
3558            any_changed |= self.remap_component_entity(ty, map);
3559        }
3560        for id in tmp.defined_resources.iter_mut() {
3561            if let Some(new) = map.resources.get(id) {
3562                *id = *new;
3563                any_changed = true;
3564            }
3565        }
3566        Self::map_map(&mut tmp.explicit_resources, &mut any_changed, map);
3567        self.insert_if_any_changed(map, any_changed, id, tmp)
3568    }
3569
3570    /// Recursively search for any resource types reachable from `id`, updating
3571    /// it and `map` if any are found and remapped, returning `true` iff at last
3572    /// one is remapped.
3573    fn remap_component_func_type_id(
3574        &mut self,
3575        id: &mut ComponentFuncTypeId,
3576        map: &mut Remapping,
3577    ) -> bool {
3578        if let Some(changed) = map.remap_id(id) {
3579            return changed;
3580        }
3581
3582        let mut any_changed = false;
3583        let mut tmp = self[*id].clone();
3584        for ty in tmp
3585            .params
3586            .iter_mut()
3587            .map(|(_, ty)| ty)
3588            .chain(tmp.results.iter_mut().map(|(_, ty)| ty))
3589        {
3590            any_changed |= self.remap_valtype(ty, map);
3591        }
3592        self.insert_if_any_changed(map, any_changed, id, tmp)
3593    }
3594
3595    /// Same as `remap_type_id`, but works with `ComponentEntityType`.
3596    fn remap_component_entity(
3597        &mut self,
3598        ty: &mut ComponentEntityType,
3599        map: &mut Remapping,
3600    ) -> bool {
3601        match ty {
3602            ComponentEntityType::Module(_) => {
3603                // Can't reference resources.
3604                false
3605            }
3606            ComponentEntityType::Func(id) => self.remap_component_func_type_id(id, map),
3607            ComponentEntityType::Instance(id) => self.remap_component_instance_type_id(id, map),
3608            ComponentEntityType::Component(id) => self.remap_component_type_id(id, map),
3609            ComponentEntityType::Type {
3610                referenced,
3611                created,
3612            } => {
3613                let mut changed = self.remap_component_any_type_id(referenced, map);
3614                if *referenced == *created {
3615                    *created = *referenced;
3616                } else {
3617                    changed |= self.remap_component_any_type_id(created, map);
3618                }
3619                changed
3620            }
3621            ComponentEntityType::Value(ty) => self.remap_valtype(ty, map),
3622        }
3623    }
3624
3625    /// Same as `remap_type_id`, but works with `ComponentValType`.
3626    fn remap_valtype(&mut self, ty: &mut ComponentValType, map: &mut Remapping) -> bool {
3627        match ty {
3628            ComponentValType::Primitive(_) => false,
3629            ComponentValType::Type(id) => self.remap_component_defined_type_id(id, map),
3630        }
3631    }
3632}
3633
3634/// Utility for mapping equivalent `ResourceId`s to each other and (when paired with the `Remap` trait)
3635/// non-destructively edit type lists to reflect those mappings.
3636#[derive(Debug, Default)]
3637pub struct Remapping {
3638    /// A mapping from old resource ID to new resource ID.
3639    pub(crate) resources: Map<ResourceId, ResourceId>,
3640
3641    /// A mapping filled in during the remapping process which records how a
3642    /// type was remapped, if applicable. This avoids remapping multiple
3643    /// references to the same type and instead only processing it once.
3644    types: Map<ComponentAnyTypeId, ComponentAnyTypeId>,
3645}
3646
3647impl Remap for TypeAlloc {
3648    fn push_ty<T>(&mut self, ty: T) -> T::Id
3649    where
3650        T: TypeData,
3651    {
3652        <TypeList>::push(self, ty)
3653    }
3654}
3655
3656impl<T> Index<T> for TypeAlloc
3657where
3658    T: TypeIdentifier,
3659{
3660    type Output = T::Data;
3661
3662    #[inline]
3663    fn index(&self, id: T) -> &T::Data {
3664        &self.list[id]
3665    }
3666}
3667
3668impl Remapping {
3669    /// Add a mapping from the specified old resource ID to the new resource ID
3670    pub fn add(&mut self, old: ResourceId, new: ResourceId) {
3671        self.resources.insert(old, new);
3672    }
3673
3674    /// Clear the type cache while leaving the resource mappings intact.
3675    pub fn reset_type_cache(&mut self) {
3676        self.types.clear()
3677    }
3678
3679    fn remap_id<T>(&self, id: &mut T) -> Option<bool>
3680    where
3681        T: Copy + Into<ComponentAnyTypeId> + TryFrom<ComponentAnyTypeId>,
3682        T::Error: core::fmt::Debug,
3683    {
3684        let old: ComponentAnyTypeId = (*id).into();
3685        let new = self.types.get(&old)?;
3686        if *new == old {
3687            Some(false)
3688        } else {
3689            *id = T::try_from(*new).expect("should never remap across different kinds");
3690            Some(true)
3691        }
3692    }
3693}
3694
3695/// Helper structure used to perform subtyping computations.
3696///
3697/// This type is used whenever a subtype needs to be tested in one direction or
3698/// the other. The methods of this type are the various entry points for
3699/// subtyping.
3700///
3701/// Internally this contains arenas for two lists of types. The `a` arena is
3702/// intended to be used for lookup of the first argument to all of the methods
3703/// below, and the `b` arena is used for lookup of the second argument.
3704///
3705/// Arenas here are used specifically for component-based subtyping queries. In
3706/// these situations new types must be created based on substitution mappings,
3707/// but the types all have temporary lifetimes. Everything in these arenas is
3708/// thrown away once the subtyping computation has finished.
3709///
3710/// Note that this subtyping context also explicitly supports being created
3711/// from to different lists `a` and `b` originally, for testing subtyping
3712/// between two different components for example.
3713pub struct SubtypeCx<'a> {
3714    /// Lookup arena for first type argument
3715    pub a: SubtypeArena<'a>,
3716    /// Lookup arena for second type argument
3717    pub b: SubtypeArena<'a>,
3718}
3719
3720impl<'a> SubtypeCx<'a> {
3721    /// Create a new instance with the specified type lists
3722    pub fn new_with_refs(a: TypesRef<'a>, b: TypesRef<'a>) -> SubtypeCx<'a> {
3723        Self::new(a.list, b.list)
3724    }
3725
3726    pub(crate) fn new(a: &'a TypeList, b: &'a TypeList) -> SubtypeCx<'a> {
3727        SubtypeCx {
3728            a: SubtypeArena::new(a),
3729            b: SubtypeArena::new(b),
3730        }
3731    }
3732
3733    /// Swap the type lists
3734    pub fn swap(&mut self) {
3735        mem::swap(&mut self.a, &mut self.b);
3736    }
3737
3738    /// Executes the closure `f`, resetting the internal arenas to their
3739    /// original size after the closure finishes.
3740    ///
3741    /// This enables `f` to modify the internal arenas while relying on all
3742    /// changes being discarded after the closure finishes.
3743    fn with_checkpoint<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
3744        let a = self.a.list.checkpoint();
3745        let b = self.b.list.checkpoint();
3746        let result = f(self);
3747        self.a.list.reset_to_checkpoint(a);
3748        self.b.list.reset_to_checkpoint(b);
3749        result
3750    }
3751
3752    /// Tests whether `a` is a subtype of `b`.
3753    ///
3754    /// Errors are reported at the `offset` specified.
3755    pub fn component_entity_type(
3756        &mut self,
3757        a: &ComponentEntityType,
3758        b: &ComponentEntityType,
3759        offset: usize,
3760    ) -> Result<()> {
3761        use ComponentEntityType::*;
3762
3763        match (a, b) {
3764            (Module(a), Module(b)) => self.module_type(*a, *b, offset),
3765            (Module(_), b) => bail!(offset, "expected {}, found module", b.desc()),
3766
3767            (Func(a), Func(b)) => self.component_func_type(*a, *b, offset),
3768            (Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
3769
3770            (Value(a), Value(b)) => self.component_val_type(a, b, offset),
3771            (Value(_), b) => bail!(offset, "expected {}, found value", b.desc()),
3772
3773            (Type { referenced: a, .. }, Type { referenced: b, .. }) => {
3774                self.component_any_type_id(*a, *b, offset)
3775            }
3776            (Type { .. }, b) => bail!(offset, "expected {}, found type", b.desc()),
3777
3778            (Instance(a), Instance(b)) => self.component_instance_type(*a, *b, offset),
3779            (Instance(_), b) => bail!(offset, "expected {}, found instance", b.desc()),
3780
3781            (Component(a), Component(b)) => self.component_type(*a, *b, offset),
3782            (Component(_), b) => bail!(offset, "expected {}, found component", b.desc()),
3783        }
3784    }
3785
3786    /// Tests whether `a` is a subtype of `b`.
3787    ///
3788    /// Errors are reported at the `offset` specified.
3789    pub fn component_type(
3790        &mut self,
3791        a: ComponentTypeId,
3792        b: ComponentTypeId,
3793        offset: usize,
3794    ) -> Result<()> {
3795        // Components are ... tricky. They follow the same basic
3796        // structure as core wasm modules, but they also have extra
3797        // logic to handle resource types. Resources are effectively
3798        // abstract types so this is sort of where an ML module system
3799        // in the component model becomes a reality.
3800        //
3801        // This also leverages the `open_instance_type` method below
3802        // heavily which internally has its own quite large suite of
3803        // logic. More-or-less what's happening here is:
3804        //
3805        // 1. Pretend that the imports of B are given as values to the
3806        //    imports of A. If A didn't import anything, for example,
3807        //    that's great and the subtyping definitely passes there.
3808        //    This operation produces a mapping of all the resources of
3809        //    A's imports to resources in B's imports.
3810        //
3811        // 2. This mapping is applied to all of A's exports. This means
3812        //    that all exports of A referring to A's imported resources
3813        //    now instead refer to B's. Note, though that A's exports
3814        //    still refer to its own defined resources.
3815        //
3816        // 3. The same `open_instance_type` method used during the
3817        //    first step is used again, but this time on the exports
3818        //    in the reverse direction. This performs a similar
3819        //    operation, though, by creating a mapping from B's
3820        //    defined resources to A's defined resources. The map
3821        //    itself is discarded as it's not needed.
3822        //
3823        // The order that everything passed here is intentional, but
3824        // also subtle. I personally think of it as
3825        // `open_instance_type` takes a list of things to satisfy a
3826        // signature and produces a mapping of resources in the
3827        // signature to those provided in the list of things. The
3828        // order of operations then goes:
3829        //
3830        // * Someone thinks they have a component of type B, but they
3831        //   actually have a component of type A (e.g. due to this
3832        //   subtype check passing).
3833        // * This person provides the imports of B and that must be
3834        //   sufficient to satisfy the imports of A. This is the first
3835        //   `open_instance_type` check.
3836        // * Now though the resources provided by B are substituted
3837        //   into A's exports since that's what was provided.
3838        // * A's exports are then handed back to the original person,
3839        //   and these exports must satisfy the signature required by B
3840        //   since that's what they're expecting.
3841        // * This is the second `open_instance_type` which, to get
3842        //   resource types to line up, will map from A's defined
3843        //   resources to B's defined resources.
3844        //
3845        // If all that passes then the resources should all line up
3846        // perfectly. Any misalignment is reported as a subtyping
3847        // error.
3848        let b_imports = self.b[b]
3849            .imports
3850            .iter()
3851            .map(|(name, ty)| (name.clone(), *ty))
3852            .collect();
3853        self.swap();
3854        let mut import_mapping =
3855            self.open_instance_type(&b_imports, a, ExternKind::Import, offset)?;
3856        self.swap();
3857        self.with_checkpoint(|this| {
3858            let mut a_exports = this.a[a]
3859                .exports
3860                .iter()
3861                .map(|(name, ty)| (name.clone(), *ty))
3862                .collect::<IndexMap<_, _>>();
3863            for ty in a_exports.values_mut() {
3864                this.a.remap_component_entity(ty, &mut import_mapping);
3865            }
3866            this.open_instance_type(&a_exports, b, ExternKind::Export, offset)?;
3867            Ok(())
3868        })
3869    }
3870
3871    /// Tests whether `a` is a subtype of `b`.
3872    ///
3873    /// Errors are reported at the `offset` specified.
3874    pub fn component_instance_type(
3875        &mut self,
3876        a_id: ComponentInstanceTypeId,
3877        b_id: ComponentInstanceTypeId,
3878        offset: usize,
3879    ) -> Result<()> {
3880        // For instance type subtyping, all exports in the other
3881        // instance type must be present in this instance type's
3882        // exports (i.e. it can export *more* than what this instance
3883        // type needs).
3884        let a = &self.a[a_id];
3885        let b = &self.b[b_id];
3886
3887        let mut exports = Vec::with_capacity(b.exports.len());
3888        for (k, b) in b.exports.iter() {
3889            match a.exports.get(k) {
3890                Some(a) => exports.push((*a, *b)),
3891                None => bail!(offset, "missing expected export `{k}`"),
3892            }
3893        }
3894        for (i, (a, b)) in exports.iter().enumerate() {
3895            let err = match self.component_entity_type(a, b, offset) {
3896                Ok(()) => continue,
3897                Err(e) => e,
3898            };
3899            // On failure attach the name of this export as context to
3900            // the error message to leave a breadcrumb trail.
3901            let (name, _) = self.b[b_id].exports.get_index(i).unwrap();
3902            return Err(err.with_context(|| format!("type mismatch in instance export `{name}`")));
3903        }
3904        Ok(())
3905    }
3906
3907    /// Tests whether `a` is a subtype of `b`.
3908    ///
3909    /// Errors are reported at the `offset` specified.
3910    pub fn component_func_type(
3911        &mut self,
3912        a: ComponentFuncTypeId,
3913        b: ComponentFuncTypeId,
3914        offset: usize,
3915    ) -> Result<()> {
3916        let a = &self.a[a];
3917        let b = &self.b[b];
3918
3919        // Note that this intentionally diverges from the upstream
3920        // specification in terms of subtyping. This is a full
3921        // type-equality check which ensures that the structure of `a`
3922        // exactly matches the structure of `b`. The rationale for this
3923        // is:
3924        //
3925        // * Primarily in Wasmtime subtyping based on function types is
3926        //   not implemented. This includes both subtyping a host
3927        //   import and additionally handling subtyping as functions
3928        //   cross component boundaries. The host import subtyping (or
3929        //   component export subtyping) is not clear how to handle at
3930        //   all at this time. The subtyping of functions between
3931        //   components can more easily be handled by extending the
3932        //   `fact` compiler, but that hasn't been done yet.
3933        //
3934        // * The upstream specification is currently pretty
3935        //   intentionally vague precisely what subtyping is allowed.
3936        //   Implementing a strict check here is intended to be a
3937        //   conservative starting point for the component model which
3938        //   can be extended in the future if necessary.
3939        //
3940        // * The interaction with subtyping on bindings generation, for
3941        //   example, is a tricky problem that doesn't have a clear
3942        //   answer at this time.  Effectively this is more rationale
3943        //   for being conservative in the first pass of the component
3944        //   model.
3945        //
3946        // So, in conclusion, the test here (and other places that
3947        // reference this comment) is for exact type equality with no
3948        // differences.
3949        if a.params.len() != b.params.len() {
3950            bail!(
3951                offset,
3952                "expected {} parameters, found {}",
3953                b.params.len(),
3954                a.params.len(),
3955            );
3956        }
3957        if a.results.len() != b.results.len() {
3958            bail!(
3959                offset,
3960                "expected {} results, found {}",
3961                b.results.len(),
3962                a.results.len(),
3963            );
3964        }
3965        for ((an, a), (bn, b)) in a.params.iter().zip(b.params.iter()) {
3966            if an != bn {
3967                bail!(offset, "expected parameter named `{bn}`, found `{an}`");
3968            }
3969            self.component_val_type(a, b, offset)
3970                .with_context(|| format!("type mismatch in function parameter `{an}`"))?;
3971        }
3972        for ((an, a), (bn, b)) in a.results.iter().zip(b.results.iter()) {
3973            if an != bn {
3974                bail!(offset, "mismatched result names");
3975            }
3976            self.component_val_type(a, b, offset)
3977                .with_context(|| "type mismatch with result type")?;
3978        }
3979        Ok(())
3980    }
3981
3982    /// Tests whether `a` is a subtype of `b`.
3983    ///
3984    /// Errors are reported at the `offset` specified.
3985    pub fn module_type(
3986        &mut self,
3987        a: ComponentCoreModuleTypeId,
3988        b: ComponentCoreModuleTypeId,
3989        offset: usize,
3990    ) -> Result<()> {
3991        // For module type subtyping, all exports in the other module
3992        // type must be present in this module type's exports (i.e. it
3993        // can export *more* than what this module type needs).
3994        // However, for imports, the check is reversed (i.e. it is okay
3995        // to import *less* than what this module type needs).
3996        self.swap();
3997        let a_imports = &self.b[a].imports;
3998        let b_imports = &self.a[b].imports;
3999        for (k, a) in a_imports {
4000            match b_imports.get(k) {
4001                Some(b) => self
4002                    .entity_type(b, a, offset)
4003                    .with_context(|| format!("type mismatch in import `{}::{}`", k.0, k.1))?,
4004                None => bail!(offset, "missing expected import `{}::{}`", k.0, k.1),
4005            }
4006        }
4007        self.swap();
4008        let a = &self.a[a];
4009        let b = &self.b[b];
4010        for (k, b) in b.exports.iter() {
4011            match a.exports.get(k) {
4012                Some(a) => self
4013                    .entity_type(a, b, offset)
4014                    .with_context(|| format!("type mismatch in export `{k}`"))?,
4015                None => bail!(offset, "missing expected export `{k}`"),
4016            }
4017        }
4018        Ok(())
4019    }
4020
4021    /// Tests whether `a` is a subtype of `b`.
4022    ///
4023    /// Errors are reported at the `offset` specified.
4024    pub fn component_any_type_id(
4025        &mut self,
4026        a: ComponentAnyTypeId,
4027        b: ComponentAnyTypeId,
4028        offset: usize,
4029    ) -> Result<()> {
4030        match (a, b) {
4031            (ComponentAnyTypeId::Resource(a), ComponentAnyTypeId::Resource(b)) => {
4032                if a.resource() == b.resource() {
4033                    Ok(())
4034                } else {
4035                    bail!(
4036                        offset,
4037                        "resource types are not the same ({:?} vs. {:?})",
4038                        a.resource(),
4039                        b.resource()
4040                    )
4041                }
4042            }
4043            (ComponentAnyTypeId::Resource(_), b) => {
4044                bail!(offset, "expected {}, found resource", b.desc())
4045            }
4046            (ComponentAnyTypeId::Defined(a), ComponentAnyTypeId::Defined(b)) => {
4047                self.component_defined_type(a, b, offset)
4048            }
4049            (ComponentAnyTypeId::Defined(_), b) => {
4050                bail!(offset, "expected {}, found defined type", b.desc())
4051            }
4052
4053            (ComponentAnyTypeId::Func(a), ComponentAnyTypeId::Func(b)) => {
4054                self.component_func_type(a, b, offset)
4055            }
4056            (ComponentAnyTypeId::Func(_), b) => {
4057                bail!(offset, "expected {}, found func type", b.desc())
4058            }
4059
4060            (ComponentAnyTypeId::Instance(a), ComponentAnyTypeId::Instance(b)) => {
4061                self.component_instance_type(a, b, offset)
4062            }
4063            (ComponentAnyTypeId::Instance(_), b) => {
4064                bail!(offset, "expected {}, found instance type", b.desc())
4065            }
4066
4067            (ComponentAnyTypeId::Component(a), ComponentAnyTypeId::Component(b)) => {
4068                self.component_type(a, b, offset)
4069            }
4070            (ComponentAnyTypeId::Component(_), b) => {
4071                bail!(offset, "expected {}, found component type", b.desc())
4072            }
4073        }
4074    }
4075
4076    /// The building block for subtyping checks when components are
4077    /// instantiated and when components are tested if they're subtypes of each
4078    /// other.
4079    ///
4080    /// This method takes a number of arguments:
4081    ///
4082    /// * `a` - this is a list of typed items which can be thought of as
4083    ///   concrete values to test against `b`.
4084    /// * `b` - this `TypeId` must point to `Type::Component`.
4085    /// * `kind` - indicates whether the `imports` or `exports` of `b` are
4086    ///   being tested against for the values in `a`.
4087    /// * `offset` - the binary offset at which to report errors if one happens.
4088    ///
4089    /// This will attempt to determine if the items in `a` satisfy the
4090    /// signature required by the `kind` items of `b`. For example component
4091    /// instantiation will have `a` as the list of arguments provided to
4092    /// instantiation, `b` is the component being instantiated, and `kind` is
4093    /// `ExternKind::Import`.
4094    ///
4095    /// This function, if successful, will return a mapping of the resources in
4096    /// `b` to the resources in `a` provided. This mapping is guaranteed to
4097    /// contain all the resources for `b` (all imported resources for
4098    /// `ExternKind::Import` or all defined resources for `ExternKind::Export`).
4099    pub fn open_instance_type(
4100        &mut self,
4101        a: &IndexMap<String, ComponentEntityType>,
4102        b: ComponentTypeId,
4103        kind: ExternKind,
4104        offset: usize,
4105    ) -> Result<Remapping> {
4106        // First, determine the mapping from resources in `b` to those supplied
4107        // by arguments in `a`.
4108        //
4109        // This loop will iterate over all the appropriate resources in `b`
4110        // and find the corresponding resource in `args`. The exact lists
4111        // in use here depend on the `kind` provided. This necessarily requires
4112        // a sequence of string lookups to find the corresponding items in each
4113        // list.
4114        //
4115        // The path to each resource in `resources` is precomputed as a list of
4116        // indexes. The first index is into `b`'s list of `entities`, and gives
4117        // the name that `b` assigns to the resource.  Each subsequent index,
4118        // if present, means that this resource was present through a layer of
4119        // an instance type, and the index is into the instance type's exports.
4120        // More information about this can be found on
4121        // `ComponentState::imported_resources`.
4122        //
4123        // This loop will follow the list of indices for each resource and, at
4124        // the same time, walk through the arguments supplied to instantiating
4125        // the `component_type`. This means that within `component_type`
4126        // index-based lookups are performed while in `args` name-based
4127        // lookups are performed.
4128        //
4129        // Note that here it's possible that `args` doesn't actually supply the
4130        // correct type of import for each item since argument checking has
4131        // not proceeded yet. These type errors, however, aren't handled by
4132        // this loop and are deferred below to the main subtyping check. That
4133        // means that `mapping` won't necessarily have a mapping for all
4134        // imported resources into `component_type`, but that should be ok.
4135        let component_type = &self.b[b];
4136        let entities = match kind {
4137            ExternKind::Import => &component_type.imports,
4138            ExternKind::Export => &component_type.exports,
4139        };
4140        let resources = match kind {
4141            ExternKind::Import => &component_type.imported_resources,
4142            ExternKind::Export => &component_type.defined_resources,
4143        };
4144        let mut mapping = Remapping::default();
4145        'outer: for (resource, path) in resources.iter() {
4146            // Lookup the first path item in `imports` and the corresponding
4147            // entry in `args` by name.
4148            let (name, ty) = entities.get_index(path[0]).unwrap();
4149            let mut ty = *ty;
4150            let mut arg = a.get(name);
4151
4152            // Lookup all the subsequent `path` entries, if any, by index in
4153            // `ty` and by name in `arg`. Type errors in `arg` are skipped over
4154            // entirely.
4155            for i in path.iter().skip(1).copied() {
4156                let id = match ty {
4157                    ComponentEntityType::Instance(id) => id,
4158                    _ => unreachable!(),
4159                };
4160                let (name, next_ty) = self.b[id].exports.get_index(i).unwrap();
4161                ty = *next_ty;
4162                arg = match arg {
4163                    Some(ComponentEntityType::Instance(id)) => self.a[*id].exports.get(name),
4164                    _ => continue 'outer,
4165                };
4166            }
4167
4168            // Double-check that `ty`, the leaf type of `component_type`, is
4169            // indeed the expected resource.
4170            if cfg!(debug_assertions) {
4171                let id = match ty {
4172                    ComponentEntityType::Type { created, .. } => match created {
4173                        ComponentAnyTypeId::Resource(id) => id.resource(),
4174                        _ => unreachable!(),
4175                    },
4176                    _ => unreachable!(),
4177                };
4178                assert_eq!(id, *resource);
4179            }
4180
4181            // The leaf of `arg` should be a type which is a resource. If not
4182            // it's skipped and this'll wind up generating an error later on in
4183            // subtype checking below.
4184            if let Some(ComponentEntityType::Type { created, .. }) = arg {
4185                if let ComponentAnyTypeId::Resource(r) = created {
4186                    mapping.resources.insert(*resource, r.resource());
4187                }
4188            }
4189        }
4190
4191        // Now that a mapping from the resources in `b` to the resources in `a`
4192        // has been determined it's possible to perform the actual subtype
4193        // check.
4194        //
4195        // This subtype check notably needs to ensure that all resource types
4196        // line up. To achieve this the `mapping` previously calculated is used
4197        // to perform a substitution on each component entity type.
4198        //
4199        // The first loop here performs a name lookup to create a list of
4200        // values from `a` to expected items in `b`. Once the list is created
4201        // the substitution check is performed on each element.
4202        let mut to_typecheck = Vec::new();
4203        for (name, expected) in entities.iter() {
4204            match a.get(name) {
4205                Some(arg) => to_typecheck.push((*arg, *expected)),
4206                None => bail!(offset, "missing {} named `{name}`", kind.desc()),
4207            }
4208        }
4209        let mut type_map = Map::default();
4210        for (i, (actual, expected)) in to_typecheck.into_iter().enumerate() {
4211            let result = self.with_checkpoint(|this| {
4212                let mut expected = expected;
4213                this.b.remap_component_entity(&mut expected, &mut mapping);
4214                mapping.types.clear();
4215                this.component_entity_type(&actual, &expected, offset)
4216            });
4217            let err = match result {
4218                Ok(()) => {
4219                    // On a successful type-check record a mapping of
4220                    // type-to-type in `type_map` for any type imports that were
4221                    // satisfied. This is then used afterwards when performing
4222                    // type substitution to remap all component-local types to
4223                    // those that were provided in the imports.
4224                    self.register_type_renamings(actual, expected, &mut type_map);
4225                    continue;
4226                }
4227                Err(e) => e,
4228            };
4229
4230            // If an error happens then attach the name of the entity to the
4231            // error message using the `i` iteration counter.
4232            let component_type = &self.b[b];
4233            let entities = match kind {
4234                ExternKind::Import => &component_type.imports,
4235                ExternKind::Export => &component_type.exports,
4236            };
4237            let (name, _) = entities.get_index(i).unwrap();
4238            return Err(err.with_context(|| format!("type mismatch for {} `{name}`", kind.desc())));
4239        }
4240        mapping.types = type_map;
4241        Ok(mapping)
4242    }
4243
4244    pub(crate) fn entity_type(&self, a: &EntityType, b: &EntityType, offset: usize) -> Result<()> {
4245        macro_rules! limits_match {
4246            ($a:expr, $b:expr) => {{
4247                let a = $a;
4248                let b = $b;
4249                a.initial >= b.initial
4250                    && match b.maximum {
4251                        Some(b_max) => match a.maximum {
4252                            Some(a_max) => a_max <= b_max,
4253                            None => false,
4254                        },
4255                        None => true,
4256                    }
4257            }};
4258        }
4259
4260        match (a, b) {
4261            (EntityType::Func(a), EntityType::Func(b)) => {
4262                self.core_func_type(self.a[*a].unwrap_func(), self.b[*b].unwrap_func(), offset)
4263            }
4264            (EntityType::Func(_), b) => bail!(offset, "expected {}, found func", b.desc()),
4265            (EntityType::Table(a), EntityType::Table(b)) => {
4266                if a.element_type != b.element_type {
4267                    bail!(
4268                        offset,
4269                        "expected table element type {}, found {}",
4270                        b.element_type,
4271                        a.element_type,
4272                    )
4273                }
4274                if limits_match!(a, b) {
4275                    Ok(())
4276                } else {
4277                    bail!(offset, "mismatch in table limits")
4278                }
4279            }
4280            (EntityType::Table(_), b) => bail!(offset, "expected {}, found table", b.desc()),
4281            (EntityType::Memory(a), EntityType::Memory(b)) => {
4282                if a.shared != b.shared {
4283                    bail!(offset, "mismatch in the shared flag for memories")
4284                }
4285                if a.memory64 != b.memory64 {
4286                    bail!(offset, "mismatch in index type used for memories")
4287                }
4288                if limits_match!(a, b) {
4289                    Ok(())
4290                } else {
4291                    bail!(offset, "mismatch in memory limits")
4292                }
4293            }
4294            (EntityType::Memory(_), b) => bail!(offset, "expected {}, found memory", b.desc()),
4295            (EntityType::Global(a), EntityType::Global(b)) => {
4296                if a.mutable != b.mutable {
4297                    bail!(offset, "global types differ in mutability")
4298                }
4299                if a.content_type == b.content_type {
4300                    Ok(())
4301                } else {
4302                    bail!(
4303                        offset,
4304                        "expected global type {}, found {}",
4305                        b.content_type,
4306                        a.content_type,
4307                    )
4308                }
4309            }
4310            (EntityType::Global(_), b) => bail!(offset, "expected {}, found global", b.desc()),
4311            (EntityType::Tag(a), EntityType::Tag(b)) => {
4312                self.core_func_type(self.a[*a].unwrap_func(), self.b[*b].unwrap_func(), offset)
4313            }
4314            (EntityType::Tag(_), b) => bail!(offset, "expected {}, found tag", b.desc()),
4315        }
4316    }
4317
4318    fn core_func_type(&self, a: &FuncType, b: &FuncType, offset: usize) -> Result<()> {
4319        if a == b {
4320            Ok(())
4321        } else {
4322            bail!(
4323                offset,
4324                "expected: {}\n\
4325                 found:    {}",
4326                b.desc(),
4327                a.desc(),
4328            )
4329        }
4330    }
4331
4332    pub(crate) fn component_val_type(
4333        &self,
4334        a: &ComponentValType,
4335        b: &ComponentValType,
4336        offset: usize,
4337    ) -> Result<()> {
4338        match (a, b) {
4339            (ComponentValType::Primitive(a), ComponentValType::Primitive(b)) => {
4340                self.primitive_val_type(*a, *b, offset)
4341            }
4342            (ComponentValType::Type(a), ComponentValType::Type(b)) => {
4343                self.component_defined_type(*a, *b, offset)
4344            }
4345            (ComponentValType::Primitive(a), ComponentValType::Type(b)) => match &self.b[*b] {
4346                ComponentDefinedType::Primitive(b) => self.primitive_val_type(*a, *b, offset),
4347                b => bail!(offset, "expected {}, found {a}", b.desc()),
4348            },
4349            (ComponentValType::Type(a), ComponentValType::Primitive(b)) => match &self.a[*a] {
4350                ComponentDefinedType::Primitive(a) => self.primitive_val_type(*a, *b, offset),
4351                a => bail!(offset, "expected {b}, found {}", a.desc()),
4352            },
4353        }
4354    }
4355
4356    fn component_defined_type(
4357        &self,
4358        a: ComponentDefinedTypeId,
4359        b: ComponentDefinedTypeId,
4360        offset: usize,
4361    ) -> Result<()> {
4362        use ComponentDefinedType::*;
4363
4364        // Note that the implementation of subtyping here diverges from the
4365        // upstream specification intentionally, see the documentation on
4366        // function subtyping for more information.
4367        match (&self.a[a], &self.b[b]) {
4368            (Primitive(a), Primitive(b)) => self.primitive_val_type(*a, *b, offset),
4369            (Primitive(a), b) => bail!(offset, "expected {}, found {a}", b.desc()),
4370            (Record(a), Record(b)) => {
4371                if a.fields.len() != b.fields.len() {
4372                    bail!(
4373                        offset,
4374                        "expected {} fields, found {}",
4375                        b.fields.len(),
4376                        a.fields.len(),
4377                    );
4378                }
4379
4380                for ((aname, a), (bname, b)) in a.fields.iter().zip(b.fields.iter()) {
4381                    if aname != bname {
4382                        bail!(offset, "expected field name `{bname}`, found `{aname}`");
4383                    }
4384                    self.component_val_type(a, b, offset)
4385                        .with_context(|| format!("type mismatch in record field `{aname}`"))?;
4386                }
4387                Ok(())
4388            }
4389            (Record(_), b) => bail!(offset, "expected {}, found record", b.desc()),
4390            (Variant(a), Variant(b)) => {
4391                if a.cases.len() != b.cases.len() {
4392                    bail!(
4393                        offset,
4394                        "expected {} cases, found {}",
4395                        b.cases.len(),
4396                        a.cases.len(),
4397                    );
4398                }
4399                for ((aname, a), (bname, b)) in a.cases.iter().zip(b.cases.iter()) {
4400                    if aname != bname {
4401                        bail!(offset, "expected case named `{bname}`, found `{aname}`");
4402                    }
4403                    match (&a.ty, &b.ty) {
4404                        (Some(a), Some(b)) => self
4405                            .component_val_type(a, b, offset)
4406                            .with_context(|| format!("type mismatch in variant case `{aname}`"))?,
4407                        (None, None) => {}
4408                        (None, Some(_)) => {
4409                            bail!(offset, "expected case `{aname}` to have a type, found none")
4410                        }
4411                        (Some(_), None) => bail!(offset, "expected case `{aname}` to have no type"),
4412                    }
4413                }
4414                Ok(())
4415            }
4416            (Variant(_), b) => bail!(offset, "expected {}, found variant", b.desc()),
4417            (List(a), List(b)) | (Option(a), Option(b)) => self.component_val_type(a, b, offset),
4418            (List(_), b) => bail!(offset, "expected {}, found list", b.desc()),
4419            (Option(_), b) => bail!(offset, "expected {}, found option", b.desc()),
4420            (Tuple(a), Tuple(b)) => {
4421                if a.types.len() != b.types.len() {
4422                    bail!(
4423                        offset,
4424                        "expected {} types, found {}",
4425                        b.types.len(),
4426                        a.types.len(),
4427                    );
4428                }
4429                for (i, (a, b)) in a.types.iter().zip(b.types.iter()).enumerate() {
4430                    self.component_val_type(a, b, offset)
4431                        .with_context(|| format!("type mismatch in tuple field {i}"))?;
4432                }
4433                Ok(())
4434            }
4435            (Tuple(_), b) => bail!(offset, "expected {}, found tuple", b.desc()),
4436            (at @ Flags(a), Flags(b)) | (at @ Enum(a), Enum(b)) => {
4437                let desc = match at {
4438                    Flags(_) => "flags",
4439                    _ => "enum",
4440                };
4441                if a.len() == b.len() && a.iter().eq(b.iter()) {
4442                    Ok(())
4443                } else {
4444                    bail!(offset, "mismatch in {desc} elements")
4445                }
4446            }
4447            (Flags(_), b) => bail!(offset, "expected {}, found flags", b.desc()),
4448            (Enum(_), b) => bail!(offset, "expected {}, found enum", b.desc()),
4449            (Result { ok: ao, err: ae }, Result { ok: bo, err: be }) => {
4450                match (ao, bo) {
4451                    (None, None) => {}
4452                    (Some(a), Some(b)) => self
4453                        .component_val_type(a, b, offset)
4454                        .with_context(|| "type mismatch in ok variant")?,
4455                    (None, Some(_)) => bail!(offset, "expected ok type, but found none"),
4456                    (Some(_), None) => bail!(offset, "expected ok type to not be present"),
4457                }
4458                match (ae, be) {
4459                    (None, None) => {}
4460                    (Some(a), Some(b)) => self
4461                        .component_val_type(a, b, offset)
4462                        .with_context(|| "type mismatch in err variant")?,
4463                    (None, Some(_)) => bail!(offset, "expected err type, but found none"),
4464                    (Some(_), None) => bail!(offset, "expected err type to not be present"),
4465                }
4466                Ok(())
4467            }
4468            (Result { .. }, b) => bail!(offset, "expected {}, found result", b.desc()),
4469            (Own(a), Own(b)) | (Borrow(a), Borrow(b)) => {
4470                if a.resource() == b.resource() {
4471                    Ok(())
4472                } else {
4473                    bail!(offset, "resource types are not the same")
4474                }
4475            }
4476            (Own(_), b) => bail!(offset, "expected {}, found own", b.desc()),
4477            (Borrow(_), b) => bail!(offset, "expected {}, found borrow", b.desc()),
4478        }
4479    }
4480
4481    fn primitive_val_type(
4482        &self,
4483        a: PrimitiveValType,
4484        b: PrimitiveValType,
4485        offset: usize,
4486    ) -> Result<()> {
4487        // Note that this intentionally diverges from the upstream specification
4488        // at this time and only considers exact equality for subtyping
4489        // relationships.
4490        //
4491        // More information can be found in the subtyping implementation for
4492        // component functions.
4493        if a == b {
4494            Ok(())
4495        } else {
4496            bail!(offset, "expected primitive `{b}` found primitive `{a}`")
4497        }
4498    }
4499
4500    fn register_type_renamings(
4501        &self,
4502        actual: ComponentEntityType,
4503        expected: ComponentEntityType,
4504        type_map: &mut Map<ComponentAnyTypeId, ComponentAnyTypeId>,
4505    ) {
4506        match (expected, actual) {
4507            (
4508                ComponentEntityType::Type {
4509                    created: expected, ..
4510                },
4511                ComponentEntityType::Type {
4512                    created: actual, ..
4513                },
4514            ) => {
4515                let prev = type_map.insert(expected, actual);
4516                assert!(prev.is_none());
4517            }
4518            (ComponentEntityType::Instance(expected), ComponentEntityType::Instance(actual)) => {
4519                let actual = &self.a[actual];
4520                for (name, expected) in self.b[expected].exports.iter() {
4521                    let actual = actual.exports[name];
4522                    self.register_type_renamings(actual, *expected, type_map);
4523                }
4524            }
4525            _ => {}
4526        }
4527    }
4528}
4529
4530/// A helper typed used purely during subtyping as part of `SubtypeCx`.
4531///
4532/// This takes a `types` list as input which is the "base" of the ids that can
4533/// be indexed through this arena. All future types pushed into this, if any,
4534/// are stored in `self.list`.
4535///
4536/// This is intended to have arena-like behavior where everything pushed onto
4537/// `self.list` is thrown away after a subtyping computation is performed. All
4538/// new types pushed into this arena are purely temporary.
4539pub struct SubtypeArena<'a> {
4540    types: &'a TypeList,
4541    list: TypeList,
4542}
4543
4544impl<'a> SubtypeArena<'a> {
4545    fn new(types: &'a TypeList) -> SubtypeArena<'a> {
4546        SubtypeArena {
4547            types,
4548            list: TypeList::default(),
4549        }
4550    }
4551}
4552
4553impl<T> Index<T> for SubtypeArena<'_>
4554where
4555    T: TypeIdentifier,
4556{
4557    type Output = T::Data;
4558
4559    fn index(&self, id: T) -> &T::Data {
4560        let index = id.index();
4561        if index < T::list(self.types).len() {
4562            &self.types[id]
4563        } else {
4564            let temp_index = index - T::list(self.types).len();
4565            let temp_index = u32::try_from(temp_index).unwrap();
4566            let temp_id = T::from_index(temp_index);
4567            &self.list[temp_id]
4568        }
4569    }
4570}
4571
4572impl Remap for SubtypeArena<'_> {
4573    fn push_ty<T>(&mut self, ty: T) -> T::Id
4574    where
4575        T: TypeData,
4576    {
4577        let index = T::Id::list(&self.list).len() + T::Id::list(self.types).len();
4578        let index = u32::try_from(index).unwrap();
4579        self.list.push(ty);
4580        T::Id::from_index(index)
4581    }
4582}
4583
4584/// Helper trait for adding contextual information to an error, modeled after
4585/// `anyhow::Context`.
4586pub(crate) trait Context {
4587    fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4588    where
4589        S: Into<String>;
4590}
4591
4592impl<T> Context for Result<T> {
4593    fn with_context<S>(self, context: impl FnOnce() -> S) -> Self
4594    where
4595        S: Into<String>,
4596    {
4597        match self {
4598            Ok(val) => Ok(val),
4599            Err(e) => Err(e.with_context(context)),
4600        }
4601    }
4602}
4603
4604impl Context for BinaryReaderError {
4605    fn with_context<S>(mut self, context: impl FnOnce() -> S) -> Self
4606    where
4607        S: Into<String>,
4608    {
4609        self.add_context(context().into());
4610        self
4611    }
4612}