1 //! This module defines the `Type` type, representing the dynamic form of a component interface type.
2 
3 #[cfg(feature = "component-model-async")]
4 use crate::component::ComponentType;
5 use crate::component::matching::InstanceType;
6 use crate::{Engine, ExternType, FuncType, prelude::*};
7 use alloc::sync::Arc;
8 use core::fmt;
9 use core::ops::Deref;
10 use wasmtime_environ::component::{
11     ComponentTypes, Export, InterfaceType, ResourceIndex, TypeComponentIndex,
12     TypeComponentInstanceIndex, TypeDef, TypeEnumIndex, TypeFlagsIndex, TypeFuncIndex,
13     TypeFutureIndex, TypeFutureTableIndex, TypeListIndex, TypeMapIndex, TypeModuleIndex,
14     TypeOptionIndex, TypeRecordIndex, TypeResourceTable, TypeResourceTableIndex, TypeResultIndex,
15     TypeStreamIndex, TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex,
16 };
17 use wasmtime_environ::{PanicOnOom as _, PrimaryMap};
18 
19 pub use crate::component::resources::ResourceType;
20 
21 /// An owned and `'static` handle for type information in a component.
22 ///
23 /// The components here are:
24 ///
25 /// * `index` - a `TypeFooIndex` defined in the `wasmtime_environ` crate. This
26 ///   then points into the next field of...
27 ///
28 /// * `types` - this is an allocation originally created from compilation and is
29 ///   stored in a compiled `Component`. This contains all types necessary and
30 ///   information about recursive structures and all other type information
31 ///   within the component. The above `index` points into this structure.
32 ///
33 /// * `resources` - this is used to "close the loop" and represent a concrete
34 ///   instance type rather than an abstract component type. Instantiating a
35 ///   component with different resources produces different instance types but
36 ///   the same underlying component type, so this field serves the purpose to
37 ///   distinguish instance types from one another. This is runtime state created
38 ///   during instantiation and threaded through here.
39 #[derive(Clone)]
40 struct Handle<T> {
41     index: T,
42     types: Arc<ComponentTypes>,
43     resources: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
44 }
45 
46 impl<T> Handle<T> {
new(index: T, ty: &InstanceType<'_>) -> Handle<T>47     fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
48         Handle {
49             index,
50             types: ty.types.clone(),
51             resources: ty.resources.clone(),
52         }
53     }
54 
instance(&self) -> InstanceType<'_>55     fn instance(&self) -> InstanceType<'_> {
56         InstanceType {
57             types: &self.types,
58             resources: &self.resources,
59         }
60     }
61 
equivalent<'a>( &'a self, other: &'a Self, type_check: fn(&TypeChecker<'a>, T, T) -> bool, ) -> bool where T: PartialEq + Copy,62     fn equivalent<'a>(
63         &'a self,
64         other: &'a Self,
65         type_check: fn(&TypeChecker<'a>, T, T) -> bool,
66     ) -> bool
67     where
68         T: PartialEq + Copy,
69     {
70         (self.index == other.index
71             && Arc::ptr_eq(&self.types, &other.types)
72             && Arc::ptr_eq(&self.resources, &other.resources))
73             || type_check(
74                 &TypeChecker {
75                     a_types: &self.types,
76                     b_types: &other.types,
77                     a_resource: &self.resources,
78                     b_resource: &other.resources,
79                 },
80                 self.index,
81                 other.index,
82             )
83     }
84 }
85 
86 impl<T: fmt::Debug> fmt::Debug for Handle<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result87     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88         f.debug_struct("Handle")
89             .field("index", &self.index)
90             .finish()
91     }
92 }
93 
94 /// Type checker between two `Handle`s
95 struct TypeChecker<'a> {
96     a_types: &'a ComponentTypes,
97     a_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
98     b_types: &'a ComponentTypes,
99     b_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
100 }
101 
102 impl TypeChecker<'_> {
interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool103     fn interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool {
104         match (a, b) {
105             (InterfaceType::Own(o1), InterfaceType::Own(o2)) => self.resources_equal(o1, o2),
106             (InterfaceType::Own(_), _) => false,
107             (InterfaceType::Borrow(b1), InterfaceType::Borrow(b2)) => self.resources_equal(b1, b2),
108             (InterfaceType::Borrow(_), _) => false,
109             (InterfaceType::List(l1), InterfaceType::List(l2)) => self.lists_equal(l1, l2),
110             (InterfaceType::List(_), _) => false,
111             (InterfaceType::Map(m1), InterfaceType::Map(m2)) => self.maps_equal(m1, m2),
112             (InterfaceType::Map(_), _) => false,
113             (InterfaceType::Record(r1), InterfaceType::Record(r2)) => self.records_equal(r1, r2),
114             (InterfaceType::Record(_), _) => false,
115             (InterfaceType::Variant(v1), InterfaceType::Variant(v2)) => self.variants_equal(v1, v2),
116             (InterfaceType::Variant(_), _) => false,
117             (InterfaceType::Result(r1), InterfaceType::Result(r2)) => self.results_equal(r1, r2),
118             (InterfaceType::Result(_), _) => false,
119             (InterfaceType::Option(o1), InterfaceType::Option(o2)) => self.options_equal(o1, o2),
120             (InterfaceType::Option(_), _) => false,
121             (InterfaceType::Enum(e1), InterfaceType::Enum(e2)) => self.enums_equal(e1, e2),
122             (InterfaceType::Enum(_), _) => false,
123             (InterfaceType::Tuple(t1), InterfaceType::Tuple(t2)) => self.tuples_equal(t1, t2),
124             (InterfaceType::Tuple(_), _) => false,
125             (InterfaceType::Flags(f1), InterfaceType::Flags(f2)) => self.flags_equal(f1, f2),
126             (InterfaceType::Flags(_), _) => false,
127             (InterfaceType::Bool, InterfaceType::Bool) => true,
128             (InterfaceType::Bool, _) => false,
129             (InterfaceType::U8, InterfaceType::U8) => true,
130             (InterfaceType::U8, _) => false,
131             (InterfaceType::U16, InterfaceType::U16) => true,
132             (InterfaceType::U16, _) => false,
133             (InterfaceType::U32, InterfaceType::U32) => true,
134             (InterfaceType::U32, _) => false,
135             (InterfaceType::U64, InterfaceType::U64) => true,
136             (InterfaceType::U64, _) => false,
137             (InterfaceType::S8, InterfaceType::S8) => true,
138             (InterfaceType::S8, _) => false,
139             (InterfaceType::S16, InterfaceType::S16) => true,
140             (InterfaceType::S16, _) => false,
141             (InterfaceType::S32, InterfaceType::S32) => true,
142             (InterfaceType::S32, _) => false,
143             (InterfaceType::S64, InterfaceType::S64) => true,
144             (InterfaceType::S64, _) => false,
145             (InterfaceType::Float32, InterfaceType::Float32) => true,
146             (InterfaceType::Float32, _) => false,
147             (InterfaceType::Float64, InterfaceType::Float64) => true,
148             (InterfaceType::Float64, _) => false,
149             (InterfaceType::String, InterfaceType::String) => true,
150             (InterfaceType::String, _) => false,
151             (InterfaceType::Char, InterfaceType::Char) => true,
152             (InterfaceType::Char, _) => false,
153             (InterfaceType::Future(t1), InterfaceType::Future(t2)) => {
154                 self.future_table_types_equal(t1, t2)
155             }
156             (InterfaceType::Future(_), _) => false,
157             (InterfaceType::Stream(t1), InterfaceType::Stream(t2)) => {
158                 self.stream_table_types_equal(t1, t2)
159             }
160             (InterfaceType::Stream(_), _) => false,
161             (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true,
162             (InterfaceType::ErrorContext(_), _) => false,
163             (InterfaceType::FixedLengthList(_), _) => todo!(), // FIXME(#12279)
164         }
165     }
166 
lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool167     fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
168         let a = &self.a_types[l1];
169         let b = &self.b_types[l2];
170         self.interface_types_equal(a.element, b.element)
171     }
172 
maps_equal(&self, m1: TypeMapIndex, m2: TypeMapIndex) -> bool173     fn maps_equal(&self, m1: TypeMapIndex, m2: TypeMapIndex) -> bool {
174         let a = &self.a_types[m1];
175         let b = &self.b_types[m2];
176         self.interface_types_equal(a.key, b.key) && self.interface_types_equal(a.value, b.value)
177     }
178 
resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool179     fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
180         match (&self.a_types[o1], &self.b_types[o2]) {
181             // Concrete resource types are the same if they map back to the
182             // exact same `ResourceType` at runtime, so look them up in resource
183             // type tables and compare the types themselves.
184             (
185                 TypeResourceTable::Concrete { ty: a, .. },
186                 TypeResourceTable::Concrete { ty: b, .. },
187             ) => self.a_resource[*a] == self.b_resource[*b],
188             (TypeResourceTable::Concrete { .. }, _) => false,
189 
190             // Abstract resource types are only the same if they have the same
191             // index and come from the exact same component.
192             (TypeResourceTable::Abstract(a), TypeResourceTable::Abstract(b)) => {
193                 core::ptr::eq(self.a_types, self.b_types) && a == b
194             }
195             (TypeResourceTable::Abstract(_), _) => false,
196         }
197     }
198 
records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool199     fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
200         let a = &self.a_types[r1];
201         let b = &self.b_types[r2];
202         if a.fields.len() != b.fields.len() {
203             return false;
204         }
205         a.fields
206             .iter()
207             .zip(b.fields.iter())
208             .all(|(a_field, b_field)| {
209                 a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
210             })
211     }
212 
variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool213     fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
214         let a = &self.a_types[v1];
215         let b = &self.b_types[v2];
216         if a.cases.len() != b.cases.len() {
217             return false;
218         }
219         a.cases
220             .iter()
221             .zip(b.cases.iter())
222             .all(|((a_name, a_ty), (b_name, b_ty))| {
223                 if a_name != b_name {
224                     return false;
225                 }
226                 match (a_ty, b_ty) {
227                     (Some(a_case_ty), Some(b_case_ty)) => {
228                         self.interface_types_equal(*a_case_ty, *b_case_ty)
229                     }
230                     (None, None) => true,
231                     _ => false,
232                 }
233             })
234     }
235 
results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool236     fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
237         let a = &self.a_types[r1];
238         let b = &self.b_types[r2];
239         let oks = match (a.ok, b.ok) {
240             (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
241             (None, None) => true,
242             _ => false,
243         };
244         if !oks {
245             return false;
246         }
247         match (a.err, b.err) {
248             (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
249             (None, None) => true,
250             _ => false,
251         }
252     }
253 
options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool254     fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
255         let a = &self.a_types[o1];
256         let b = &self.b_types[o2];
257         self.interface_types_equal(a.ty, b.ty)
258     }
259 
enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool260     fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
261         let a = &self.a_types[e1];
262         let b = &self.b_types[e2];
263         a.names == b.names
264     }
265 
tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool266     fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
267         let a = &self.a_types[t1];
268         let b = &self.b_types[t2];
269         if a.types.len() != b.types.len() {
270             return false;
271         }
272         a.types
273             .iter()
274             .zip(b.types.iter())
275             .all(|(&a, &b)| self.interface_types_equal(a, b))
276     }
277 
flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool278     fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
279         let a = &self.a_types[f1];
280         let b = &self.b_types[f2];
281         a.names == b.names
282     }
283 
future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool284     fn future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool {
285         self.futures_equal(self.a_types[t1].ty, self.b_types[t2].ty)
286     }
287 
futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool288     fn futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool {
289         let a = &self.a_types[t1];
290         let b = &self.b_types[t2];
291         match (a.payload, b.payload) {
292             (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
293             (None, None) => true,
294             _ => false,
295         }
296     }
297 
stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool298     fn stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool {
299         self.streams_equal(self.a_types[t1].ty, self.b_types[t2].ty)
300     }
301 
streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> bool302     fn streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> bool {
303         let a = &self.a_types[t1];
304         let b = &self.b_types[t2];
305         match (a.payload, b.payload) {
306             (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
307             (None, None) => true,
308             _ => false,
309         }
310     }
311 }
312 
313 /// A `list` interface type
314 #[derive(Clone, Debug)]
315 pub struct List(Handle<TypeListIndex>);
316 
317 impl PartialEq for List {
eq(&self, other: &Self) -> bool318     fn eq(&self, other: &Self) -> bool {
319         self.0.equivalent(&other.0, TypeChecker::lists_equal)
320     }
321 }
322 
323 impl Eq for List {}
324 
325 impl List {
from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self326     pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
327         List(Handle::new(index, ty))
328     }
329 
330     /// Retrieve the element type of this `list`.
ty(&self) -> Type331     pub fn ty(&self) -> Type {
332         Type::from(&self.0.types[self.0.index].element, &self.0.instance())
333     }
334 }
335 
336 /// A `map` interface type
337 #[derive(Clone, Debug)]
338 pub struct Map(Handle<TypeMapIndex>);
339 
340 impl PartialEq for Map {
eq(&self, other: &Self) -> bool341     fn eq(&self, other: &Self) -> bool {
342         self.0.equivalent(&other.0, TypeChecker::maps_equal)
343     }
344 }
345 
346 impl Eq for Map {}
347 
348 impl Map {
from(index: TypeMapIndex, ty: &InstanceType<'_>) -> Self349     pub(crate) fn from(index: TypeMapIndex, ty: &InstanceType<'_>) -> Self {
350         Map(Handle::new(index, ty))
351     }
352 
353     /// Retrieve the key type of this `map`.
key(&self) -> Type354     pub fn key(&self) -> Type {
355         Type::from(&self.0.types[self.0.index].key, &self.0.instance())
356     }
357 
358     /// Retrieve the value type of this `map`.
value(&self) -> Type359     pub fn value(&self) -> Type {
360         Type::from(&self.0.types[self.0.index].value, &self.0.instance())
361     }
362 }
363 
364 /// A field declaration belonging to a `record`
365 #[derive(Debug)]
366 pub struct Field<'a> {
367     /// The name of the field
368     pub name: &'a str,
369     /// The type of the field
370     pub ty: Type,
371 }
372 
373 /// A `record` interface type
374 #[derive(Clone, Debug)]
375 pub struct Record(Handle<TypeRecordIndex>);
376 
377 impl Record {
from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self378     pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
379         Record(Handle::new(index, ty))
380     }
381 
382     /// Retrieve the fields of this `record` in declaration order.
fields(&self) -> impl ExactSizeIterator<Item = Field<'_>>383     pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
384         self.0.types[self.0.index].fields.iter().map(|field| Field {
385             name: &field.name,
386             ty: Type::from(&field.ty, &self.0.instance()),
387         })
388     }
389 }
390 
391 impl PartialEq for Record {
eq(&self, other: &Self) -> bool392     fn eq(&self, other: &Self) -> bool {
393         self.0.equivalent(&other.0, TypeChecker::records_equal)
394     }
395 }
396 
397 impl Eq for Record {}
398 
399 /// A `tuple` interface type
400 #[derive(Clone, Debug)]
401 pub struct Tuple(Handle<TypeTupleIndex>);
402 
403 impl Tuple {
from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self404     pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
405         Tuple(Handle::new(index, ty))
406     }
407 
408     /// Retrieve the types of the fields of this `tuple` in declaration order.
types(&self) -> impl ExactSizeIterator<Item = Type> + '_409     pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
410         self.0.types[self.0.index]
411             .types
412             .iter()
413             .map(|ty| Type::from(ty, &self.0.instance()))
414     }
415 }
416 
417 impl PartialEq for Tuple {
eq(&self, other: &Self) -> bool418     fn eq(&self, other: &Self) -> bool {
419         self.0.equivalent(&other.0, TypeChecker::tuples_equal)
420     }
421 }
422 
423 impl Eq for Tuple {}
424 
425 /// A case declaration belonging to a `variant`
426 pub struct Case<'a> {
427     /// The name of the case
428     pub name: &'a str,
429     /// The optional payload type of the case
430     pub ty: Option<Type>,
431 }
432 
433 /// A `variant` interface type
434 #[derive(Clone, Debug)]
435 pub struct Variant(Handle<TypeVariantIndex>);
436 
437 impl Variant {
from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self438     pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
439         Variant(Handle::new(index, ty))
440     }
441 
442     /// Retrieve the cases of this `variant` in declaration order.
cases(&self) -> impl ExactSizeIterator<Item = Case<'_>>443     pub fn cases(&self) -> impl ExactSizeIterator<Item = Case<'_>> {
444         self.0.types[self.0.index]
445             .cases
446             .iter()
447             .map(|(name, ty)| Case {
448                 name,
449                 ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
450             })
451     }
452 }
453 
454 impl PartialEq for Variant {
eq(&self, other: &Self) -> bool455     fn eq(&self, other: &Self) -> bool {
456         self.0.equivalent(&other.0, TypeChecker::variants_equal)
457     }
458 }
459 
460 impl Eq for Variant {}
461 
462 /// An `enum` interface type
463 #[derive(Clone, Debug)]
464 pub struct Enum(Handle<TypeEnumIndex>);
465 
466 impl Enum {
from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self467     pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
468         Enum(Handle::new(index, ty))
469     }
470 
471     /// Retrieve the names of the cases of this `enum` in declaration order.
names(&self) -> impl ExactSizeIterator<Item = &str>472     pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
473         self.0.types[self.0.index]
474             .names
475             .iter()
476             .map(|name| name.deref())
477     }
478 }
479 
480 impl PartialEq for Enum {
eq(&self, other: &Self) -> bool481     fn eq(&self, other: &Self) -> bool {
482         self.0.equivalent(&other.0, TypeChecker::enums_equal)
483     }
484 }
485 
486 impl Eq for Enum {}
487 
488 /// An `option` interface type
489 #[derive(Clone, Debug)]
490 pub struct OptionType(Handle<TypeOptionIndex>);
491 
492 impl OptionType {
from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self493     pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
494         OptionType(Handle::new(index, ty))
495     }
496 
497     /// Retrieve the type parameter for this `option`.
ty(&self) -> Type498     pub fn ty(&self) -> Type {
499         Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
500     }
501 }
502 
503 impl PartialEq for OptionType {
eq(&self, other: &Self) -> bool504     fn eq(&self, other: &Self) -> bool {
505         self.0.equivalent(&other.0, TypeChecker::options_equal)
506     }
507 }
508 
509 impl Eq for OptionType {}
510 
511 /// A `result` interface type
512 #[derive(Clone, Debug)]
513 pub struct ResultType(Handle<TypeResultIndex>);
514 
515 impl ResultType {
from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self516     pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
517         ResultType(Handle::new(index, ty))
518     }
519 
520     /// Retrieve the `ok` type parameter for this `result`.
ok(&self) -> Option<Type>521     pub fn ok(&self) -> Option<Type> {
522         Some(Type::from(
523             self.0.types[self.0.index].ok.as_ref()?,
524             &self.0.instance(),
525         ))
526     }
527 
528     /// Retrieve the `err` type parameter for this `result`.
err(&self) -> Option<Type>529     pub fn err(&self) -> Option<Type> {
530         Some(Type::from(
531             self.0.types[self.0.index].err.as_ref()?,
532             &self.0.instance(),
533         ))
534     }
535 }
536 
537 impl PartialEq for ResultType {
eq(&self, other: &Self) -> bool538     fn eq(&self, other: &Self) -> bool {
539         self.0.equivalent(&other.0, TypeChecker::results_equal)
540     }
541 }
542 
543 impl Eq for ResultType {}
544 
545 /// A `flags` interface type
546 #[derive(Clone, Debug)]
547 pub struct Flags(Handle<TypeFlagsIndex>);
548 
549 impl Flags {
from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self550     pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
551         Flags(Handle::new(index, ty))
552     }
553 
554     /// Retrieve the names of the flags of this `flags` type in declaration order.
names(&self) -> impl ExactSizeIterator<Item = &str>555     pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
556         self.0.types[self.0.index]
557             .names
558             .iter()
559             .map(|name| name.deref())
560     }
561 }
562 
563 impl PartialEq for Flags {
eq(&self, other: &Self) -> bool564     fn eq(&self, other: &Self) -> bool {
565         self.0.equivalent(&other.0, TypeChecker::flags_equal)
566     }
567 }
568 
569 impl Eq for Flags {}
570 
571 #[cfg(feature = "component-model-async")]
typecheck_payload<T>( payload: Option<&InterfaceType>, types: &InstanceType<'_>, ) -> crate::Result<()> where T: ComponentType,572 pub(crate) fn typecheck_payload<T>(
573     payload: Option<&InterfaceType>,
574     types: &InstanceType<'_>,
575 ) -> crate::Result<()>
576 where
577     T: ComponentType,
578 {
579     match payload {
580         Some(a) => T::typecheck(a, types),
581         None => {
582             if T::IS_RUST_UNIT_TYPE {
583                 Ok(())
584             } else {
585                 crate::bail!("future payload types differ")
586             }
587         }
588     }
589 }
590 
591 /// An `future` interface type
592 #[derive(Clone, Debug)]
593 pub struct FutureType(Handle<TypeFutureIndex>);
594 
595 impl FutureType {
from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self596     pub(crate) fn from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self {
597         FutureType(Handle::new(index, ty))
598     }
599 
600     /// Retrieve the type parameter for this `future`.
ty(&self) -> Option<Type>601     pub fn ty(&self) -> Option<Type> {
602         Some(Type::from(
603             self.0.types[self.0.index].payload.as_ref()?,
604             &self.0.instance(),
605         ))
606     }
607 
608     #[cfg(feature = "component-model-async")]
equivalent_payload_guest( &self, ty: &InstanceType<'_>, payload: Option<&InterfaceType>, ) -> bool609     pub(crate) fn equivalent_payload_guest(
610         &self,
611         ty: &InstanceType<'_>,
612         payload: Option<&InterfaceType>,
613     ) -> bool {
614         let my_payload = self.0.types[self.0.index].payload.as_ref();
615         match (my_payload, payload) {
616             (Some(a), Some(b)) => TypeChecker {
617                 a_types: &self.0.types,
618                 a_resource: &self.0.resources,
619                 b_types: ty.types,
620                 b_resource: ty.resources,
621             }
622             .interface_types_equal(*a, *b),
623             (None, None) => true,
624             (Some(_), None) | (None, Some(_)) => false,
625         }
626     }
627 
628     #[cfg(feature = "component-model-async")]
equivalent_payload_host<T>(&self) -> crate::Result<()> where T: ComponentType,629     pub(crate) fn equivalent_payload_host<T>(&self) -> crate::Result<()>
630     where
631         T: ComponentType,
632     {
633         typecheck_payload::<T>(
634             self.0.types[self.0.index].payload.as_ref(),
635             &self.0.instance(),
636         )
637     }
638 }
639 
640 impl PartialEq for FutureType {
eq(&self, other: &Self) -> bool641     fn eq(&self, other: &Self) -> bool {
642         self.0.equivalent(&other.0, TypeChecker::futures_equal)
643     }
644 }
645 
646 impl Eq for FutureType {}
647 
648 /// An `stream` interface type
649 #[derive(Clone, Debug)]
650 pub struct StreamType(Handle<TypeStreamIndex>);
651 
652 impl StreamType {
from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self653     pub(crate) fn from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self {
654         StreamType(Handle::new(index, ty))
655     }
656 
657     /// Retrieve the type parameter for this `stream`.
ty(&self) -> Option<Type>658     pub fn ty(&self) -> Option<Type> {
659         Some(Type::from(
660             self.0.types[self.0.index].payload.as_ref()?,
661             &self.0.instance(),
662         ))
663     }
664 
665     #[cfg(feature = "component-model-async")]
equivalent_payload_guest( &self, ty: &InstanceType<'_>, payload: Option<&InterfaceType>, ) -> bool666     pub(crate) fn equivalent_payload_guest(
667         &self,
668         ty: &InstanceType<'_>,
669         payload: Option<&InterfaceType>,
670     ) -> bool {
671         let my_payload = self.0.types[self.0.index].payload.as_ref();
672         match (my_payload, payload) {
673             (Some(a), Some(b)) => TypeChecker {
674                 a_types: &self.0.types,
675                 a_resource: &self.0.resources,
676                 b_types: ty.types,
677                 b_resource: ty.resources,
678             }
679             .interface_types_equal(*a, *b),
680             (None, None) => true,
681             (Some(_), None) | (None, Some(_)) => false,
682         }
683     }
684 
685     #[cfg(feature = "component-model-async")]
equivalent_payload_host<T>(&self) -> crate::Result<()> where T: ComponentType,686     pub(crate) fn equivalent_payload_host<T>(&self) -> crate::Result<()>
687     where
688         T: ComponentType,
689     {
690         typecheck_payload::<T>(
691             self.0.types[self.0.index].payload.as_ref(),
692             &self.0.instance(),
693         )
694     }
695 }
696 
697 impl PartialEq for StreamType {
eq(&self, other: &Self) -> bool698     fn eq(&self, other: &Self) -> bool {
699         self.0.equivalent(&other.0, TypeChecker::streams_equal)
700     }
701 }
702 
703 impl Eq for StreamType {}
704 
705 /// Represents a component model interface type
706 #[derive(Clone, PartialEq, Eq, Debug)]
707 #[expect(missing_docs, reason = "self-describing variants")]
708 pub enum Type {
709     Bool,
710     S8,
711     U8,
712     S16,
713     U16,
714     S32,
715     U32,
716     S64,
717     U64,
718     Float32,
719     Float64,
720     Char,
721     String,
722     List(List),
723     Map(Map),
724     Record(Record),
725     Tuple(Tuple),
726     Variant(Variant),
727     Enum(Enum),
728     Option(OptionType),
729     Result(ResultType),
730     Flags(Flags),
731     Own(ResourceType),
732     Borrow(ResourceType),
733     Future(FutureType),
734     Stream(StreamType),
735     ErrorContext,
736 }
737 
738 impl Type {
739     /// Retrieve the inner [`List`] of a [`Type::List`].
740     ///
741     /// # Panics
742     ///
743     /// This will panic if `self` is not a [`Type::List`].
unwrap_list(&self) -> &List744     pub fn unwrap_list(&self) -> &List {
745         if let Type::List(handle) = self {
746             &handle
747         } else {
748             panic!("attempted to unwrap a {} as a list", self.desc())
749         }
750     }
751 
752     /// Retrieve the inner [`Record`] of a [`Type::Record`].
753     ///
754     /// # Panics
755     ///
756     /// This will panic if `self` is not a [`Type::Record`].
unwrap_record(&self) -> &Record757     pub fn unwrap_record(&self) -> &Record {
758         if let Type::Record(handle) = self {
759             &handle
760         } else {
761             panic!("attempted to unwrap a {} as a record", self.desc())
762         }
763     }
764 
765     /// Retrieve the inner [`Tuple`] of a [`Type::Tuple`].
766     ///
767     /// # Panics
768     ///
769     /// This will panic if `self` is not a [`Type::Tuple`].
unwrap_tuple(&self) -> &Tuple770     pub fn unwrap_tuple(&self) -> &Tuple {
771         if let Type::Tuple(handle) = self {
772             &handle
773         } else {
774             panic!("attempted to unwrap a {} as a tuple", self.desc())
775         }
776     }
777 
778     /// Retrieve the inner [`Variant`] of a [`Type::Variant`].
779     ///
780     /// # Panics
781     ///
782     /// This will panic if `self` is not a [`Type::Variant`].
unwrap_variant(&self) -> &Variant783     pub fn unwrap_variant(&self) -> &Variant {
784         if let Type::Variant(handle) = self {
785             &handle
786         } else {
787             panic!("attempted to unwrap a {} as a variant", self.desc())
788         }
789     }
790 
791     /// Retrieve the inner [`Enum`] of a [`Type::Enum`].
792     ///
793     /// # Panics
794     ///
795     /// This will panic if `self` is not a [`Type::Enum`].
unwrap_enum(&self) -> &Enum796     pub fn unwrap_enum(&self) -> &Enum {
797         if let Type::Enum(handle) = self {
798             &handle
799         } else {
800             panic!("attempted to unwrap a {} as a enum", self.desc())
801         }
802     }
803 
804     /// Retrieve the inner [`OptionType`] of a [`Type::Option`].
805     ///
806     /// # Panics
807     ///
808     /// This will panic if `self` is not a [`Type::Option`].
unwrap_option(&self) -> &OptionType809     pub fn unwrap_option(&self) -> &OptionType {
810         if let Type::Option(handle) = self {
811             &handle
812         } else {
813             panic!("attempted to unwrap a {} as a option", self.desc())
814         }
815     }
816 
817     /// Retrieve the inner [`ResultType`] of a [`Type::Result`].
818     ///
819     /// # Panics
820     ///
821     /// This will panic if `self` is not a [`Type::Result`].
unwrap_result(&self) -> &ResultType822     pub fn unwrap_result(&self) -> &ResultType {
823         if let Type::Result(handle) = self {
824             &handle
825         } else {
826             panic!("attempted to unwrap a {} as a result", self.desc())
827         }
828     }
829 
830     /// Retrieve the inner [`Flags`] of a [`Type::Flags`].
831     ///
832     /// # Panics
833     ///
834     /// This will panic if `self` is not a [`Type::Flags`].
unwrap_flags(&self) -> &Flags835     pub fn unwrap_flags(&self) -> &Flags {
836         if let Type::Flags(handle) = self {
837             &handle
838         } else {
839             panic!("attempted to unwrap a {} as a flags", self.desc())
840         }
841     }
842 
843     /// Retrieve the inner [`ResourceType`] of a [`Type::Own`].
844     ///
845     /// # Panics
846     ///
847     /// This will panic if `self` is not a [`Type::Own`].
unwrap_own(&self) -> &ResourceType848     pub fn unwrap_own(&self) -> &ResourceType {
849         match self {
850             Type::Own(ty) => ty,
851             _ => panic!("attempted to unwrap a {} as a own", self.desc()),
852         }
853     }
854 
855     /// Retrieve the inner [`ResourceType`] of a [`Type::Borrow`].
856     ///
857     /// # Panics
858     ///
859     /// This will panic if `self` is not a [`Type::Borrow`].
unwrap_borrow(&self) -> &ResourceType860     pub fn unwrap_borrow(&self) -> &ResourceType {
861         match self {
862             Type::Borrow(ty) => ty,
863             _ => panic!("attempted to unwrap a {} as a own", self.desc()),
864         }
865     }
866 
867     /// Convert the specified `InterfaceType` to a `Type`.
from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self868     pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
869         match ty {
870             InterfaceType::Bool => Type::Bool,
871             InterfaceType::S8 => Type::S8,
872             InterfaceType::U8 => Type::U8,
873             InterfaceType::S16 => Type::S16,
874             InterfaceType::U16 => Type::U16,
875             InterfaceType::S32 => Type::S32,
876             InterfaceType::U32 => Type::U32,
877             InterfaceType::S64 => Type::S64,
878             InterfaceType::U64 => Type::U64,
879             InterfaceType::Float32 => Type::Float32,
880             InterfaceType::Float64 => Type::Float64,
881             InterfaceType::Char => Type::Char,
882             InterfaceType::String => Type::String,
883             InterfaceType::List(index) => Type::List(List::from(*index, instance)),
884             InterfaceType::Map(index) => Type::Map(Map::from(*index, instance)),
885             InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
886             InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
887             InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
888             InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
889             InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
890             InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
891             InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
892             InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
893             InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
894             InterfaceType::Future(index) => Type::Future(instance.future_type(*index)),
895             InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)),
896             InterfaceType::ErrorContext(_) => Type::ErrorContext,
897             InterfaceType::FixedLengthList(_) => todo!(), // FIXME(#12279)
898         }
899     }
900 
desc(&self) -> &'static str901     fn desc(&self) -> &'static str {
902         match self {
903             Type::Bool => "bool",
904             Type::S8 => "s8",
905             Type::U8 => "u8",
906             Type::S16 => "s16",
907             Type::U16 => "u16",
908             Type::S32 => "s32",
909             Type::U32 => "u32",
910             Type::S64 => "s64",
911             Type::U64 => "u64",
912             Type::Float32 => "float32",
913             Type::Float64 => "float64",
914             Type::Char => "char",
915             Type::String => "string",
916             Type::List(_) => "list",
917             Type::Map(_) => "map",
918             Type::Record(_) => "record",
919             Type::Tuple(_) => "tuple",
920             Type::Variant(_) => "variant",
921             Type::Enum(_) => "enum",
922             Type::Option(_) => "option",
923             Type::Result(_) => "result",
924             Type::Flags(_) => "flags",
925             Type::Own(_) => "own",
926             Type::Borrow(_) => "borrow",
927             Type::Future(_) => "future",
928             Type::Stream(_) => "stream",
929             Type::ErrorContext => "error-context",
930         }
931     }
932 }
933 
934 /// Component function type
935 #[derive(Clone, Debug)]
936 pub struct ComponentFunc(Handle<TypeFuncIndex>);
937 
938 impl ComponentFunc {
from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self939     pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
940         Self(Handle::new(index, ty))
941     }
942 
943     /// Returns whether this is an async function
async_(&self) -> bool944     pub fn async_(&self) -> bool {
945         self.0.types[self.0.index].async_
946     }
947 
948     /// Iterates over types of function parameters and names.
params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_949     pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
950         let ty = &self.0.types[self.0.index];
951         self.0.types[ty.params]
952             .types
953             .iter()
954             .zip(&ty.param_names)
955             .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
956     }
957 
958     /// Iterates over types of function results
results(&self) -> impl ExactSizeIterator<Item = Type> + '_959     pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
960         let results = self.0.types[self.0.index].results;
961         self.0.types[results]
962             .types
963             .iter()
964             .map(|ty| Type::from(ty, &self.0.instance()))
965     }
966 
967     #[doc(hidden)]
typecheck<Params, Return>(&self, cx: &InstanceType) -> crate::Result<()> where Params: crate::component::ComponentNamedList + crate::component::Lower, Return: crate::component::ComponentNamedList + crate::component::Lift,968     pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> crate::Result<()>
969     where
970         Params: crate::component::ComponentNamedList + crate::component::Lower,
971         Return: crate::component::ComponentNamedList + crate::component::Lift,
972     {
973         let ty = &self.0.types[self.0.index];
974         Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
975         Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
976         Ok(())
977     }
978 }
979 
980 /// Core module type
981 #[derive(Clone, Debug)]
982 pub struct Module(Handle<TypeModuleIndex>);
983 
984 impl Module {
from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self985     pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
986         Self(Handle::new(index, ty))
987     }
988 
989     /// Iterates over imports of the module
imports<'a>( &'a self, engine: &'a Engine, ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a990     pub fn imports<'a>(
991         &'a self,
992         engine: &'a Engine,
993     ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
994         self.0.types[self.0.index]
995             .imports
996             .iter()
997             .map(|((namespace, name), ty)| {
998                 (
999                     (namespace.as_str(), name.as_str()),
1000                     ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
1001                 )
1002             })
1003     }
1004 
1005     /// Iterates over exports of the module
exports<'a>( &'a self, engine: &'a Engine, ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a1006     pub fn exports<'a>(
1007         &'a self,
1008         engine: &'a Engine,
1009     ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
1010         self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
1011             (
1012                 name.as_str(),
1013                 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
1014             )
1015         })
1016     }
1017 }
1018 
1019 /// Component type
1020 #[derive(Clone, Debug)]
1021 pub struct Component(Handle<TypeComponentIndex>);
1022 
1023 impl Component {
from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self1024     pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
1025         Self(Handle::new(index, ty))
1026     }
1027 
1028     /// Returns import associated with `name`, if such exists in the component
get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem>1029     pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
1030         self.0.types[self.0.index]
1031             .imports
1032             .get(name)
1033             .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
1034     }
1035 
1036     /// Iterates over imports of the component
imports<'a>( &'a self, engine: &'a Engine, ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a1037     pub fn imports<'a>(
1038         &'a self,
1039         engine: &'a Engine,
1040     ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
1041         self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
1042             (
1043                 name.as_str(),
1044                 ComponentItem::from(engine, ty, &self.0.instance()),
1045             )
1046         })
1047     }
1048 
1049     /// Returns export associated with `name`, if such exists in the component
get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem>1050     pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
1051         self.0.types[self.0.index]
1052             .exports
1053             .get(name)
1054             .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
1055     }
1056 
1057     /// Iterates over exports of the component
exports<'a>( &'a self, engine: &'a Engine, ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a1058     pub fn exports<'a>(
1059         &'a self,
1060         engine: &'a Engine,
1061     ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
1062         self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
1063             (
1064                 name.as_str(),
1065                 ComponentItem::from(engine, ty, &self.0.instance()),
1066             )
1067         })
1068     }
1069 
1070     #[doc(hidden)]
instance_type(&self) -> InstanceType<'_>1071     pub fn instance_type(&self) -> InstanceType<'_> {
1072         InstanceType {
1073             types: &self.0.types,
1074             resources: &self.0.resources,
1075         }
1076     }
1077 }
1078 
1079 /// Component instance type
1080 #[derive(Clone, Debug)]
1081 pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
1082 
1083 impl ComponentInstance {
from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self1084     pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
1085         Self(Handle::new(index, ty))
1086     }
1087 
1088     /// Returns export associated with `name`, if such exists in the component instance
get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem>1089     pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
1090         self.0.types[self.0.index]
1091             .exports
1092             .get(name)
1093             .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
1094     }
1095 
1096     /// Iterates over exports of the component instance
exports<'a>( &'a self, engine: &'a Engine, ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)>1097     pub fn exports<'a>(
1098         &'a self,
1099         engine: &'a Engine,
1100     ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> {
1101         self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
1102             (
1103                 name.as_str(),
1104                 ComponentItem::from(engine, ty, &self.0.instance()),
1105             )
1106         })
1107     }
1108 }
1109 
1110 /// Type of an item contained within the component
1111 #[derive(Clone, Debug)]
1112 pub enum ComponentItem {
1113     /// Component function item
1114     ComponentFunc(ComponentFunc),
1115     /// Core function item
1116     CoreFunc(FuncType),
1117     /// Core module item
1118     Module(Module),
1119     /// Component item
1120     Component(Component),
1121     /// Component instance item
1122     ComponentInstance(ComponentInstance),
1123     /// Interface type item
1124     Type(Type),
1125     /// Resource item
1126     Resource(ResourceType),
1127 }
1128 
1129 impl ComponentItem {
from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self1130     pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
1131         match def {
1132             TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
1133             TypeDef::ComponentInstance(idx) => {
1134                 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1135             }
1136             TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
1137             TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
1138             TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
1139             TypeDef::CoreFunc(idx) => {
1140                 let subty = &ty.types[*idx];
1141                 Self::CoreFunc(
1142                     FuncType::from_wasm_func_type(
1143                         engine,
1144                         subty.is_final,
1145                         subty.supertype,
1146                         subty.unwrap_func().try_clone().panic_on_oom(),
1147                     )
1148                     .panic_on_oom(),
1149                 )
1150             }
1151             TypeDef::Resource(idx) => match ty.types[*idx] {
1152                 TypeResourceTable::Concrete {
1153                     ty: resource_index, ..
1154                 } => {
1155                     let ty = match ty.resources.get(resource_index) {
1156                         // This resource type was substituted by a linker for
1157                         // example so it's replaced here.
1158                         Some(ty) => *ty,
1159 
1160                         // This resource type was not substituted.
1161                         None => ResourceType::uninstantiated(&ty.types, resource_index),
1162                     };
1163                     Self::Resource(ty)
1164                 }
1165                 TypeResourceTable::Abstract(resource_index) => {
1166                     Self::Resource(ResourceType::abstract_(&ty.types, resource_index))
1167                 }
1168             },
1169         }
1170     }
from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self1171     pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
1172         match export {
1173             Export::Instance { ty: idx, .. } => {
1174                 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1175             }
1176             Export::LiftedFunction { ty: idx, .. } => {
1177                 Self::ComponentFunc(ComponentFunc::from(*idx, ty))
1178             }
1179             Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
1180                 Self::Module(Module::from(*idx, ty))
1181             }
1182             Export::Type(idx) => Self::from(engine, idx, ty),
1183         }
1184     }
1185 }
1186