Skip to main content

wasmtime/runtime/component/
types.rs

1//! This module defines the `Type` type, representing the dynamic form of a component interface type.
2
3#[cfg(feature = "component-model-async")]
4use crate::component::ComponentType;
5use crate::component::matching::InstanceType;
6use crate::component::{ResourceAny, Val};
7use crate::{AsContextMut, Engine, ExternType, FuncType, StoreContextMut, prelude::*};
8use alloc::sync::Arc;
9use core::fmt;
10use core::ops::Deref;
11use wasmtime_environ::PanicOnOom as _;
12use wasmtime_environ::component::{
13    ComponentTypes, Export, InterfaceType, ResourceIndex, TypeComponentIndex,
14    TypeComponentInstanceIndex, TypeDef, TypeEnumIndex, TypeFixedLengthListIndex, TypeFlagsIndex,
15    TypeFuncIndex, TypeFutureIndex, TypeFutureTableIndex, TypeListIndex, TypeMapIndex,
16    TypeModuleIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTable, TypeResourceTableIndex,
17    TypeResultIndex, TypeStreamIndex, TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex,
18    alternate_lookup_key,
19};
20
21pub use crate::component::resources::ResourceType;
22
23/// An owned and `'static` handle for type information in a component.
24///
25/// The components here are:
26///
27/// * `index` - a `TypeFooIndex` defined in the `wasmtime_environ` crate. This
28///   then points into the next field of...
29///
30/// * `types` - this is an allocation originally created from compilation and is
31///   stored in a compiled `Component`. This contains all types necessary and
32///   information about recursive structures and all other type information
33///   within the component. The above `index` points into this structure.
34///
35/// * `resources` - this is used to "close the loop" and represent a concrete
36///   instance type rather than an abstract component type. Instantiating a
37///   component with different resources produces different instance types but
38///   the same underlying component type, so this field serves the purpose to
39///   distinguish instance types from one another. This is runtime state created
40///   during instantiation and threaded through here. Note that if this field
41///   is `None` then this represents an abstract uninstantiated component type.
42#[derive(Clone)]
43struct Handle<T> {
44    index: T,
45    types: Arc<ComponentTypes>,
46    resources: Option<Arc<TryPrimaryMap<ResourceIndex, ResourceType>>>,
47}
48
49impl<T> Handle<T> {
50    fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
51        Handle {
52            index,
53            types: ty.types.clone(),
54            resources: ty.resources.cloned(),
55        }
56    }
57
58    fn instance(&self) -> InstanceType<'_> {
59        InstanceType {
60            types: &self.types,
61            resources: self.resources.as_ref(),
62        }
63    }
64
65    fn equivalent<'a>(
66        &'a self,
67        other: &'a Self,
68        type_check: fn(&TypeChecker<'a>, T, T) -> bool,
69    ) -> bool
70    where
71        T: PartialEq + Copy,
72    {
73        (self.index == other.index
74            && Arc::ptr_eq(&self.types, &other.types)
75            && match (&self.resources, &other.resources) {
76                (Some(a), Some(b)) => Arc::ptr_eq(a, b),
77                (None, None) => true,
78                _ => false,
79            })
80            || type_check(
81                &TypeChecker {
82                    a_types: &self.types,
83                    b_types: &other.types,
84                    a_resource: self.resources.as_deref(),
85                    b_resource: other.resources.as_deref(),
86                },
87                self.index,
88                other.index,
89            )
90    }
91}
92
93impl<T: fmt::Debug> fmt::Debug for Handle<T> {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        f.debug_struct("Handle")
96            .field("index", &self.index)
97            .finish()
98    }
99}
100
101/// Type checker between two `Handle`s
102struct TypeChecker<'a> {
103    a_types: &'a ComponentTypes,
104    a_resource: Option<&'a TryPrimaryMap<ResourceIndex, ResourceType>>,
105    b_types: &'a ComponentTypes,
106    b_resource: Option<&'a TryPrimaryMap<ResourceIndex, ResourceType>>,
107}
108
109impl TypeChecker<'_> {
110    fn interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool {
111        match (a, b) {
112            (InterfaceType::Own(o1), InterfaceType::Own(o2)) => self.resources_equal(o1, o2),
113            (InterfaceType::Own(_), _) => false,
114            (InterfaceType::Borrow(b1), InterfaceType::Borrow(b2)) => self.resources_equal(b1, b2),
115            (InterfaceType::Borrow(_), _) => false,
116            (InterfaceType::List(l1), InterfaceType::List(l2)) => self.lists_equal(l1, l2),
117            (InterfaceType::List(_), _) => false,
118            (InterfaceType::Map(m1), InterfaceType::Map(m2)) => self.maps_equal(m1, m2),
119            (InterfaceType::Map(_), _) => false,
120            (InterfaceType::Record(r1), InterfaceType::Record(r2)) => self.records_equal(r1, r2),
121            (InterfaceType::Record(_), _) => false,
122            (InterfaceType::Variant(v1), InterfaceType::Variant(v2)) => self.variants_equal(v1, v2),
123            (InterfaceType::Variant(_), _) => false,
124            (InterfaceType::Result(r1), InterfaceType::Result(r2)) => self.results_equal(r1, r2),
125            (InterfaceType::Result(_), _) => false,
126            (InterfaceType::Option(o1), InterfaceType::Option(o2)) => self.options_equal(o1, o2),
127            (InterfaceType::Option(_), _) => false,
128            (InterfaceType::Enum(e1), InterfaceType::Enum(e2)) => self.enums_equal(e1, e2),
129            (InterfaceType::Enum(_), _) => false,
130            (InterfaceType::Tuple(t1), InterfaceType::Tuple(t2)) => self.tuples_equal(t1, t2),
131            (InterfaceType::Tuple(_), _) => false,
132            (InterfaceType::Flags(f1), InterfaceType::Flags(f2)) => self.flags_equal(f1, f2),
133            (InterfaceType::Flags(_), _) => false,
134            (InterfaceType::Bool, InterfaceType::Bool) => true,
135            (InterfaceType::Bool, _) => false,
136            (InterfaceType::U8, InterfaceType::U8) => true,
137            (InterfaceType::U8, _) => false,
138            (InterfaceType::U16, InterfaceType::U16) => true,
139            (InterfaceType::U16, _) => false,
140            (InterfaceType::U32, InterfaceType::U32) => true,
141            (InterfaceType::U32, _) => false,
142            (InterfaceType::U64, InterfaceType::U64) => true,
143            (InterfaceType::U64, _) => false,
144            (InterfaceType::S8, InterfaceType::S8) => true,
145            (InterfaceType::S8, _) => false,
146            (InterfaceType::S16, InterfaceType::S16) => true,
147            (InterfaceType::S16, _) => false,
148            (InterfaceType::S32, InterfaceType::S32) => true,
149            (InterfaceType::S32, _) => false,
150            (InterfaceType::S64, InterfaceType::S64) => true,
151            (InterfaceType::S64, _) => false,
152            (InterfaceType::Float32, InterfaceType::Float32) => true,
153            (InterfaceType::Float32, _) => false,
154            (InterfaceType::Float64, InterfaceType::Float64) => true,
155            (InterfaceType::Float64, _) => false,
156            (InterfaceType::String, InterfaceType::String) => true,
157            (InterfaceType::String, _) => false,
158            (InterfaceType::Char, InterfaceType::Char) => true,
159            (InterfaceType::Char, _) => false,
160            (InterfaceType::Future(t1), InterfaceType::Future(t2)) => {
161                self.future_table_types_equal(t1, t2)
162            }
163            (InterfaceType::Future(_), _) => false,
164            (InterfaceType::Stream(t1), InterfaceType::Stream(t2)) => {
165                self.stream_table_types_equal(t1, t2)
166            }
167            (InterfaceType::Stream(_), _) => false,
168            (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true,
169            (InterfaceType::ErrorContext(_), _) => false,
170            (InterfaceType::FixedLengthList(t1), InterfaceType::FixedLengthList(t2)) => {
171                self.fixed_length_lists_equal(t1, t2)
172            }
173            (InterfaceType::FixedLengthList(_), _) => false,
174        }
175    }
176
177    fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
178        let a = &self.a_types[l1];
179        let b = &self.b_types[l2];
180        self.interface_types_equal(a.element, b.element)
181    }
182
183    fn maps_equal(&self, m1: TypeMapIndex, m2: TypeMapIndex) -> bool {
184        let a = &self.a_types[m1];
185        let b = &self.b_types[m2];
186        self.interface_types_equal(a.key, b.key) && self.interface_types_equal(a.value, b.value)
187    }
188
189    fn fixed_length_lists_equal(
190        &self,
191        l1: wasmtime_environ::component::TypeFixedLengthListIndex,
192        l2: wasmtime_environ::component::TypeFixedLengthListIndex,
193    ) -> bool {
194        let a = &self.a_types[l1];
195        let b = &self.b_types[l2];
196        if a.size != b.size {
197            return false;
198        }
199        self.interface_types_equal(a.element, b.element)
200    }
201
202    fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
203        match (&self.a_types[o1], &self.b_types[o2]) {
204            // Concrete resource types are the same if they map back to the
205            // exact same `ResourceType` at runtime, so look them up in resource
206            // type tables and compare the types themselves.
207            (
208                TypeResourceTable::Concrete { ty: a, .. },
209                TypeResourceTable::Concrete { ty: b, .. },
210            ) => self.a_resource.unwrap()[*a] == self.b_resource.unwrap()[*b],
211            (TypeResourceTable::Concrete { .. }, _) => false,
212
213            // Abstract resource types are only the same if they have the same
214            // index and come from the exact same component.
215            (TypeResourceTable::Abstract(a), TypeResourceTable::Abstract(b)) => {
216                core::ptr::eq(self.a_types, self.b_types) && a == b
217            }
218            (TypeResourceTable::Abstract(_), _) => false,
219        }
220    }
221
222    fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
223        let a = &self.a_types[r1];
224        let b = &self.b_types[r2];
225        if a.fields.len() != b.fields.len() {
226            return false;
227        }
228        a.fields
229            .iter()
230            .zip(b.fields.iter())
231            .all(|(a_field, b_field)| {
232                a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
233            })
234    }
235
236    fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
237        let a = &self.a_types[v1];
238        let b = &self.b_types[v2];
239        if a.cases.len() != b.cases.len() {
240            return false;
241        }
242        a.cases
243            .iter()
244            .zip(b.cases.iter())
245            .all(|((a_name, a_ty), (b_name, b_ty))| {
246                if a_name != b_name {
247                    return false;
248                }
249                match (a_ty, b_ty) {
250                    (Some(a_case_ty), Some(b_case_ty)) => {
251                        self.interface_types_equal(*a_case_ty, *b_case_ty)
252                    }
253                    (None, None) => true,
254                    _ => false,
255                }
256            })
257    }
258
259    fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
260        let a = &self.a_types[r1];
261        let b = &self.b_types[r2];
262        let oks = match (a.ok, b.ok) {
263            (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
264            (None, None) => true,
265            _ => false,
266        };
267        if !oks {
268            return false;
269        }
270        match (a.err, b.err) {
271            (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
272            (None, None) => true,
273            _ => false,
274        }
275    }
276
277    fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
278        let a = &self.a_types[o1];
279        let b = &self.b_types[o2];
280        self.interface_types_equal(a.ty, b.ty)
281    }
282
283    fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
284        let a = &self.a_types[e1];
285        let b = &self.b_types[e2];
286        a.names == b.names
287    }
288
289    fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
290        let a = &self.a_types[t1];
291        let b = &self.b_types[t2];
292        if a.types.len() != b.types.len() {
293            return false;
294        }
295        a.types
296            .iter()
297            .zip(b.types.iter())
298            .all(|(&a, &b)| self.interface_types_equal(a, b))
299    }
300
301    fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
302        let a = &self.a_types[f1];
303        let b = &self.b_types[f2];
304        a.names == b.names
305    }
306
307    fn future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool {
308        self.futures_equal(self.a_types[t1].ty, self.b_types[t2].ty)
309    }
310
311    fn futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool {
312        let a = &self.a_types[t1];
313        let b = &self.b_types[t2];
314        match (a.payload, b.payload) {
315            (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
316            (None, None) => true,
317            _ => false,
318        }
319    }
320
321    fn stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool {
322        self.streams_equal(self.a_types[t1].ty, self.b_types[t2].ty)
323    }
324
325    fn streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> bool {
326        let a = &self.a_types[t1];
327        let b = &self.b_types[t2];
328        match (a.payload, b.payload) {
329            (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
330            (None, None) => true,
331            _ => false,
332        }
333    }
334}
335
336/// A `list` interface type
337#[derive(Clone, Debug)]
338pub struct List(Handle<TypeListIndex>);
339
340impl PartialEq for List {
341    fn eq(&self, other: &Self) -> bool {
342        self.0.equivalent(&other.0, TypeChecker::lists_equal)
343    }
344}
345
346impl Eq for List {}
347
348impl List {
349    pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
350        List(Handle::new(index, ty))
351    }
352
353    /// Retrieve the element type of this `list`.
354    pub fn ty(&self) -> Type {
355        Type::from(&self.0.types[self.0.index].element, &self.0.instance())
356    }
357}
358
359/// A `map` interface type
360#[derive(Clone, Debug)]
361pub struct Map(Handle<TypeMapIndex>);
362
363impl PartialEq for Map {
364    fn eq(&self, other: &Self) -> bool {
365        self.0.equivalent(&other.0, TypeChecker::maps_equal)
366    }
367}
368
369impl Eq for Map {}
370
371impl Map {
372    pub(crate) fn from(index: TypeMapIndex, ty: &InstanceType<'_>) -> Self {
373        Map(Handle::new(index, ty))
374    }
375
376    /// Retrieve the key type of this `map`.
377    pub fn key(&self) -> Type {
378        Type::from(&self.0.types[self.0.index].key, &self.0.instance())
379    }
380
381    /// Retrieve the value type of this `map`.
382    pub fn value(&self) -> Type {
383        Type::from(&self.0.types[self.0.index].value, &self.0.instance())
384    }
385}
386/// A `list` interface type
387#[derive(Clone, Debug)]
388pub struct FixedLengthList(Handle<TypeFixedLengthListIndex>);
389
390impl PartialEq for FixedLengthList {
391    fn eq(&self, other: &Self) -> bool {
392        self.0
393            .equivalent(&other.0, TypeChecker::fixed_length_lists_equal)
394    }
395}
396
397impl Eq for FixedLengthList {}
398
399impl FixedLengthList {
400    pub(crate) fn from(index: TypeFixedLengthListIndex, ty: &InstanceType<'_>) -> Self {
401        FixedLengthList(Handle::new(index, ty))
402    }
403
404    /// Retrieve the element type of this `list`.
405    pub fn ty(&self) -> Type {
406        Type::from(&self.0.types[self.0.index].element, &self.0.instance())
407    }
408
409    /// Retrieve the length of this `list`.
410    pub fn len(&self) -> u32 {
411        self.0.types[self.0.index].size
412    }
413}
414
415/// A field declaration belonging to a `record`
416#[derive(Debug)]
417pub struct Field<'a> {
418    /// The name of the field
419    pub name: &'a str,
420    /// The type of the field
421    pub ty: Type,
422}
423
424/// A `record` interface type
425#[derive(Clone, Debug)]
426pub struct Record(Handle<TypeRecordIndex>);
427
428impl Record {
429    pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
430        Record(Handle::new(index, ty))
431    }
432
433    /// Retrieve the fields of this `record` in declaration order.
434    pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
435        self.0.types[self.0.index].fields.iter().map(|field| Field {
436            name: &field.name,
437            ty: Type::from(&field.ty, &self.0.instance()),
438        })
439    }
440}
441
442impl PartialEq for Record {
443    fn eq(&self, other: &Self) -> bool {
444        self.0.equivalent(&other.0, TypeChecker::records_equal)
445    }
446}
447
448impl Eq for Record {}
449
450/// A `tuple` interface type
451#[derive(Clone, Debug)]
452pub struct Tuple(Handle<TypeTupleIndex>);
453
454impl Tuple {
455    pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
456        Tuple(Handle::new(index, ty))
457    }
458
459    /// Retrieve the types of the fields of this `tuple` in declaration order.
460    pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
461        self.0.types[self.0.index]
462            .types
463            .iter()
464            .map(|ty| Type::from(ty, &self.0.instance()))
465    }
466}
467
468impl PartialEq for Tuple {
469    fn eq(&self, other: &Self) -> bool {
470        self.0.equivalent(&other.0, TypeChecker::tuples_equal)
471    }
472}
473
474impl Eq for Tuple {}
475
476/// A case declaration belonging to a `variant`
477pub struct Case<'a> {
478    /// The name of the case
479    pub name: &'a str,
480    /// The optional payload type of the case
481    pub ty: Option<Type>,
482}
483
484/// A `variant` interface type
485#[derive(Clone, Debug)]
486pub struct Variant(Handle<TypeVariantIndex>);
487
488impl Variant {
489    pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
490        Variant(Handle::new(index, ty))
491    }
492
493    /// Retrieve the cases of this `variant` in declaration order.
494    pub fn cases(&self) -> impl ExactSizeIterator<Item = Case<'_>> {
495        self.0.types[self.0.index]
496            .cases
497            .iter()
498            .map(|(name, ty)| Case {
499                name,
500                ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
501            })
502    }
503}
504
505impl PartialEq for Variant {
506    fn eq(&self, other: &Self) -> bool {
507        self.0.equivalent(&other.0, TypeChecker::variants_equal)
508    }
509}
510
511impl Eq for Variant {}
512
513/// An `enum` interface type
514#[derive(Clone, Debug)]
515pub struct Enum(Handle<TypeEnumIndex>);
516
517impl Enum {
518    pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
519        Enum(Handle::new(index, ty))
520    }
521
522    /// Retrieve the names of the cases of this `enum` in declaration order.
523    pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
524        self.0.types[self.0.index]
525            .names
526            .iter()
527            .map(|name| name.deref())
528    }
529}
530
531impl PartialEq for Enum {
532    fn eq(&self, other: &Self) -> bool {
533        self.0.equivalent(&other.0, TypeChecker::enums_equal)
534    }
535}
536
537impl Eq for Enum {}
538
539/// An `option` interface type
540#[derive(Clone, Debug)]
541pub struct OptionType(Handle<TypeOptionIndex>);
542
543impl OptionType {
544    pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
545        OptionType(Handle::new(index, ty))
546    }
547
548    /// Retrieve the type parameter for this `option`.
549    pub fn ty(&self) -> Type {
550        Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
551    }
552}
553
554impl PartialEq for OptionType {
555    fn eq(&self, other: &Self) -> bool {
556        self.0.equivalent(&other.0, TypeChecker::options_equal)
557    }
558}
559
560impl Eq for OptionType {}
561
562/// A `result` interface type
563#[derive(Clone, Debug)]
564pub struct ResultType(Handle<TypeResultIndex>);
565
566impl ResultType {
567    pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
568        ResultType(Handle::new(index, ty))
569    }
570
571    /// Retrieve the `ok` type parameter for this `result`.
572    pub fn ok(&self) -> Option<Type> {
573        Some(Type::from(
574            self.0.types[self.0.index].ok.as_ref()?,
575            &self.0.instance(),
576        ))
577    }
578
579    /// Retrieve the `err` type parameter for this `result`.
580    pub fn err(&self) -> Option<Type> {
581        Some(Type::from(
582            self.0.types[self.0.index].err.as_ref()?,
583            &self.0.instance(),
584        ))
585    }
586}
587
588impl PartialEq for ResultType {
589    fn eq(&self, other: &Self) -> bool {
590        self.0.equivalent(&other.0, TypeChecker::results_equal)
591    }
592}
593
594impl Eq for ResultType {}
595
596/// A `flags` interface type
597#[derive(Clone, Debug)]
598pub struct Flags(Handle<TypeFlagsIndex>);
599
600impl Flags {
601    pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
602        Flags(Handle::new(index, ty))
603    }
604
605    /// Retrieve the names of the flags of this `flags` type in declaration order.
606    pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
607        self.0.types[self.0.index]
608            .names
609            .iter()
610            .map(|name| name.deref())
611    }
612}
613
614impl PartialEq for Flags {
615    fn eq(&self, other: &Self) -> bool {
616        self.0.equivalent(&other.0, TypeChecker::flags_equal)
617    }
618}
619
620impl Eq for Flags {}
621
622#[cfg(feature = "component-model-async")]
623pub(crate) fn typecheck_payload<T>(
624    payload: Option<&InterfaceType>,
625    types: &InstanceType<'_>,
626) -> crate::Result<()>
627where
628    T: ComponentType,
629{
630    match payload {
631        Some(a) => T::typecheck(a, types),
632        None => {
633            if T::IS_RUST_UNIT_TYPE {
634                Ok(())
635            } else {
636                crate::bail!("future payload types differ")
637            }
638        }
639    }
640}
641
642/// An `future` interface type
643#[derive(Clone, Debug)]
644pub struct FutureType(Handle<TypeFutureIndex>);
645
646impl FutureType {
647    pub(crate) fn from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self {
648        FutureType(Handle::new(index, ty))
649    }
650
651    /// Retrieve the type parameter for this `future`.
652    pub fn ty(&self) -> Option<Type> {
653        Some(Type::from(
654            self.0.types[self.0.index].payload.as_ref()?,
655            &self.0.instance(),
656        ))
657    }
658
659    #[cfg(feature = "component-model-async")]
660    pub(crate) fn equivalent_payload_guest(
661        &self,
662        ty: &InstanceType<'_>,
663        payload: Option<&InterfaceType>,
664    ) -> bool {
665        let my_payload = self.0.types[self.0.index].payload.as_ref();
666        match (my_payload, payload) {
667            (Some(a), Some(b)) => TypeChecker {
668                a_types: &self.0.types,
669                a_resource: self.0.resources.as_deref(),
670                b_types: ty.types,
671                b_resource: ty.resources.map(|p| &**p),
672            }
673            .interface_types_equal(*a, *b),
674            (None, None) => true,
675            (Some(_), None) | (None, Some(_)) => false,
676        }
677    }
678
679    #[cfg(feature = "component-model-async")]
680    pub(crate) fn equivalent_payload_host<T>(&self) -> crate::Result<()>
681    where
682        T: ComponentType,
683    {
684        typecheck_payload::<T>(
685            self.0.types[self.0.index].payload.as_ref(),
686            &self.0.instance(),
687        )
688    }
689}
690
691impl PartialEq for FutureType {
692    fn eq(&self, other: &Self) -> bool {
693        self.0.equivalent(&other.0, TypeChecker::futures_equal)
694    }
695}
696
697impl Eq for FutureType {}
698
699/// An `stream` interface type
700#[derive(Clone, Debug)]
701pub struct StreamType(Handle<TypeStreamIndex>);
702
703impl StreamType {
704    pub(crate) fn from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self {
705        StreamType(Handle::new(index, ty))
706    }
707
708    /// Retrieve the type parameter for this `stream`.
709    pub fn ty(&self) -> Option<Type> {
710        Some(Type::from(
711            self.0.types[self.0.index].payload.as_ref()?,
712            &self.0.instance(),
713        ))
714    }
715
716    #[cfg(feature = "component-model-async")]
717    pub(crate) fn equivalent_payload_guest(
718        &self,
719        ty: &InstanceType<'_>,
720        payload: Option<&InterfaceType>,
721    ) -> bool {
722        let my_payload = self.0.types[self.0.index].payload.as_ref();
723        match (my_payload, payload) {
724            (Some(a), Some(b)) => TypeChecker {
725                a_types: &self.0.types,
726                a_resource: self.0.resources.as_deref(),
727                b_types: ty.types,
728                b_resource: ty.resources.map(|p| &**p),
729            }
730            .interface_types_equal(*a, *b),
731            (None, None) => true,
732            (Some(_), None) | (None, Some(_)) => false,
733        }
734    }
735
736    #[cfg(feature = "component-model-async")]
737    pub(crate) fn equivalent_payload_host<T>(&self) -> crate::Result<()>
738    where
739        T: ComponentType,
740    {
741        typecheck_payload::<T>(
742            self.0.types[self.0.index].payload.as_ref(),
743            &self.0.instance(),
744        )
745    }
746}
747
748impl PartialEq for StreamType {
749    fn eq(&self, other: &Self) -> bool {
750        self.0.equivalent(&other.0, TypeChecker::streams_equal)
751    }
752}
753
754impl Eq for StreamType {}
755
756/// Represents a component model interface type
757#[derive(Clone, PartialEq, Eq, Debug)]
758#[expect(missing_docs, reason = "self-describing variants")]
759pub enum Type {
760    Bool,
761    S8,
762    U8,
763    S16,
764    U16,
765    S32,
766    U32,
767    S64,
768    U64,
769    Float32,
770    Float64,
771    Char,
772    String,
773    List(List),
774    Map(Map),
775    Record(Record),
776    Tuple(Tuple),
777    Variant(Variant),
778    Enum(Enum),
779    Option(OptionType),
780    Result(ResultType),
781    Flags(Flags),
782    Own(ResourceType),
783    Borrow(ResourceType),
784    Future(FutureType),
785    Stream(StreamType),
786    ErrorContext,
787    FixedLengthList(FixedLengthList),
788}
789
790impl Type {
791    /// Retrieve the inner [`List`] of a [`Type::List`].
792    ///
793    /// # Panics
794    ///
795    /// This will panic if `self` is not a [`Type::List`].
796    pub fn unwrap_list(&self) -> &List {
797        if let Type::List(handle) = self {
798            &handle
799        } else {
800            panic!("attempted to unwrap a {} as a list", self.desc())
801        }
802    }
803
804    /// Retrieve the inner [`Map`] of a [`Type::Map`].
805    ///
806    /// # Panics
807    ///
808    /// This will panic if `self` is not a [`Type::Map`].
809    pub fn unwrap_map(&self) -> &Map {
810        if let Type::Map(handle) = self {
811            &handle
812        } else {
813            panic!("attempted to unwrap a {} as a map", self.desc())
814        }
815    }
816
817    /// Retrieve the inner [`Record`] of a [`Type::Record`].
818    ///
819    /// # Panics
820    ///
821    /// This will panic if `self` is not a [`Type::Record`].
822    pub fn unwrap_record(&self) -> &Record {
823        if let Type::Record(handle) = self {
824            &handle
825        } else {
826            panic!("attempted to unwrap a {} as a record", self.desc())
827        }
828    }
829
830    /// Retrieve the inner [`Tuple`] of a [`Type::Tuple`].
831    ///
832    /// # Panics
833    ///
834    /// This will panic if `self` is not a [`Type::Tuple`].
835    pub fn unwrap_tuple(&self) -> &Tuple {
836        if let Type::Tuple(handle) = self {
837            &handle
838        } else {
839            panic!("attempted to unwrap a {} as a tuple", self.desc())
840        }
841    }
842
843    /// Retrieve the inner [`Variant`] of a [`Type::Variant`].
844    ///
845    /// # Panics
846    ///
847    /// This will panic if `self` is not a [`Type::Variant`].
848    pub fn unwrap_variant(&self) -> &Variant {
849        if let Type::Variant(handle) = self {
850            &handle
851        } else {
852            panic!("attempted to unwrap a {} as a variant", self.desc())
853        }
854    }
855
856    /// Retrieve the inner [`Enum`] of a [`Type::Enum`].
857    ///
858    /// # Panics
859    ///
860    /// This will panic if `self` is not a [`Type::Enum`].
861    pub fn unwrap_enum(&self) -> &Enum {
862        if let Type::Enum(handle) = self {
863            &handle
864        } else {
865            panic!("attempted to unwrap a {} as a enum", self.desc())
866        }
867    }
868
869    /// Retrieve the inner [`OptionType`] of a [`Type::Option`].
870    ///
871    /// # Panics
872    ///
873    /// This will panic if `self` is not a [`Type::Option`].
874    pub fn unwrap_option(&self) -> &OptionType {
875        if let Type::Option(handle) = self {
876            &handle
877        } else {
878            panic!("attempted to unwrap a {} as a option", self.desc())
879        }
880    }
881
882    /// Retrieve the inner [`ResultType`] of a [`Type::Result`].
883    ///
884    /// # Panics
885    ///
886    /// This will panic if `self` is not a [`Type::Result`].
887    pub fn unwrap_result(&self) -> &ResultType {
888        if let Type::Result(handle) = self {
889            &handle
890        } else {
891            panic!("attempted to unwrap a {} as a result", self.desc())
892        }
893    }
894
895    /// Retrieve the inner [`Flags`] of a [`Type::Flags`].
896    ///
897    /// # Panics
898    ///
899    /// This will panic if `self` is not a [`Type::Flags`].
900    pub fn unwrap_flags(&self) -> &Flags {
901        if let Type::Flags(handle) = self {
902            &handle
903        } else {
904            panic!("attempted to unwrap a {} as a flags", self.desc())
905        }
906    }
907
908    /// Retrieve the inner [`ResourceType`] of a [`Type::Own`].
909    ///
910    /// # Panics
911    ///
912    /// This will panic if `self` is not a [`Type::Own`].
913    pub fn unwrap_own(&self) -> &ResourceType {
914        match self {
915            Type::Own(ty) => ty,
916            _ => panic!("attempted to unwrap a {} as a own", self.desc()),
917        }
918    }
919
920    /// Retrieve the inner [`ResourceType`] of a [`Type::Borrow`].
921    ///
922    /// # Panics
923    ///
924    /// This will panic if `self` is not a [`Type::Borrow`].
925    pub fn unwrap_borrow(&self) -> &ResourceType {
926        match self {
927            Type::Borrow(ty) => ty,
928            _ => panic!("attempted to unwrap a {} as a own", self.desc()),
929        }
930    }
931
932    /// Convert the specified `InterfaceType` to a `Type`.
933    pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
934        match ty {
935            InterfaceType::Bool => Type::Bool,
936            InterfaceType::S8 => Type::S8,
937            InterfaceType::U8 => Type::U8,
938            InterfaceType::S16 => Type::S16,
939            InterfaceType::U16 => Type::U16,
940            InterfaceType::S32 => Type::S32,
941            InterfaceType::U32 => Type::U32,
942            InterfaceType::S64 => Type::S64,
943            InterfaceType::U64 => Type::U64,
944            InterfaceType::Float32 => Type::Float32,
945            InterfaceType::Float64 => Type::Float64,
946            InterfaceType::Char => Type::Char,
947            InterfaceType::String => Type::String,
948            InterfaceType::List(index) => Type::List(List::from(*index, instance)),
949            InterfaceType::Map(index) => Type::Map(Map::from(*index, instance)),
950            InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
951            InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
952            InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
953            InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
954            InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
955            InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
956            InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
957            InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
958            InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
959            InterfaceType::Future(index) => Type::Future(instance.future_type(*index)),
960            InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)),
961            InterfaceType::ErrorContext(_) => Type::ErrorContext,
962            InterfaceType::FixedLengthList(index) => {
963                Type::FixedLengthList(FixedLengthList::from(*index, instance))
964            }
965        }
966    }
967
968    /// Construct a default value of this type, if one exists.
969    ///
970    /// Defaults are the "empty" or "zero" value of each type: zero for the
971    /// numerics, the empty `string`/`list`, `none` for `option`, `ok` for
972    /// `result`, no flags set, and the first case of a `variant` or `enum`.
973    ///
974    /// An `own` or `borrow` of a host-defined resource defaults to a fresh
975    /// handle in `store`, with an arbitrary representation and no destructor.
976    /// Nothing can be done with such a handle beyond passing it back to the
977    /// component that the resource was defined for.
978    ///
979    /// # Errors
980    ///
981    /// Returns an error for an `own` or `borrow` of a guest-defined resource,
982    /// whose representation belongs to the guest and so cannot be conjured by
983    /// the host.
984    ///
985    /// Returns an error for `future`, `stream`, and `error-context`, as there
986    /// is currently no way to synthesize these without statically knowing
987    /// their payload type.
988    ///
989    /// An aggregate containing any of the above is an error for the same
990    /// reason.
991    ///
992    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error
993    /// when memory allocation fails. See the `OutOfMemory` type's
994    /// documentation for details on Wasmtime's out-of-memory handling.
995    pub fn default_value(&self, mut store: impl AsContextMut) -> Result<Val> {
996        self.default_value_impl(store.as_context_mut())
997    }
998
999    /// Recursive implementation of `default_value`.
1000    fn default_value_impl<T>(&self, mut store: StoreContextMut<'_, T>) -> Result<Val> {
1001        Ok(match self {
1002            Type::Bool => Val::Bool(false),
1003            Type::S8 => Val::S8(0),
1004            Type::U8 => Val::U8(0),
1005            Type::S16 => Val::S16(0),
1006            Type::U16 => Val::U16(0),
1007            Type::S32 => Val::S32(0),
1008            Type::U32 => Val::U32(0),
1009            Type::S64 => Val::S64(0),
1010            Type::U64 => Val::U64(0),
1011            Type::Float32 => Val::Float32(0.0),
1012            Type::Float64 => Val::Float64(0.0),
1013            Type::Char => Val::Char('\0'),
1014            Type::String => Val::String(String::new()),
1015
1016            // These never visit their payload types.
1017            Type::List(_) => Val::List(Vec::new()),
1018            Type::Map(_) => Val::Map(Vec::new()),
1019            Type::Option(_) => Val::Option(None),
1020            Type::Flags(_) => Val::Flags(Vec::new()),
1021
1022            Type::Enum(e) => {
1023                let name = e.names().next().ok_or_else(|| {
1024                    format_err!("no default value exists for an `enum` with no cases")
1025                })?;
1026                Val::Enum(name.to_string())
1027            }
1028
1029            Type::Record(record) => {
1030                let mut fields = TryVec::with_capacity(record.fields().len())?;
1031                for field in record.fields() {
1032                    let val = field.ty.default_value_impl(store.as_context_mut())?;
1033                    fields.push((field.name.to_string(), val))?;
1034                }
1035                Val::Record(fields.into())
1036            }
1037
1038            Type::Tuple(tuple) => {
1039                let mut vals = TryVec::with_capacity(tuple.types().len())?;
1040                for ty in tuple.types() {
1041                    vals.push(ty.default_value_impl(store.as_context_mut())?)?;
1042                }
1043                Val::Tuple(vals.into())
1044            }
1045
1046            Type::Variant(variant) => {
1047                let case = variant.cases().next().ok_or_else(|| {
1048                    format_err!("no default value exists for a `variant` with no cases")
1049                })?;
1050                let payload = match &case.ty {
1051                    Some(ty) => Some(Box::new(ty.default_value_impl(store.as_context_mut())?)),
1052                    None => None,
1053                };
1054                Val::Variant(case.name.to_string(), payload)
1055            }
1056
1057            Type::Result(result) => Val::Result(Ok(match result.ok() {
1058                Some(ty) => Some(Box::new(ty.default_value_impl(store.as_context_mut())?)),
1059                None => None,
1060            })),
1061
1062            Type::FixedLengthList(list) => {
1063                // Every element has the same type, so one value is cloned.
1064                let element = list.ty().default_value_impl(store.as_context_mut())?;
1065                let len = usize::try_from(list.len())?;
1066                let mut vals = TryVec::with_capacity(len)?;
1067                for _ in 0..len {
1068                    vals.push(element.clone())?;
1069                }
1070                Val::FixedLengthList(vals.into())
1071            }
1072
1073            // The `rep` is arbitrary and never dereferenced: there is no
1074            // destructor, and the handle is opaque to everything but the
1075            // component that defines the resource.
1076            Type::Own(ty) | Type::Borrow(ty) => {
1077                Val::Resource(ResourceAny::new_own_dynamic(*ty, 0, &mut store)?)
1078            }
1079
1080            Type::Future(_) | Type::Stream(_) | Type::ErrorContext => {
1081                bail!("no default value exists for type `{}`", self.desc())
1082            }
1083        })
1084    }
1085
1086    fn desc(&self) -> &'static str {
1087        match self {
1088            Type::Bool => "bool",
1089            Type::S8 => "s8",
1090            Type::U8 => "u8",
1091            Type::S16 => "s16",
1092            Type::U16 => "u16",
1093            Type::S32 => "s32",
1094            Type::U32 => "u32",
1095            Type::S64 => "s64",
1096            Type::U64 => "u64",
1097            Type::Float32 => "float32",
1098            Type::Float64 => "float64",
1099            Type::Char => "char",
1100            Type::String => "string",
1101            Type::List(_) => "list",
1102            Type::Map(_) => "map",
1103            Type::Record(_) => "record",
1104            Type::Tuple(_) => "tuple",
1105            Type::Variant(_) => "variant",
1106            Type::Enum(_) => "enum",
1107            Type::Option(_) => "option",
1108            Type::Result(_) => "result",
1109            Type::Flags(_) => "flags",
1110            Type::Own(_) => "own",
1111            Type::Borrow(_) => "borrow",
1112            Type::Future(_) => "future",
1113            Type::Stream(_) => "stream",
1114            Type::ErrorContext => "error-context",
1115            Type::FixedLengthList(_) => "list<_, N>",
1116        }
1117    }
1118}
1119
1120/// Component function type
1121#[derive(Clone, Debug)]
1122pub struct ComponentFunc(Handle<TypeFuncIndex>);
1123
1124impl ComponentFunc {
1125    pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
1126        Self(Handle::new(index, ty))
1127    }
1128
1129    /// Returns whether this is an async function
1130    pub fn async_(&self) -> bool {
1131        self.0.types[self.0.index].async_
1132    }
1133
1134    /// Iterates over types of function parameters and names.
1135    pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
1136        let ty = &self.0.types[self.0.index];
1137        self.0.types[ty.params]
1138            .types
1139            .iter()
1140            .zip(&ty.param_names)
1141            .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
1142    }
1143
1144    /// Iterates over types of function results
1145    pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
1146        let results = self.0.types[self.0.index].results;
1147        self.0.types[results]
1148            .types
1149            .iter()
1150            .map(|ty| Type::from(ty, &self.0.instance()))
1151    }
1152
1153    #[doc(hidden)]
1154    pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> crate::Result<()>
1155    where
1156        Params: crate::component::ComponentNamedList + crate::component::Lower,
1157        Return: crate::component::ComponentNamedList + crate::component::Lift,
1158    {
1159        let ty = &self.0.types[self.0.index];
1160        Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
1161        Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
1162        Ok(())
1163    }
1164}
1165
1166/// Core module type
1167#[derive(Clone, Debug)]
1168pub struct Module(Handle<TypeModuleIndex>);
1169
1170impl Module {
1171    pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
1172        Self(Handle::new(index, ty))
1173    }
1174
1175    /// Iterates over imports of the module
1176    pub fn imports<'a>(
1177        &'a self,
1178        engine: &'a Engine,
1179    ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
1180        self.0.types[self.0.index]
1181            .imports
1182            .iter()
1183            .map(|((namespace, name), ty)| {
1184                (
1185                    (namespace.as_str(), name.as_str()),
1186                    ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
1187                )
1188            })
1189    }
1190
1191    /// Iterates over exports of the module
1192    pub fn exports<'a>(
1193        &'a self,
1194        engine: &'a Engine,
1195    ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
1196        self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
1197            (
1198                name.as_str(),
1199                ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
1200            )
1201        })
1202    }
1203}
1204
1205/// Component type
1206#[derive(Clone, Debug)]
1207pub struct Component(Handle<TypeComponentIndex>);
1208
1209impl Component {
1210    pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
1211        Self(Handle::new(index, ty))
1212    }
1213
1214    /// Returns import associated with `name`, if such exists in the component
1215    pub fn get_import<'a>(&'a self, engine: &'a Engine, name: &str) -> Option<ComponentExtern<'a>> {
1216        self.0.types[self.0.index]
1217            .imports
1218            .get(name)
1219            .map(|e| ComponentExtern::new(engine, &self.0.instance(), e))
1220    }
1221
1222    /// Iterates over imports of the component
1223    pub fn imports<'a>(
1224        &'a self,
1225        engine: &'a Engine,
1226    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentExtern<'a>)> + 'a {
1227        self.0.types[self.0.index].imports.iter().map(|(name, e)| {
1228            (
1229                name.as_str(),
1230                ComponentExtern::new(engine, &self.0.instance(), e),
1231            )
1232        })
1233    }
1234
1235    /// Returns export associated with `name`, if such exists in the component
1236    pub fn get_export<'a>(&'a self, engine: &'a Engine, name: &str) -> Option<ComponentExtern<'a>> {
1237        self.0.types[self.0.index]
1238            .exports
1239            .get(name)
1240            .map(|e| ComponentExtern::new(engine, &self.0.instance(), e))
1241    }
1242
1243    /// Iterates over exports of the component
1244    pub fn exports<'a>(
1245        &'a self,
1246        engine: &'a Engine,
1247    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentExtern<'a>)> + 'a {
1248        self.0.types[self.0.index].exports.iter().map(|(name, e)| {
1249            (
1250                name.as_str(),
1251                ComponentExtern::new(engine, &self.0.instance(), e),
1252            )
1253        })
1254    }
1255
1256    #[doc(hidden)]
1257    pub fn instance_type(&self) -> InstanceType<'_> {
1258        InstanceType {
1259            types: &self.0.types,
1260            resources: self.0.resources.as_ref(),
1261        }
1262    }
1263}
1264
1265/// Component instance type
1266#[derive(Clone, Debug)]
1267pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
1268
1269impl ComponentInstance {
1270    pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
1271        Self(Handle::new(index, ty))
1272    }
1273
1274    /// Returns export associated with `name`, if such exists in the component instance
1275    pub fn get_export<'a>(&'a self, engine: &'a Engine, name: &str) -> Option<ComponentExtern<'a>> {
1276        self.0.types[self.0.index]
1277            .exports
1278            .get(name)
1279            .map(|e| ComponentExtern::new(engine, &self.0.instance(), e))
1280    }
1281
1282    /// Iterates over exports of the component instance
1283    pub fn exports<'a>(
1284        &'a self,
1285        engine: &'a Engine,
1286    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentExtern<'a>)> {
1287        self.0.types[self.0.index].exports.iter().map(|(name, e)| {
1288            (
1289                name.as_str(),
1290                ComponentExtern::new(engine, &self.0.instance(), e),
1291            )
1292        })
1293    }
1294}
1295
1296/// An import or an export from either [`Component`] or [`ComponentInstance`].
1297///
1298/// This records the type of the item that is being imported or exported along
1299/// with any other metadata associated.
1300#[derive(Clone, Debug)]
1301pub struct ComponentExtern<'a> {
1302    /// The type of this item.
1303    pub ty: ComponentItem,
1304    /// The `(implements "...")` annotation, if present.
1305    pub implements: Option<&'a str>,
1306    /// The `(external-id "...")` annotation, if present.
1307    ///
1308    /// This is a free-form host-defined identifier and is intended to indicate
1309    /// how the host should satisfy an import (or interpret an export).
1310    pub external_id: Option<&'a str>,
1311}
1312
1313impl<'a> ComponentExtern<'a> {
1314    fn new(
1315        engine: &'a Engine,
1316        instance_ty: &InstanceType<'_>,
1317        env: &'a wasmtime_environ::component::ComponentExtern,
1318    ) -> Self {
1319        Self {
1320            implements: env.data.implements.as_deref(),
1321            external_id: env.data.external_id.as_deref(),
1322            ty: ComponentItem::from(engine, &env.ty, instance_ty),
1323        }
1324    }
1325
1326    /// Returns whether this item is tagged with `(implements "..")` with an
1327    /// interface that's compatible with `name`.
1328    ///
1329    /// This function will return `false` if `(implements "...")` is not
1330    /// present. If it is present, and it's equal to `name`, then `true` is
1331    /// returned. Failing that, this attempts to perform version-matching to see
1332    /// if a compatible version of this item is implemented. For example if
1333    /// `(implements "a:b/c@1.1.0")` is specified then this will return `true`
1334    /// for `a:b/c@1.0.0` and `a:b/c@1.2.0` as well. The same goes for a
1335    /// canonical name such as `(implements "a:b/c@1")`.
1336    pub fn is_implements(&self, name: &str) -> bool {
1337        let implements = match self.implements {
1338            Some(s) => s,
1339            None => return false,
1340        };
1341        if name == implements {
1342            return true;
1343        }
1344
1345        // Compare semver-compatible versions in their reduced form, for
1346        // example `a:b/c@1.2.0` as `a:b/c@1`. Canonical names are already in
1347        // that form, so they're compared as-is.
1348        let reduced = |name| alternate_lookup_key(name).map_or(name, |(name, _)| name);
1349        reduced(implements) == reduced(name)
1350    }
1351}
1352
1353/// Type of an item contained within the component
1354#[derive(Clone, Debug)]
1355pub enum ComponentItem {
1356    /// Component function item
1357    ComponentFunc(ComponentFunc),
1358    /// Core function item
1359    CoreFunc(FuncType),
1360    /// Core module item
1361    Module(Module),
1362    /// Component item
1363    Component(Component),
1364    /// Component instance item
1365    ComponentInstance(ComponentInstance),
1366    /// Interface type item
1367    Type(Type),
1368    /// Resource item
1369    Resource(ResourceType),
1370}
1371
1372impl ComponentItem {
1373    pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
1374        match def {
1375            TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
1376            TypeDef::ComponentInstance(idx) => {
1377                Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1378            }
1379            TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
1380            TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
1381            TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
1382            TypeDef::CoreFunc(idx) => {
1383                let subty = &ty.types[*idx];
1384                Self::CoreFunc(
1385                    FuncType::from_wasm_func_type(
1386                        engine,
1387                        subty.is_final,
1388                        subty.supertype,
1389                        subty.unwrap_func().try_clone().panic_on_oom(),
1390                    )
1391                    .panic_on_oom(),
1392                )
1393            }
1394            TypeDef::Resource(idx) => match ty.types[*idx] {
1395                TypeResourceTable::Concrete {
1396                    ty: resource_index, ..
1397                } => {
1398                    let ty = match ty.resources.and_then(|t| t.get(resource_index)) {
1399                        // This resource type was substituted by a linker for
1400                        // example so it's replaced here.
1401                        Some(ty) => *ty,
1402
1403                        // This resource type was not substituted.
1404                        None => ResourceType::uninstantiated(&ty.types, resource_index),
1405                    };
1406                    Self::Resource(ty)
1407                }
1408                TypeResourceTable::Abstract(resource_index) => {
1409                    Self::Resource(ResourceType::abstract_(&ty.types, resource_index))
1410                }
1411            },
1412        }
1413    }
1414    pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
1415        match export {
1416            Export::Instance { ty: idx, .. } => {
1417                Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1418            }
1419            Export::LiftedFunction { ty: idx, .. } => {
1420                Self::ComponentFunc(ComponentFunc::from(*idx, ty))
1421            }
1422            Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
1423                Self::Module(Module::from(*idx, ty))
1424            }
1425            Export::Type(idx) => Self::from(engine, idx, ty),
1426        }
1427    }
1428}