Skip to main content

wasmparser/validator/
component_types.rs

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