wasmtime/runtime/
types.rs

1use crate::prelude::*;
2use core::fmt::{self, Display, Write};
3use wasmtime_environ::{
4    EngineOrModuleTypeIndex, EntityType, Global, Memory, ModuleTypes, Table, TypeTrace,
5    VMSharedTypeIndex, WasmArrayType, WasmCompositeType, WasmFieldType, WasmFuncType, WasmHeapType,
6    WasmRefType, WasmStorageType, WasmStructType, WasmSubType, WasmValType,
7};
8
9use crate::{type_registry::RegisteredType, Engine};
10
11pub(crate) mod matching;
12
13// Type Representations
14
15// Type attributes
16
17/// Indicator of whether a global value, struct's field, or array type's
18/// elements are mutable or not.
19#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
20pub enum Mutability {
21    /// The global value, struct field, or array elements are constant and the
22    /// value does not change.
23    Const,
24    /// The value of the global, struct field, or array elements can change over
25    /// time.
26    Var,
27}
28
29impl Mutability {
30    /// Is this constant?
31    #[inline]
32    pub fn is_const(&self) -> bool {
33        *self == Self::Const
34    }
35
36    /// Is this variable?
37    #[inline]
38    pub fn is_var(&self) -> bool {
39        *self == Self::Var
40    }
41}
42
43/// Indicator of whether a type is final or not.
44///
45/// Final types may not be the supertype of other types.
46#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
47pub enum Finality {
48    /// The associated type is final.
49    Final,
50    /// The associated type is not final.
51    NonFinal,
52}
53
54impl Finality {
55    /// Is this final?
56    #[inline]
57    pub fn is_final(&self) -> bool {
58        *self == Self::Final
59    }
60
61    /// Is this non-final?
62    #[inline]
63    pub fn is_non_final(&self) -> bool {
64        *self == Self::NonFinal
65    }
66}
67
68// Value Types
69
70/// A list of all possible value types in WebAssembly.
71///
72/// # Subtyping and Equality
73///
74/// `ValType` does not implement `Eq`, because reference types have a subtyping
75/// relationship, and so 99.99% of the time you actually want to check whether
76/// one type matches (i.e. is a subtype of) another type. You can use the
77/// [`ValType::matches`] and [`Val::matches_ty`][crate::Val::matches_ty] methods
78/// to perform these types of checks. If, however, you are in that 0.01%
79/// scenario where you need to check precise equality between types, you can use
80/// the [`ValType::eq`] method.
81#[derive(Clone, Hash)]
82pub enum ValType {
83    // NB: the ordering of variants here is intended to match the ordering in
84    // `wasmtime_types::WasmType` to help improve codegen when converting.
85    //
86    /// Signed 32 bit integer.
87    I32,
88    /// Signed 64 bit integer.
89    I64,
90    /// Floating point 32 bit integer.
91    F32,
92    /// Floating point 64 bit integer.
93    F64,
94    /// A 128 bit number.
95    V128,
96    /// An opaque reference to some type on the heap.
97    Ref(RefType),
98}
99
100impl fmt::Debug for ValType {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        fmt::Display::fmt(self, f)
103    }
104}
105
106impl Display for ValType {
107    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
108        match self {
109            ValType::I32 => write!(f, "i32"),
110            ValType::I64 => write!(f, "i64"),
111            ValType::F32 => write!(f, "f32"),
112            ValType::F64 => write!(f, "f64"),
113            ValType::V128 => write!(f, "v128"),
114            ValType::Ref(r) => Display::fmt(r, f),
115        }
116    }
117}
118
119impl From<RefType> for ValType {
120    #[inline]
121    fn from(r: RefType) -> Self {
122        ValType::Ref(r)
123    }
124}
125
126impl ValType {
127    /// The `externref` type, aka `(ref null extern)`.
128    pub const EXTERNREF: Self = ValType::Ref(RefType::EXTERNREF);
129
130    /// The `nullexternref` type, aka `(ref null noextern)`.
131    pub const NULLEXTERNREF: Self = ValType::Ref(RefType::NULLEXTERNREF);
132
133    /// The `funcref` type, aka `(ref null func)`.
134    pub const FUNCREF: Self = ValType::Ref(RefType::FUNCREF);
135
136    /// The `nullfuncref` type, aka `(ref null nofunc)`.
137    pub const NULLFUNCREF: Self = ValType::Ref(RefType::NULLFUNCREF);
138
139    /// The `anyref` type, aka `(ref null any)`.
140    pub const ANYREF: Self = ValType::Ref(RefType::ANYREF);
141
142    /// The `i31ref` type, aka `(ref null i31)`.
143    pub const I31REF: Self = ValType::Ref(RefType::I31REF);
144
145    /// The `arrayref` type, aka `(ref null array)`.
146    pub const ARRAYREF: Self = ValType::Ref(RefType::ARRAYREF);
147
148    /// The `structref` type, aka `(ref null struct)`.
149    pub const STRUCTREF: Self = ValType::Ref(RefType::STRUCTREF);
150
151    /// The `nullref` type, aka `(ref null none)`.
152    pub const NULLREF: Self = ValType::Ref(RefType::NULLREF);
153
154    /// Returns true if `ValType` matches any of the numeric types. (e.g. `I32`,
155    /// `I64`, `F32`, `F64`).
156    #[inline]
157    pub fn is_num(&self) -> bool {
158        match self {
159            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 => true,
160            _ => false,
161        }
162    }
163
164    /// Is this the `i32` type?
165    #[inline]
166    pub fn is_i32(&self) -> bool {
167        matches!(self, ValType::I32)
168    }
169
170    /// Is this the `i64` type?
171    #[inline]
172    pub fn is_i64(&self) -> bool {
173        matches!(self, ValType::I64)
174    }
175
176    /// Is this the `f32` type?
177    #[inline]
178    pub fn is_f32(&self) -> bool {
179        matches!(self, ValType::F32)
180    }
181
182    /// Is this the `f64` type?
183    #[inline]
184    pub fn is_f64(&self) -> bool {
185        matches!(self, ValType::F64)
186    }
187
188    /// Is this the `v128` type?
189    #[inline]
190    pub fn is_v128(&self) -> bool {
191        matches!(self, ValType::V128)
192    }
193
194    /// Returns true if `ValType` is any kind of reference type.
195    #[inline]
196    pub fn is_ref(&self) -> bool {
197        matches!(self, ValType::Ref(_))
198    }
199
200    /// Is this the `funcref` (aka `(ref null func)`) type?
201    #[inline]
202    pub fn is_funcref(&self) -> bool {
203        matches!(
204            self,
205            ValType::Ref(RefType {
206                is_nullable: true,
207                heap_type: HeapType::Func
208            })
209        )
210    }
211
212    /// Is this the `externref` (aka `(ref null extern)`) type?
213    #[inline]
214    pub fn is_externref(&self) -> bool {
215        matches!(
216            self,
217            ValType::Ref(RefType {
218                is_nullable: true,
219                heap_type: HeapType::Extern
220            })
221        )
222    }
223
224    /// Is this the `anyref` (aka `(ref null any)`) type?
225    #[inline]
226    pub fn is_anyref(&self) -> bool {
227        matches!(
228            self,
229            ValType::Ref(RefType {
230                is_nullable: true,
231                heap_type: HeapType::Any
232            })
233        )
234    }
235
236    /// Get the underlying reference type, if this value type is a reference
237    /// type.
238    #[inline]
239    pub fn as_ref(&self) -> Option<&RefType> {
240        match self {
241            ValType::Ref(r) => Some(r),
242            _ => None,
243        }
244    }
245
246    /// Get the underlying reference type, panicking if this value type is not a
247    /// reference type.
248    #[inline]
249    pub fn unwrap_ref(&self) -> &RefType {
250        self.as_ref()
251            .expect("ValType::unwrap_ref on a non-reference type")
252    }
253
254    /// Does this value type match the other type?
255    ///
256    /// That is, is this value type a subtype of the other?
257    ///
258    /// # Panics
259    ///
260    /// Panics if either type is associated with a different engine from the
261    /// other.
262    pub fn matches(&self, other: &ValType) -> bool {
263        match (self, other) {
264            (Self::I32, Self::I32) => true,
265            (Self::I64, Self::I64) => true,
266            (Self::F32, Self::F32) => true,
267            (Self::F64, Self::F64) => true,
268            (Self::V128, Self::V128) => true,
269            (Self::Ref(a), Self::Ref(b)) => a.matches(b),
270            (Self::I32, _)
271            | (Self::I64, _)
272            | (Self::F32, _)
273            | (Self::F64, _)
274            | (Self::V128, _)
275            | (Self::Ref(_), _) => false,
276        }
277    }
278
279    /// Is value type `a` precisely equal to value type `b`?
280    ///
281    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
282    /// are not exactly the same value type.
283    ///
284    /// # Panics
285    ///
286    /// Panics if either type is associated with a different engine.
287    pub fn eq(a: &Self, b: &Self) -> bool {
288        a.matches(b) && b.matches(a)
289    }
290
291    /// Is this a `VMGcRef` type that is not i31 and is not an uninhabited
292    /// bottom type?
293    #[inline]
294    pub(crate) fn is_vmgcref_type_and_points_to_object(&self) -> bool {
295        match self {
296            ValType::Ref(r) => r.is_vmgcref_type_and_points_to_object(),
297            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => false,
298        }
299    }
300
301    pub(crate) fn ensure_matches(&self, engine: &Engine, other: &ValType) -> Result<()> {
302        if !self.comes_from_same_engine(engine) || !other.comes_from_same_engine(engine) {
303            bail!("type used with wrong engine");
304        }
305        if self.matches(other) {
306            Ok(())
307        } else {
308            bail!("type mismatch: expected {other}, found {self}")
309        }
310    }
311
312    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
313        match self {
314            Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128 => true,
315            Self::Ref(r) => r.comes_from_same_engine(engine),
316        }
317    }
318
319    pub(crate) fn to_wasm_type(&self) -> WasmValType {
320        match self {
321            Self::I32 => WasmValType::I32,
322            Self::I64 => WasmValType::I64,
323            Self::F32 => WasmValType::F32,
324            Self::F64 => WasmValType::F64,
325            Self::V128 => WasmValType::V128,
326            Self::Ref(r) => WasmValType::Ref(r.to_wasm_type()),
327        }
328    }
329
330    #[inline]
331    pub(crate) fn from_wasm_type(engine: &Engine, ty: &WasmValType) -> Self {
332        match ty {
333            WasmValType::I32 => Self::I32,
334            WasmValType::I64 => Self::I64,
335            WasmValType::F32 => Self::F32,
336            WasmValType::F64 => Self::F64,
337            WasmValType::V128 => Self::V128,
338            WasmValType::Ref(r) => Self::Ref(RefType::from_wasm_type(engine, r)),
339        }
340    }
341
342    /// What is the size (in bytes) of this type's values when they are stored
343    /// inside the GC heap?
344    pub(crate) fn byte_size_in_gc_heap(&self) -> u32 {
345        match self {
346            ValType::I32 => 4,
347            ValType::I64 => 8,
348            ValType::F32 => 4,
349            ValType::F64 => 8,
350            ValType::V128 => 16,
351            ValType::Ref(r) => r.byte_size_in_gc_heap(),
352        }
353    }
354}
355
356/// Opaque references to data in the Wasm heap or to host data.
357///
358/// # Subtyping and Equality
359///
360/// `RefType` does not implement `Eq`, because reference types have a subtyping
361/// relationship, and so 99.99% of the time you actually want to check whether
362/// one type matches (i.e. is a subtype of) another type. You can use the
363/// [`RefType::matches`] and [`Ref::matches_ty`][crate::Ref::matches_ty] methods
364/// to perform these types of checks. If, however, you are in that 0.01%
365/// scenario where you need to check precise equality between types, you can use
366/// the [`RefType::eq`] method.
367#[derive(Clone, Hash)]
368pub struct RefType {
369    is_nullable: bool,
370    heap_type: HeapType,
371}
372
373impl fmt::Debug for RefType {
374    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375        Display::fmt(self, f)
376    }
377}
378
379impl fmt::Display for RefType {
380    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
381        write!(f, "(ref ")?;
382        if self.is_nullable() {
383            write!(f, "null ")?;
384        }
385        write!(f, "{})", self.heap_type())
386    }
387}
388
389impl RefType {
390    /// The `externref` type, aka `(ref null extern)`.
391    pub const EXTERNREF: Self = RefType {
392        is_nullable: true,
393        heap_type: HeapType::Extern,
394    };
395
396    /// The `nullexternref` type, aka `(ref null noextern)`.
397    pub const NULLEXTERNREF: Self = RefType {
398        is_nullable: true,
399        heap_type: HeapType::NoExtern,
400    };
401
402    /// The `funcref` type, aka `(ref null func)`.
403    pub const FUNCREF: Self = RefType {
404        is_nullable: true,
405        heap_type: HeapType::Func,
406    };
407
408    /// The `nullfuncref` type, aka `(ref null nofunc)`.
409    pub const NULLFUNCREF: Self = RefType {
410        is_nullable: true,
411        heap_type: HeapType::NoFunc,
412    };
413
414    /// The `anyref` type, aka `(ref null any)`.
415    pub const ANYREF: Self = RefType {
416        is_nullable: true,
417        heap_type: HeapType::Any,
418    };
419
420    /// The `i31ref` type, aka `(ref null i31)`.
421    pub const I31REF: Self = RefType {
422        is_nullable: true,
423        heap_type: HeapType::I31,
424    };
425
426    /// The `arrayref` type, aka `(ref null array)`.
427    pub const ARRAYREF: Self = RefType {
428        is_nullable: true,
429        heap_type: HeapType::Array,
430    };
431
432    /// The `structref` type, aka `(ref null struct)`.
433    pub const STRUCTREF: Self = RefType {
434        is_nullable: true,
435        heap_type: HeapType::Struct,
436    };
437
438    /// The `nullref` type, aka `(ref null none)`.
439    pub const NULLREF: Self = RefType {
440        is_nullable: true,
441        heap_type: HeapType::None,
442    };
443
444    /// Construct a new reference type.
445    pub fn new(is_nullable: bool, heap_type: HeapType) -> RefType {
446        RefType {
447            is_nullable,
448            heap_type,
449        }
450    }
451
452    /// Can this type of reference be null?
453    pub fn is_nullable(&self) -> bool {
454        self.is_nullable
455    }
456
457    /// The heap type that this is a reference to.
458    #[inline]
459    pub fn heap_type(&self) -> &HeapType {
460        &self.heap_type
461    }
462
463    /// Does this reference type match the other?
464    ///
465    /// That is, is this reference type a subtype of the other?
466    ///
467    /// # Panics
468    ///
469    /// Panics if either type is associated with a different engine from the
470    /// other.
471    pub fn matches(&self, other: &RefType) -> bool {
472        if self.is_nullable() && !other.is_nullable() {
473            return false;
474        }
475        self.heap_type().matches(other.heap_type())
476    }
477
478    /// Is reference type `a` precisely equal to reference type `b`?
479    ///
480    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
481    /// are not exactly the same reference type.
482    ///
483    /// # Panics
484    ///
485    /// Panics if either type is associated with a different engine.
486    pub fn eq(a: &RefType, b: &RefType) -> bool {
487        a.matches(b) && b.matches(a)
488    }
489
490    pub(crate) fn ensure_matches(&self, engine: &Engine, other: &RefType) -> Result<()> {
491        if !self.comes_from_same_engine(engine) || !other.comes_from_same_engine(engine) {
492            bail!("type used with wrong engine");
493        }
494        if self.matches(other) {
495            Ok(())
496        } else {
497            bail!("type mismatch: expected {other}, found {self}")
498        }
499    }
500
501    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
502        self.heap_type().comes_from_same_engine(engine)
503    }
504
505    pub(crate) fn to_wasm_type(&self) -> WasmRefType {
506        WasmRefType {
507            nullable: self.is_nullable(),
508            heap_type: self.heap_type().to_wasm_type(),
509        }
510    }
511
512    pub(crate) fn from_wasm_type(engine: &Engine, ty: &WasmRefType) -> RefType {
513        RefType {
514            is_nullable: ty.nullable,
515            heap_type: HeapType::from_wasm_type(engine, &ty.heap_type),
516        }
517    }
518
519    pub(crate) fn is_vmgcref_type_and_points_to_object(&self) -> bool {
520        self.heap_type().is_vmgcref_type_and_points_to_object()
521    }
522
523    /// What is the size (in bytes) of this type's values when they are stored
524    /// inside the GC heap?
525    pub(crate) fn byte_size_in_gc_heap(&self) -> u32 {
526        match &self.heap_type {
527            HeapType::Extern | HeapType::NoExtern => 4,
528
529            HeapType::Func | HeapType::ConcreteFunc(_) | HeapType::NoFunc => {
530                todo!("funcrefs in the gc heap aren't supported yet")
531            }
532            HeapType::Any
533            | HeapType::Eq
534            | HeapType::I31
535            | HeapType::Array
536            | HeapType::ConcreteArray(_)
537            | HeapType::Struct
538            | HeapType::ConcreteStruct(_)
539            | HeapType::None => 4,
540        }
541    }
542}
543
544/// The heap types that can Wasm can have references to.
545///
546/// # Subtyping Hierarchy
547///
548/// Wasm has three different heap type hierarchies:
549///
550/// 1. Function types
551/// 2. External types
552/// 3. Internal types
553///
554/// Each hierarchy has a top type (the common supertype of which everything else
555/// in its hierarchy is a subtype of) and a bottom type (the common subtype of
556/// which everything else in its hierarchy is supertype of).
557///
558/// ## Function Types Hierarchy
559///
560/// The top of the function types hierarchy is `func`; the bottom is
561/// `nofunc`. In between are all the concrete function types.
562///
563/// ```text
564///                          func
565///                       /  /  \  \
566///      ,----------------  /    \  -------------------------.
567///     /                  /      \                           \
568///    |              ,----        -----------.                |
569///    |              |                       |                |
570///    |              |                       |                |
571/// (func)    (func (param i32))    (func (param i32 i32))    ...
572///    |              |                       |                |
573///    |              |                       |                |
574///    |              `---.        ,----------'                |
575///     \                  \      /                           /
576///      `---------------.  \    /  ,------------------------'
577///                       \  \  /  /
578///                         nofunc
579/// ```
580///
581/// Additionally, some concrete function types are sub- or supertypes of other
582/// concrete function types, if that was declared in their definition. For
583/// simplicity, this isn't depicted in the diagram above.
584///
585/// ## External
586///
587/// The top of the external types hierarchy is `extern`; the bottom is
588/// `noextern`. There are no concrete types in this hierarchy.
589///
590/// ```text
591///  extern
592///    |
593/// noextern
594/// ```
595///
596/// ## Internal
597///
598/// The top of the internal types hierarchy is `any`; the bottom is `none`. The
599/// `eq` type is the common supertype of all types that can be compared for
600/// equality. The `struct` and `array` types are the common supertypes of all
601/// concrete struct and array types respectively. The `i31` type represents
602/// unboxed 31-bit integers.
603///
604/// ```text
605///                                   any
606///                                  / | \
607///    ,----------------------------'  |  `--------------------------.
608///   /                                |                              \
609///  |                        .--------'                               |
610///  |                        |                                        |
611///  |                      struct                                   array
612///  |                     /  |   \                                 /  |   \
613/// i31             ,-----'   |    '-----.                   ,-----'   |    `-----.
614///  |             /          |           \                 /          |           \
615///  |            |           |            |               |           |            |
616///  |        (struct)    (struct i32)    ...        (array i32)    (array i64)    ...
617///  |            |           |            |               |           |            |
618///  |             \          |           /                 \          |           /
619///   \             `-----.   |    ,-----'                   `-----.   |    ,-----'
620///    \                   \  |   /                                 \  |   /
621///     \                   \ |  /                                   \ |  /
622///      \                   \| /                                     \| /
623///       \                   |/                                       |/
624///        \                  |                                        |
625///         \                 |                                       /
626///          \                '--------.                             /
627///           \                        |                            /
628///            `--------------------.  |   ,-----------------------'
629///                                  \ |  /
630///                                   none
631/// ```
632///
633/// Additionally, concrete struct and array types can be subtypes of other
634/// concrete struct and array types respectively, if that was declared in their
635/// definitions. Once again, this is omitted from the above diagram for
636/// simplicity.
637///
638/// # Subtyping and Equality
639///
640/// `HeapType` does not implement `Eq`, because heap types have a subtyping
641/// relationship, and so 99.99% of the time you actually want to check whether
642/// one type matches (i.e. is a subtype of) another type. You can use the
643/// [`HeapType::matches`] method to perform these types of checks. If, however,
644/// you are in that 0.01% scenario where you need to check precise equality
645/// between types, you can use the [`HeapType::eq`] method.
646#[derive(Debug, Clone, Hash)]
647pub enum HeapType {
648    /// The abstract `extern` heap type represents external host data.
649    ///
650    /// This is the top type for the external type hierarchy, and therefore is
651    /// the common supertype of all external reference types.
652    Extern,
653
654    /// The abstract `noextern` heap type represents the null external
655    /// reference.
656    ///
657    /// This is the bottom type for the external type hierarchy, and therefore
658    /// is the common subtype of all external reference types.
659    NoExtern,
660
661    /// The abstract `func` heap type represents a reference to any kind of
662    /// function.
663    ///
664    /// This is the top type for the function references type hierarchy, and is
665    /// therefore a supertype of every function reference.
666    Func,
667
668    /// A reference to a function of a specific, concrete type.
669    ///
670    /// These are subtypes of `func` and supertypes of `nofunc`.
671    ConcreteFunc(FuncType),
672
673    /// The abstract `nofunc` heap type represents the null function reference.
674    ///
675    /// This is the bottom type for the function references type hierarchy, and
676    /// therefore `nofunc` is a subtype of all function reference types.
677    NoFunc,
678
679    /// The abstract `any` heap type represents all internal Wasm data.
680    ///
681    /// This is the top type of the internal type hierarchy, and is therefore a
682    /// supertype of all internal types (such as `eq`, `i31`, `struct`s, and
683    /// `array`s).
684    Any,
685
686    /// The abstract `eq` heap type represenets all internal Wasm references
687    /// that can be compared for equality.
688    ///
689    /// This is a subtype of `any` and a supertype of `i31`, `array`, `struct`,
690    /// and `none` heap types.
691    Eq,
692
693    /// The `i31` heap type represents unboxed 31-bit integers.
694    ///
695    /// This is a subtype of `any` and `eq`, and a supertype of `none`.
696    I31,
697
698    /// The abstract `array` heap type represents a reference to any kind of
699    /// array.
700    ///
701    /// This is a subtype of `any` and `eq`, and a supertype of all concrete
702    /// array types, as well as a supertype of the abstract `none` heap type.
703    Array,
704
705    /// A reference to an array of a specific, concrete type.
706    ///
707    /// These are subtypes of the `array` heap type (therefore also a subtype of
708    /// `any` and `eq`) and supertypes of the `none` heap type.
709    ConcreteArray(ArrayType),
710
711    /// The abstract `struct` heap type represents a reference to any kind of
712    /// struct.
713    ///
714    /// This is a subtype of `any` and `eq`, and a supertype of all concrete
715    /// struct types, as well as a supertype of the abstract `none` heap type.
716    Struct,
717
718    /// A reference to an struct of a specific, concrete type.
719    ///
720    /// These are subtypes of the `struct` heap type (therefore also a subtype
721    /// of `any` and `eq`) and supertypes of the `none` heap type.
722    ConcreteStruct(StructType),
723
724    /// The abstract `none` heap type represents the null internal reference.
725    ///
726    /// This is the bottom type for the internal type hierarchy, and therefore
727    /// `none` is a subtype of internal types.
728    None,
729}
730
731impl Display for HeapType {
732    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
733        match self {
734            HeapType::Extern => write!(f, "extern"),
735            HeapType::NoExtern => write!(f, "noextern"),
736            HeapType::Func => write!(f, "func"),
737            HeapType::NoFunc => write!(f, "nofunc"),
738            HeapType::Any => write!(f, "any"),
739            HeapType::Eq => write!(f, "eq"),
740            HeapType::I31 => write!(f, "i31"),
741            HeapType::Array => write!(f, "array"),
742            HeapType::Struct => write!(f, "struct"),
743            HeapType::None => write!(f, "none"),
744            HeapType::ConcreteFunc(ty) => write!(f, "(concrete func {:?})", ty.type_index()),
745            HeapType::ConcreteArray(ty) => write!(f, "(concrete array {:?})", ty.type_index()),
746            HeapType::ConcreteStruct(ty) => write!(f, "(concrete struct {:?})", ty.type_index()),
747        }
748    }
749}
750
751impl From<FuncType> for HeapType {
752    #[inline]
753    fn from(f: FuncType) -> Self {
754        HeapType::ConcreteFunc(f)
755    }
756}
757
758impl From<ArrayType> for HeapType {
759    #[inline]
760    fn from(a: ArrayType) -> Self {
761        HeapType::ConcreteArray(a)
762    }
763}
764
765impl From<StructType> for HeapType {
766    #[inline]
767    fn from(s: StructType) -> Self {
768        HeapType::ConcreteStruct(s)
769    }
770}
771
772impl HeapType {
773    /// Is this the abstract `extern` heap type?
774    pub fn is_extern(&self) -> bool {
775        matches!(self, HeapType::Extern)
776    }
777
778    /// Is this the abstract `func` heap type?
779    pub fn is_func(&self) -> bool {
780        matches!(self, HeapType::Func)
781    }
782
783    /// Is this the abstract `nofunc` heap type?
784    pub fn is_no_func(&self) -> bool {
785        matches!(self, HeapType::NoFunc)
786    }
787
788    /// Is this the abstract `any` heap type?
789    pub fn is_any(&self) -> bool {
790        matches!(self, HeapType::Any)
791    }
792
793    /// Is this the abstract `i31` heap type?
794    pub fn is_i31(&self) -> bool {
795        matches!(self, HeapType::I31)
796    }
797
798    /// Is this the abstract `none` heap type?
799    pub fn is_none(&self) -> bool {
800        matches!(self, HeapType::None)
801    }
802
803    /// Is this an abstract type?
804    ///
805    /// Types that are not abstract are concrete, user-defined types.
806    pub fn is_abstract(&self) -> bool {
807        !self.is_concrete()
808    }
809
810    /// Is this a concrete, user-defined heap type?
811    ///
812    /// Types that are not concrete, user-defined types are abstract types.
813    #[inline]
814    pub fn is_concrete(&self) -> bool {
815        matches!(
816            self,
817            HeapType::ConcreteFunc(_) | HeapType::ConcreteArray(_) | HeapType::ConcreteStruct(_)
818        )
819    }
820
821    /// Is this a concrete, user-defined function type?
822    pub fn is_concrete_func(&self) -> bool {
823        matches!(self, HeapType::ConcreteFunc(_))
824    }
825
826    /// Get the underlying concrete, user-defined function type, if any.
827    ///
828    /// Returns `None` if this is not a concrete function type.
829    pub fn as_concrete_func(&self) -> Option<&FuncType> {
830        match self {
831            HeapType::ConcreteFunc(f) => Some(f),
832            _ => None,
833        }
834    }
835
836    /// Get the underlying concrete, user-defined type, panicking if this is not
837    /// a concrete function type.
838    pub fn unwrap_concrete_func(&self) -> &FuncType {
839        self.as_concrete_func().unwrap()
840    }
841
842    /// Is this a concrete, user-defined array type?
843    pub fn is_concrete_array(&self) -> bool {
844        matches!(self, HeapType::ConcreteArray(_))
845    }
846
847    /// Get the underlying concrete, user-defined array type, if any.
848    ///
849    /// Returns `None` for if this is not a concrete array type.
850    pub fn as_concrete_array(&self) -> Option<&ArrayType> {
851        match self {
852            HeapType::ConcreteArray(f) => Some(f),
853            _ => None,
854        }
855    }
856
857    /// Get the underlying concrete, user-defined type, panicking if this is not
858    /// a concrete array type.
859    pub fn unwrap_concrete_array(&self) -> &ArrayType {
860        self.as_concrete_array().unwrap()
861    }
862
863    /// Is this a concrete, user-defined struct type?
864    pub fn is_concrete_struct(&self) -> bool {
865        matches!(self, HeapType::ConcreteStruct(_))
866    }
867
868    /// Get the underlying concrete, user-defined struct type, if any.
869    ///
870    /// Returns `None` for if this is not a concrete struct type.
871    pub fn as_concrete_struct(&self) -> Option<&StructType> {
872        match self {
873            HeapType::ConcreteStruct(f) => Some(f),
874            _ => None,
875        }
876    }
877
878    /// Get the underlying concrete, user-defined type, panicking if this is not
879    /// a concrete struct type.
880    pub fn unwrap_concrete_struct(&self) -> &StructType {
881        self.as_concrete_struct().unwrap()
882    }
883
884    /// Get the top type of this heap type's type hierarchy.
885    ///
886    /// The returned heap type is a supertype of all types in this heap type's
887    /// type hierarchy.
888    #[inline]
889    pub fn top(&self) -> HeapType {
890        match self {
891            HeapType::Func | HeapType::ConcreteFunc(_) | HeapType::NoFunc => HeapType::Func,
892
893            HeapType::Extern | HeapType::NoExtern => HeapType::Extern,
894
895            HeapType::Any
896            | HeapType::Eq
897            | HeapType::I31
898            | HeapType::Array
899            | HeapType::ConcreteArray(_)
900            | HeapType::Struct
901            | HeapType::ConcreteStruct(_)
902            | HeapType::None => HeapType::Any,
903        }
904    }
905
906    /// Is this the top type within its type hierarchy?
907    #[inline]
908    pub fn is_top(&self) -> bool {
909        match self {
910            HeapType::Any | HeapType::Extern | HeapType::Func => true,
911            _ => false,
912        }
913    }
914
915    /// Get the bottom type of this heap type's type hierarchy.
916    ///
917    /// The returned heap type is a subtype of all types in this heap type's
918    /// type hierarchy.
919    #[inline]
920    pub fn bottom(&self) -> HeapType {
921        match self {
922            HeapType::Extern | HeapType::NoExtern => HeapType::NoExtern,
923
924            HeapType::Func | HeapType::ConcreteFunc(_) | HeapType::NoFunc => HeapType::NoFunc,
925
926            HeapType::Any
927            | HeapType::Eq
928            | HeapType::I31
929            | HeapType::Array
930            | HeapType::ConcreteArray(_)
931            | HeapType::Struct
932            | HeapType::ConcreteStruct(_)
933            | HeapType::None => HeapType::None,
934        }
935    }
936
937    /// Is this the bottom type within its type hierarchy?
938    #[inline]
939    pub fn is_bottom(&self) -> bool {
940        match self {
941            HeapType::None | HeapType::NoExtern | HeapType::NoFunc => true,
942            _ => false,
943        }
944    }
945
946    /// Does this heap type match the other heap type?
947    ///
948    /// That is, is this heap type a subtype of the other?
949    ///
950    /// # Panics
951    ///
952    /// Panics if either type is associated with a different engine from the
953    /// other.
954    pub fn matches(&self, other: &HeapType) -> bool {
955        match (self, other) {
956            (HeapType::Extern, HeapType::Extern) => true,
957            (HeapType::Extern, _) => false,
958
959            (HeapType::NoExtern, HeapType::NoExtern | HeapType::Extern) => true,
960            (HeapType::NoExtern, _) => false,
961
962            (HeapType::NoFunc, HeapType::NoFunc | HeapType::ConcreteFunc(_) | HeapType::Func) => {
963                true
964            }
965            (HeapType::NoFunc, _) => false,
966
967            (HeapType::ConcreteFunc(_), HeapType::Func) => true,
968            (HeapType::ConcreteFunc(a), HeapType::ConcreteFunc(b)) => {
969                assert!(a.comes_from_same_engine(b.engine()));
970                a.engine()
971                    .signatures()
972                    .is_subtype(a.type_index(), b.type_index())
973            }
974            (HeapType::ConcreteFunc(_), _) => false,
975
976            (HeapType::Func, HeapType::Func) => true,
977            (HeapType::Func, _) => false,
978
979            (
980                HeapType::None,
981                HeapType::None
982                | HeapType::ConcreteArray(_)
983                | HeapType::Array
984                | HeapType::ConcreteStruct(_)
985                | HeapType::Struct
986                | HeapType::I31
987                | HeapType::Eq
988                | HeapType::Any,
989            ) => true,
990            (HeapType::None, _) => false,
991
992            (HeapType::ConcreteArray(_), HeapType::Array | HeapType::Eq | HeapType::Any) => true,
993            (HeapType::ConcreteArray(a), HeapType::ConcreteArray(b)) => {
994                assert!(a.comes_from_same_engine(b.engine()));
995                a.engine()
996                    .signatures()
997                    .is_subtype(a.type_index(), b.type_index())
998            }
999            (HeapType::ConcreteArray(_), _) => false,
1000
1001            (HeapType::Array, HeapType::Array | HeapType::Eq | HeapType::Any) => true,
1002            (HeapType::Array, _) => false,
1003
1004            (HeapType::ConcreteStruct(_), HeapType::Struct | HeapType::Eq | HeapType::Any) => true,
1005            (HeapType::ConcreteStruct(a), HeapType::ConcreteStruct(b)) => {
1006                assert!(a.comes_from_same_engine(b.engine()));
1007                a.engine()
1008                    .signatures()
1009                    .is_subtype(a.type_index(), b.type_index())
1010            }
1011            (HeapType::ConcreteStruct(_), _) => false,
1012
1013            (HeapType::Struct, HeapType::Struct | HeapType::Eq | HeapType::Any) => true,
1014            (HeapType::Struct, _) => false,
1015
1016            (HeapType::I31, HeapType::I31 | HeapType::Eq | HeapType::Any) => true,
1017            (HeapType::I31, _) => false,
1018
1019            (HeapType::Eq, HeapType::Eq | HeapType::Any) => true,
1020            (HeapType::Eq, _) => false,
1021
1022            (HeapType::Any, HeapType::Any) => true,
1023            (HeapType::Any, _) => false,
1024        }
1025    }
1026
1027    /// Is heap type `a` precisely equal to heap type `b`?
1028    ///
1029    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
1030    /// are not exactly the same heap type.
1031    ///
1032    /// # Panics
1033    ///
1034    /// Panics if either type is associated with a different engine from the
1035    /// other.
1036    pub fn eq(a: &HeapType, b: &HeapType) -> bool {
1037        a.matches(b) && b.matches(a)
1038    }
1039
1040    pub(crate) fn ensure_matches(&self, engine: &Engine, other: &HeapType) -> Result<()> {
1041        if !self.comes_from_same_engine(engine) || !other.comes_from_same_engine(engine) {
1042            bail!("type used with wrong engine");
1043        }
1044        if self.matches(other) {
1045            Ok(())
1046        } else {
1047            bail!("type mismatch: expected {other}, found {self}");
1048        }
1049    }
1050
1051    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
1052        match self {
1053            HeapType::Extern
1054            | HeapType::NoExtern
1055            | HeapType::Func
1056            | HeapType::NoFunc
1057            | HeapType::Any
1058            | HeapType::Eq
1059            | HeapType::I31
1060            | HeapType::Array
1061            | HeapType::Struct
1062            | HeapType::None => true,
1063            HeapType::ConcreteFunc(ty) => ty.comes_from_same_engine(engine),
1064            HeapType::ConcreteArray(ty) => ty.comes_from_same_engine(engine),
1065            HeapType::ConcreteStruct(ty) => ty.comes_from_same_engine(engine),
1066        }
1067    }
1068
1069    pub(crate) fn to_wasm_type(&self) -> WasmHeapType {
1070        match self {
1071            HeapType::Extern => WasmHeapType::Extern,
1072            HeapType::NoExtern => WasmHeapType::NoExtern,
1073            HeapType::Func => WasmHeapType::Func,
1074            HeapType::NoFunc => WasmHeapType::NoFunc,
1075            HeapType::Any => WasmHeapType::Any,
1076            HeapType::Eq => WasmHeapType::Eq,
1077            HeapType::I31 => WasmHeapType::I31,
1078            HeapType::Array => WasmHeapType::Array,
1079            HeapType::Struct => WasmHeapType::Struct,
1080            HeapType::None => WasmHeapType::None,
1081            HeapType::ConcreteFunc(f) => {
1082                WasmHeapType::ConcreteFunc(EngineOrModuleTypeIndex::Engine(f.type_index()))
1083            }
1084            HeapType::ConcreteArray(a) => {
1085                WasmHeapType::ConcreteArray(EngineOrModuleTypeIndex::Engine(a.type_index()))
1086            }
1087            HeapType::ConcreteStruct(a) => {
1088                WasmHeapType::ConcreteStruct(EngineOrModuleTypeIndex::Engine(a.type_index()))
1089            }
1090        }
1091    }
1092
1093    pub(crate) fn from_wasm_type(engine: &Engine, ty: &WasmHeapType) -> HeapType {
1094        match ty {
1095            WasmHeapType::Extern => HeapType::Extern,
1096            WasmHeapType::NoExtern => HeapType::NoExtern,
1097            WasmHeapType::Func => HeapType::Func,
1098            WasmHeapType::NoFunc => HeapType::NoFunc,
1099            WasmHeapType::Any => HeapType::Any,
1100            WasmHeapType::Eq => HeapType::Eq,
1101            WasmHeapType::I31 => HeapType::I31,
1102            WasmHeapType::Array => HeapType::Array,
1103            WasmHeapType::Struct => HeapType::Struct,
1104            WasmHeapType::None => HeapType::None,
1105            WasmHeapType::ConcreteFunc(EngineOrModuleTypeIndex::Engine(idx)) => {
1106                HeapType::ConcreteFunc(FuncType::from_shared_type_index(engine, *idx))
1107            }
1108            WasmHeapType::ConcreteArray(EngineOrModuleTypeIndex::Engine(idx)) => {
1109                HeapType::ConcreteArray(ArrayType::from_shared_type_index(engine, *idx))
1110            }
1111            WasmHeapType::ConcreteStruct(EngineOrModuleTypeIndex::Engine(idx)) => {
1112                HeapType::ConcreteStruct(StructType::from_shared_type_index(engine, *idx))
1113            }
1114
1115            WasmHeapType::ConcreteFunc(EngineOrModuleTypeIndex::Module(_))
1116            | WasmHeapType::ConcreteFunc(EngineOrModuleTypeIndex::RecGroup(_))
1117            | WasmHeapType::ConcreteArray(EngineOrModuleTypeIndex::Module(_))
1118            | WasmHeapType::ConcreteArray(EngineOrModuleTypeIndex::RecGroup(_))
1119            | WasmHeapType::ConcreteStruct(EngineOrModuleTypeIndex::Module(_))
1120            | WasmHeapType::ConcreteStruct(EngineOrModuleTypeIndex::RecGroup(_)) => {
1121                panic!("HeapType::from_wasm_type on non-canonicalized-for-runtime-usage heap type")
1122            }
1123        }
1124    }
1125
1126    pub(crate) fn as_registered_type(&self) -> Option<&RegisteredType> {
1127        match self {
1128            HeapType::ConcreteFunc(f) => Some(&f.registered_type),
1129            HeapType::ConcreteArray(a) => Some(&a.registered_type),
1130            HeapType::ConcreteStruct(a) => Some(&a.registered_type),
1131
1132            HeapType::Extern
1133            | HeapType::NoExtern
1134            | HeapType::Func
1135            | HeapType::NoFunc
1136            | HeapType::Any
1137            | HeapType::Eq
1138            | HeapType::I31
1139            | HeapType::Array
1140            | HeapType::Struct
1141            | HeapType::None => None,
1142        }
1143    }
1144
1145    #[inline]
1146    pub(crate) fn is_vmgcref_type(&self) -> bool {
1147        match self.top() {
1148            Self::Any | Self::Extern => true,
1149            Self::Func => false,
1150            ty => unreachable!("not a top type: {ty:?}"),
1151        }
1152    }
1153
1154    /// Is this a `VMGcRef` type that is not i31 and is not an uninhabited
1155    /// bottom type?
1156    #[inline]
1157    pub(crate) fn is_vmgcref_type_and_points_to_object(&self) -> bool {
1158        self.is_vmgcref_type()
1159            && !matches!(
1160                self,
1161                HeapType::I31 | HeapType::NoExtern | HeapType::NoFunc | HeapType::None
1162            )
1163    }
1164}
1165
1166// External Types
1167
1168/// A list of all possible types which can be externally referenced from a
1169/// WebAssembly module.
1170///
1171/// This list can be found in [`ImportType`] or [`ExportType`], so these types
1172/// can either be imported or exported.
1173#[derive(Debug, Clone)]
1174pub enum ExternType {
1175    /// This external type is the type of a WebAssembly function.
1176    Func(FuncType),
1177    /// This external type is the type of a WebAssembly global.
1178    Global(GlobalType),
1179    /// This external type is the type of a WebAssembly table.
1180    Table(TableType),
1181    /// This external type is the type of a WebAssembly memory.
1182    Memory(MemoryType),
1183}
1184
1185macro_rules! extern_type_accessors {
1186    ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
1187        /// Attempt to return the underlying type of this external type,
1188        /// returning `None` if it is a different type.
1189        pub fn $get(&self) -> Option<&$ty> {
1190            if let ExternType::$variant(e) = self {
1191                Some(e)
1192            } else {
1193                None
1194            }
1195        }
1196
1197        /// Returns the underlying descriptor of this [`ExternType`], panicking
1198        /// if it is a different type.
1199        ///
1200        /// # Panics
1201        ///
1202        /// Panics if `self` is not of the right type.
1203        pub fn $unwrap(&self) -> &$ty {
1204            self.$get().expect(concat!("expected ", stringify!($ty)))
1205        }
1206    )*)
1207}
1208
1209impl ExternType {
1210    extern_type_accessors! {
1211        (Func(FuncType) func unwrap_func)
1212        (Global(GlobalType) global unwrap_global)
1213        (Table(TableType) table unwrap_table)
1214        (Memory(MemoryType) memory unwrap_memory)
1215    }
1216
1217    pub(crate) fn from_wasmtime(
1218        engine: &Engine,
1219        types: &ModuleTypes,
1220        ty: &EntityType,
1221    ) -> ExternType {
1222        match ty {
1223            EntityType::Function(idx) => match idx {
1224                EngineOrModuleTypeIndex::Engine(e) => {
1225                    FuncType::from_shared_type_index(engine, *e).into()
1226                }
1227                EngineOrModuleTypeIndex::Module(m) => {
1228                    let subty = &types[*m];
1229                    FuncType::from_wasm_func_type(
1230                        engine,
1231                        subty.is_final,
1232                        subty.supertype,
1233                        subty.unwrap_func().clone(),
1234                    )
1235                    .into()
1236                }
1237                EngineOrModuleTypeIndex::RecGroup(_) => unreachable!(),
1238            },
1239            EntityType::Global(ty) => GlobalType::from_wasmtime_global(engine, ty).into(),
1240            EntityType::Memory(ty) => MemoryType::from_wasmtime_memory(ty).into(),
1241            EntityType::Table(ty) => TableType::from_wasmtime_table(engine, ty).into(),
1242            EntityType::Tag(_) => unimplemented!("wasm tag support"),
1243        }
1244    }
1245}
1246
1247impl From<FuncType> for ExternType {
1248    fn from(ty: FuncType) -> ExternType {
1249        ExternType::Func(ty)
1250    }
1251}
1252
1253impl From<GlobalType> for ExternType {
1254    fn from(ty: GlobalType) -> ExternType {
1255        ExternType::Global(ty)
1256    }
1257}
1258
1259impl From<MemoryType> for ExternType {
1260    fn from(ty: MemoryType) -> ExternType {
1261        ExternType::Memory(ty)
1262    }
1263}
1264
1265impl From<TableType> for ExternType {
1266    fn from(ty: TableType) -> ExternType {
1267        ExternType::Table(ty)
1268    }
1269}
1270
1271/// The storage type of a `struct` field or `array` element.
1272///
1273/// This is either a packed 8- or -16 bit integer, or else it is some unpacked
1274/// Wasm value type.
1275#[derive(Clone, Hash)]
1276pub enum StorageType {
1277    /// `i8`, an 8-bit integer.
1278    I8,
1279    /// `i16`, a 16-bit integer.
1280    I16,
1281    /// A value type.
1282    ValType(ValType),
1283}
1284
1285impl fmt::Display for StorageType {
1286    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1287        match self {
1288            StorageType::I8 => write!(f, "i8"),
1289            StorageType::I16 => write!(f, "i16"),
1290            StorageType::ValType(ty) => fmt::Display::fmt(ty, f),
1291        }
1292    }
1293}
1294
1295impl From<ValType> for StorageType {
1296    #[inline]
1297    fn from(v: ValType) -> Self {
1298        StorageType::ValType(v)
1299    }
1300}
1301
1302impl StorageType {
1303    /// Is this an `i8`?
1304    #[inline]
1305    pub fn is_i8(&self) -> bool {
1306        matches!(self, Self::I8)
1307    }
1308
1309    /// Is this an `i16`?
1310    #[inline]
1311    pub fn is_i16(&self) -> bool {
1312        matches!(self, Self::I16)
1313    }
1314
1315    /// Is this a Wasm value type?
1316    #[inline]
1317    pub fn is_val_type(&self) -> bool {
1318        matches!(self, Self::I16)
1319    }
1320
1321    /// Get this storage type's underlying value type, if any.
1322    ///
1323    /// Returns `None` if this storage type is not a value type.
1324    #[inline]
1325    pub fn as_val_type(&self) -> Option<&ValType> {
1326        match self {
1327            Self::ValType(v) => Some(v),
1328            _ => None,
1329        }
1330    }
1331
1332    /// Get this storage type's underlying value type, panicking if it is not a
1333    /// value type.
1334    pub fn unwrap_val_type(&self) -> &ValType {
1335        self.as_val_type().unwrap()
1336    }
1337
1338    /// Unpack this (possibly packed) storage type into a full `ValType`.
1339    ///
1340    /// If this is a `StorageType::ValType`, then the inner `ValType` is
1341    /// returned as-is.
1342    ///
1343    /// If this is a packed `StorageType::I8` or `StorageType::I16, then a
1344    /// `ValType::I32` is returned.
1345    pub fn unpack(&self) -> &ValType {
1346        match self {
1347            StorageType::I8 | StorageType::I16 => &ValType::I32,
1348            StorageType::ValType(ty) => ty,
1349        }
1350    }
1351
1352    /// Does this field type match the other field type?
1353    ///
1354    /// That is, is this field type a subtype of the other field type?
1355    ///
1356    /// # Panics
1357    ///
1358    /// Panics if either type is associated with a different engine from the
1359    /// other.
1360    pub fn matches(&self, other: &Self) -> bool {
1361        match (self, other) {
1362            (StorageType::I8, StorageType::I8) => true,
1363            (StorageType::I8, _) => false,
1364            (StorageType::I16, StorageType::I16) => true,
1365            (StorageType::I16, _) => false,
1366            (StorageType::ValType(a), StorageType::ValType(b)) => a.matches(b),
1367            (StorageType::ValType(_), _) => false,
1368        }
1369    }
1370
1371    /// Is field type `a` precisely equal to field type `b`?
1372    ///
1373    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
1374    /// are not exactly the same field type.
1375    ///
1376    /// # Panics
1377    ///
1378    /// Panics if either type is associated with a different engine from the
1379    /// other.
1380    pub fn eq(a: &Self, b: &Self) -> bool {
1381        a.matches(b) && b.matches(a)
1382    }
1383
1384    /// What is the size (in bytes) of this type's values when they are stored
1385    /// inside the GC heap?
1386    pub(crate) fn byte_size_in_gc_heap(&self) -> u32 {
1387        match self {
1388            StorageType::I8 => 1,
1389            StorageType::I16 => 2,
1390            StorageType::ValType(ty) => ty.byte_size_in_gc_heap(),
1391        }
1392    }
1393
1394    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
1395        match self {
1396            StorageType::I8 | StorageType::I16 => true,
1397            StorageType::ValType(v) => v.comes_from_same_engine(engine),
1398        }
1399    }
1400
1401    pub(crate) fn from_wasm_storage_type(engine: &Engine, ty: &WasmStorageType) -> Self {
1402        match ty {
1403            WasmStorageType::I8 => Self::I8,
1404            WasmStorageType::I16 => Self::I16,
1405            WasmStorageType::Val(v) => ValType::from_wasm_type(engine, &v).into(),
1406        }
1407    }
1408
1409    pub(crate) fn to_wasm_storage_type(&self) -> WasmStorageType {
1410        match self {
1411            Self::I8 => WasmStorageType::I8,
1412            Self::I16 => WasmStorageType::I16,
1413            Self::ValType(v) => WasmStorageType::Val(v.to_wasm_type()),
1414        }
1415    }
1416}
1417
1418/// The type of a `struct` field or an `array`'s elements.
1419///
1420/// This is a pair of both the field's storage type and its mutability
1421/// (i.e. whether the field can be updated or not).
1422#[derive(Clone, Hash)]
1423pub struct FieldType {
1424    mutability: Mutability,
1425    element_type: StorageType,
1426}
1427
1428impl fmt::Display for FieldType {
1429    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1430        if self.mutability.is_var() {
1431            write!(f, "(mut {})", self.element_type)
1432        } else {
1433            fmt::Display::fmt(&self.element_type, f)
1434        }
1435    }
1436}
1437
1438impl FieldType {
1439    /// Construct a new field type from the given parts.
1440    #[inline]
1441    pub fn new(mutability: Mutability, element_type: StorageType) -> Self {
1442        Self {
1443            mutability,
1444            element_type,
1445        }
1446    }
1447
1448    /// Get whether or not this field type is mutable.
1449    #[inline]
1450    pub fn mutability(&self) -> Mutability {
1451        self.mutability
1452    }
1453
1454    /// Get this field type's storage type.
1455    #[inline]
1456    pub fn element_type(&self) -> &StorageType {
1457        &self.element_type
1458    }
1459
1460    /// Does this field type match the other field type?
1461    ///
1462    /// That is, is this field type a subtype of the other field type?
1463    ///
1464    /// # Panics
1465    ///
1466    /// Panics if either type is associated with a different engine from the
1467    /// other.
1468    pub fn matches(&self, other: &Self) -> bool {
1469        (other.mutability == Mutability::Var || self.mutability == Mutability::Const)
1470            && self.element_type.matches(&other.element_type)
1471    }
1472
1473    /// Is field type `a` precisely equal to field type `b`?
1474    ///
1475    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
1476    /// are not exactly the same field type.
1477    ///
1478    /// # Panics
1479    ///
1480    /// Panics if either type is associated with a different engine from the
1481    /// other.
1482    pub fn eq(a: &Self, b: &Self) -> bool {
1483        a.matches(b) && b.matches(a)
1484    }
1485
1486    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
1487        self.element_type.comes_from_same_engine(engine)
1488    }
1489
1490    pub(crate) fn from_wasm_field_type(engine: &Engine, ty: &WasmFieldType) -> Self {
1491        Self {
1492            mutability: if ty.mutable {
1493                Mutability::Var
1494            } else {
1495                Mutability::Const
1496            },
1497            element_type: StorageType::from_wasm_storage_type(engine, &ty.element_type),
1498        }
1499    }
1500
1501    pub(crate) fn to_wasm_field_type(&self) -> WasmFieldType {
1502        WasmFieldType {
1503            element_type: self.element_type.to_wasm_storage_type(),
1504            mutable: matches!(self.mutability, Mutability::Var),
1505        }
1506    }
1507}
1508
1509/// The type of a WebAssembly struct.
1510///
1511/// WebAssembly structs are a static, fixed-length, ordered sequence of
1512/// fields. Fields are named by index, not an identifier. Each field is mutable
1513/// or constant and stores unpacked [`Val`][crate::Val]s or packed 8-/16-bit
1514/// integers.
1515///
1516/// # Subtyping and Equality
1517///
1518/// `StructType` does not implement `Eq`, because reference types have a
1519/// subtyping relationship, and so 99.99% of the time you actually want to check
1520/// whether one type matches (i.e. is a subtype of) another type. You can use
1521/// the [`StructType::matches`] method to perform these types of checks. If,
1522/// however, you are in that 0.01% scenario where you need to check precise
1523/// equality between types, you can use the [`StructType::eq`] method.
1524//
1525// TODO: Once we have struct values, update above docs with a reference to the
1526// future `Struct::matches_ty` method
1527#[derive(Debug, Clone, Hash)]
1528pub struct StructType {
1529    registered_type: RegisteredType,
1530}
1531
1532impl fmt::Display for StructType {
1533    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1534        write!(f, "(struct")?;
1535        for field in self.fields() {
1536            write!(f, " (field {field})")?;
1537        }
1538        write!(f, ")")?;
1539        Ok(())
1540    }
1541}
1542
1543impl StructType {
1544    /// Construct a new `StructType` with the given field types.
1545    ///
1546    /// This `StructType` will be final and without a supertype.
1547    ///
1548    /// The result will be associated with the given engine, and attempts to use
1549    /// it with other engines will panic (for example, checking whether it is a
1550    /// subtype of another struct type that is associated with a different
1551    /// engine).
1552    ///
1553    /// Returns an error if the number of fields exceeds the implementation
1554    /// limit.
1555    ///
1556    /// # Panics
1557    ///
1558    /// Panics if any given field type is not associated with the given engine.
1559    pub fn new(engine: &Engine, fields: impl IntoIterator<Item = FieldType>) -> Result<Self> {
1560        Self::with_finality_and_supertype(engine, Finality::Final, None, fields)
1561    }
1562
1563    /// Construct a new `StructType` with the given finality, supertype, and
1564    /// fields.
1565    ///
1566    /// The result will be associated with the given engine, and attempts to use
1567    /// it with other engines will panic (for example, checking whether it is a
1568    /// subtype of another struct type that is associated with a different
1569    /// engine).
1570    ///
1571    /// Returns an error if the number of fields exceeds the implementation
1572    /// limit, if the supertype is final, or if this type does not match the
1573    /// supertype.
1574    ///
1575    /// # Panics
1576    ///
1577    /// Panics if any given field type is not associated with the given engine.
1578    pub fn with_finality_and_supertype(
1579        engine: &Engine,
1580        finality: Finality,
1581        supertype: Option<&Self>,
1582        fields: impl IntoIterator<Item = FieldType>,
1583    ) -> Result<Self> {
1584        let fields = fields.into_iter();
1585
1586        let mut wasmtime_fields = Vec::with_capacity({
1587            let size_hint = fields.size_hint();
1588            let cap = size_hint.1.unwrap_or(size_hint.0);
1589            // Only reserve space if we have a supertype, as that is the only time
1590            // that this vec is used.
1591            supertype.is_some() as usize * cap
1592        });
1593
1594        // Same as in `FuncType::new`: we must prevent any `RegisteredType`s
1595        // from being reclaimed while constructing this struct type.
1596        let mut registrations = smallvec::SmallVec::<[_; 4]>::new();
1597
1598        let fields = fields
1599            .map(|ty: FieldType| {
1600                assert!(ty.comes_from_same_engine(engine));
1601
1602                if supertype.is_some() {
1603                    wasmtime_fields.push(ty.clone());
1604                }
1605
1606                if let Some(r) = ty.element_type.as_val_type().and_then(|v| v.as_ref()) {
1607                    if let Some(r) = r.heap_type().as_registered_type() {
1608                        registrations.push(r.clone());
1609                    }
1610                }
1611
1612                ty.to_wasm_field_type()
1613            })
1614            .collect();
1615
1616        if let Some(supertype) = supertype {
1617            ensure!(
1618                supertype.finality().is_non_final(),
1619                "cannot create a subtype of a final supertype"
1620            );
1621            ensure!(
1622                Self::fields_match(wasmtime_fields.into_iter(), supertype.fields()),
1623                "struct fields must match their supertype's fields"
1624            );
1625        }
1626
1627        Self::from_wasm_struct_type(
1628            engine,
1629            finality.is_final(),
1630            supertype.map(|ty| ty.type_index().into()),
1631            WasmStructType { fields },
1632        )
1633    }
1634
1635    /// Get the engine that this struct type is associated with.
1636    pub fn engine(&self) -> &Engine {
1637        self.registered_type.engine()
1638    }
1639
1640    /// Get the finality of this struct type.
1641    pub fn finality(&self) -> Finality {
1642        match self.registered_type.is_final {
1643            true => Finality::Final,
1644            false => Finality::NonFinal,
1645        }
1646    }
1647
1648    /// Get the supertype of this struct type, if any.
1649    pub fn supertype(&self) -> Option<Self> {
1650        self.registered_type
1651            .supertype
1652            .map(|ty| Self::from_shared_type_index(self.engine(), ty.unwrap_engine_type_index()))
1653    }
1654
1655    /// Get the `i`th field type.
1656    ///
1657    /// Returns `None` if `i` is out of bounds.
1658    pub fn field(&self, i: usize) -> Option<FieldType> {
1659        let engine = self.engine();
1660        self.as_wasm_struct_type()
1661            .fields
1662            .get(i)
1663            .map(|ty| FieldType::from_wasm_field_type(engine, ty))
1664    }
1665
1666    /// Returns the list of field types for this function.
1667    #[inline]
1668    pub fn fields(&self) -> impl ExactSizeIterator<Item = FieldType> + '_ {
1669        let engine = self.engine();
1670        self.as_wasm_struct_type()
1671            .fields
1672            .iter()
1673            .map(|ty| FieldType::from_wasm_field_type(engine, ty))
1674    }
1675
1676    /// Does this struct type match the other struct type?
1677    ///
1678    /// That is, is this function type a subtype of the other struct type?
1679    ///
1680    /// # Panics
1681    ///
1682    /// Panics if either type is associated with a different engine from the
1683    /// other.
1684    pub fn matches(&self, other: &StructType) -> bool {
1685        assert!(self.comes_from_same_engine(other.engine()));
1686
1687        // Avoid matching on structure for subtyping checks when we have
1688        // precisely the same type.
1689        if self.type_index() == other.type_index() {
1690            return true;
1691        }
1692
1693        Self::fields_match(self.fields(), other.fields())
1694    }
1695
1696    fn fields_match(
1697        a: impl ExactSizeIterator<Item = FieldType>,
1698        b: impl ExactSizeIterator<Item = FieldType>,
1699    ) -> bool {
1700        a.len() >= b.len() && a.zip(b).all(|(a, b)| a.matches(&b))
1701    }
1702
1703    /// Is struct type `a` precisely equal to struct type `b`?
1704    ///
1705    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
1706    /// are not exactly the same struct type.
1707    ///
1708    /// # Panics
1709    ///
1710    /// Panics if either type is associated with a different engine from the
1711    /// other.
1712    pub fn eq(a: &StructType, b: &StructType) -> bool {
1713        assert!(a.comes_from_same_engine(b.engine()));
1714        a.type_index() == b.type_index()
1715    }
1716
1717    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
1718        Engine::same(self.registered_type().engine(), engine)
1719    }
1720
1721    pub(crate) fn type_index(&self) -> VMSharedTypeIndex {
1722        self.registered_type().index()
1723    }
1724
1725    pub(crate) fn as_wasm_struct_type(&self) -> &WasmStructType {
1726        self.registered_type().unwrap_struct()
1727    }
1728
1729    pub(crate) fn registered_type(&self) -> &RegisteredType {
1730        &self.registered_type
1731    }
1732
1733    /// Construct a `StructType` from a `WasmStructType`.
1734    ///
1735    /// This method should only be used when something has already registered --
1736    /// and is *keeping registered* -- any other concrete Wasm types referenced
1737    /// by the given `WasmStructType`.
1738    ///
1739    /// For example, this method may be called to convert an struct type from
1740    /// within a Wasm module's `ModuleTypes` since the Wasm module itself is
1741    /// holding a strong reference to all of its types, including any `(ref null
1742    /// <index>)` types used as the element type for this struct type.
1743    pub(crate) fn from_wasm_struct_type(
1744        engine: &Engine,
1745        is_final: bool,
1746        supertype: Option<EngineOrModuleTypeIndex>,
1747        ty: WasmStructType,
1748    ) -> Result<StructType> {
1749        const MAX_FIELDS: usize = 10_000;
1750        let fields_len = ty.fields.len();
1751        ensure!(
1752            fields_len <= MAX_FIELDS,
1753            "attempted to define a struct type with {fields_len} fields, but \
1754             that is more than the maximum supported number of fields \
1755             ({MAX_FIELDS})",
1756        );
1757
1758        let ty = RegisteredType::new(
1759            engine,
1760            WasmSubType {
1761                is_final,
1762                supertype,
1763                composite_type: WasmCompositeType::Struct(ty),
1764            },
1765        );
1766        Ok(Self {
1767            registered_type: ty,
1768        })
1769    }
1770
1771    pub(crate) fn from_shared_type_index(engine: &Engine, index: VMSharedTypeIndex) -> StructType {
1772        let ty = RegisteredType::root(engine, index).expect(
1773            "VMSharedTypeIndex is not registered in the Engine! Wrong \
1774             engine? Didn't root the index somewhere?",
1775        );
1776        Self::from_registered_type(ty)
1777    }
1778
1779    pub(crate) fn from_registered_type(registered_type: RegisteredType) -> Self {
1780        debug_assert!(registered_type.is_struct());
1781        Self { registered_type }
1782    }
1783}
1784
1785/// The type of a WebAssembly array.
1786///
1787/// WebAssembly arrays are dynamically-sized, but not resizable. They contain
1788/// either unpacked [`Val`][crate::Val]s or packed 8-/16-bit integers.
1789///
1790/// # Subtyping and Equality
1791///
1792/// `ArrayType` does not implement `Eq`, because reference types have a
1793/// subtyping relationship, and so 99.99% of the time you actually want to check
1794/// whether one type matches (i.e. is a subtype of) another type. You can use
1795/// the [`ArrayType::matches`] method to perform these types of checks. If,
1796/// however, you are in that 0.01% scenario where you need to check precise
1797/// equality between types, you can use the [`ArrayType::eq`] method.
1798//
1799// TODO: Once we have array values, update above docs with a reference to the
1800// future `Array::matches_ty` method
1801#[derive(Debug, Clone, Hash)]
1802pub struct ArrayType {
1803    registered_type: RegisteredType,
1804}
1805
1806impl fmt::Display for ArrayType {
1807    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1808        let field_ty = self.field_type();
1809        write!(f, "(array (field {field_ty}))")?;
1810        Ok(())
1811    }
1812}
1813
1814impl ArrayType {
1815    /// Construct a new `ArrayType` with the given field type's mutability and
1816    /// storage type.
1817    ///
1818    /// The new `ArrayType` will be final and without a supertype.
1819    ///
1820    /// The result will be associated with the given engine, and attempts to use
1821    /// it with other engines will panic (for example, checking whether it is a
1822    /// subtype of another array type that is associated with a different
1823    /// engine).
1824    ///
1825    /// # Panics
1826    ///
1827    /// Panics if the given field type is not associated with the given engine.
1828    pub fn new(engine: &Engine, field_type: FieldType) -> Self {
1829        Self::with_finality_and_supertype(engine, Finality::Final, None, field_type)
1830            .expect("cannot fail without a supertype")
1831    }
1832
1833    /// Construct a new `StructType` with the given finality, supertype, and
1834    /// fields.
1835    ///
1836    /// The result will be associated with the given engine, and attempts to use
1837    /// it with other engines will panic (for example, checking whether it is a
1838    /// subtype of another struct type that is associated with a different
1839    /// engine).
1840    ///
1841    /// Returns an error if the supertype is final, or if this type does not
1842    /// match the supertype.
1843    ///
1844    /// # Panics
1845    ///
1846    /// Panics if the given field type is not associated with the given engine.
1847    pub fn with_finality_and_supertype(
1848        engine: &Engine,
1849        finality: Finality,
1850        supertype: Option<&Self>,
1851        field_type: FieldType,
1852    ) -> Result<Self> {
1853        if let Some(supertype) = supertype {
1854            assert!(supertype.comes_from_same_engine(engine));
1855            ensure!(
1856                supertype.finality().is_non_final(),
1857                "cannot create a subtype of a final supertype"
1858            );
1859            ensure!(
1860                field_type.matches(&supertype.field_type()),
1861                "array field type must match its supertype's field type"
1862            );
1863        }
1864
1865        // Same as in `FuncType::new`: we must prevent any `RegisteredType` in
1866        // `field_type` from being reclaimed while constructing this array type.
1867        let _registration = field_type
1868            .element_type
1869            .as_val_type()
1870            .and_then(|v| v.as_ref())
1871            .and_then(|r| r.heap_type().as_registered_type());
1872
1873        assert!(field_type.comes_from_same_engine(engine));
1874        let wasm_ty = WasmArrayType(field_type.to_wasm_field_type());
1875
1876        Ok(Self::from_wasm_array_type(
1877            engine,
1878            finality.is_final(),
1879            supertype.map(|ty| ty.type_index().into()),
1880            wasm_ty,
1881        ))
1882    }
1883
1884    /// Get the engine that this array type is associated with.
1885    pub fn engine(&self) -> &Engine {
1886        self.registered_type.engine()
1887    }
1888
1889    /// Get the finality of this array type.
1890    pub fn finality(&self) -> Finality {
1891        match self.registered_type.is_final {
1892            true => Finality::Final,
1893            false => Finality::NonFinal,
1894        }
1895    }
1896
1897    /// Get the supertype of this array type, if any.
1898    pub fn supertype(&self) -> Option<Self> {
1899        self.registered_type
1900            .supertype
1901            .map(|ty| Self::from_shared_type_index(self.engine(), ty.unwrap_engine_type_index()))
1902    }
1903
1904    /// Get this array's underlying field type.
1905    ///
1906    /// The field type contains information about both this array type's
1907    /// mutability and the storage type used for its elements.
1908    pub fn field_type(&self) -> FieldType {
1909        FieldType::from_wasm_field_type(self.engine(), &self.as_wasm_array_type().0)
1910    }
1911
1912    /// Get this array type's mutability and whether its instances' elements can
1913    /// be updated or not.
1914    ///
1915    /// This is a convenience method providing a short-hand for
1916    /// `my_array_type.field_type().mutability()`.
1917    pub fn mutability(&self) -> Mutability {
1918        if self.as_wasm_array_type().0.mutable {
1919            Mutability::Var
1920        } else {
1921            Mutability::Const
1922        }
1923    }
1924
1925    /// Get the storage type used for this array type's elements.
1926    ///
1927    /// This is a convenience method providing a short-hand for
1928    /// `my_array_type.field_type().element_type()`.
1929    pub fn element_type(&self) -> StorageType {
1930        StorageType::from_wasm_storage_type(
1931            self.engine(),
1932            &self.registered_type.unwrap_array().0.element_type,
1933        )
1934    }
1935
1936    /// Does this array type match the other array type?
1937    ///
1938    /// That is, is this function type a subtype of the other array type?
1939    ///
1940    /// # Panics
1941    ///
1942    /// Panics if either type is associated with a different engine from the
1943    /// other.
1944    pub fn matches(&self, other: &ArrayType) -> bool {
1945        assert!(self.comes_from_same_engine(other.engine()));
1946
1947        // Avoid matching on structure for subtyping checks when we have
1948        // precisely the same type.
1949        if self.type_index() == other.type_index() {
1950            return true;
1951        }
1952
1953        self.field_type().matches(&other.field_type())
1954    }
1955
1956    /// Is array type `a` precisely equal to array type `b`?
1957    ///
1958    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
1959    /// are not exactly the same array type.
1960    ///
1961    /// # Panics
1962    ///
1963    /// Panics if either type is associated with a different engine from the
1964    /// other.
1965    pub fn eq(a: &ArrayType, b: &ArrayType) -> bool {
1966        assert!(a.comes_from_same_engine(b.engine()));
1967        a.type_index() == b.type_index()
1968    }
1969
1970    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
1971        Engine::same(self.registered_type.engine(), engine)
1972    }
1973
1974    pub(crate) fn registered_type(&self) -> &RegisteredType {
1975        &self.registered_type
1976    }
1977
1978    pub(crate) fn type_index(&self) -> VMSharedTypeIndex {
1979        self.registered_type.index()
1980    }
1981
1982    pub(crate) fn as_wasm_array_type(&self) -> &WasmArrayType {
1983        self.registered_type.unwrap_array()
1984    }
1985
1986    /// Construct a `ArrayType` from a `WasmArrayType`.
1987    ///
1988    /// This method should only be used when something has already registered --
1989    /// and is *keeping registered* -- any other concrete Wasm types referenced
1990    /// by the given `WasmArrayType`.
1991    ///
1992    /// For example, this method may be called to convert an array type from
1993    /// within a Wasm module's `ModuleTypes` since the Wasm module itself is
1994    /// holding a strong reference to all of its types, including any `(ref null
1995    /// <index>)` types used as the element type for this array type.
1996    pub(crate) fn from_wasm_array_type(
1997        engine: &Engine,
1998        is_final: bool,
1999        supertype: Option<EngineOrModuleTypeIndex>,
2000        ty: WasmArrayType,
2001    ) -> ArrayType {
2002        let ty = RegisteredType::new(
2003            engine,
2004            WasmSubType {
2005                is_final,
2006                supertype,
2007                composite_type: WasmCompositeType::Array(ty),
2008            },
2009        );
2010        Self {
2011            registered_type: ty,
2012        }
2013    }
2014
2015    pub(crate) fn from_shared_type_index(engine: &Engine, index: VMSharedTypeIndex) -> ArrayType {
2016        let ty = RegisteredType::root(engine, index).expect(
2017            "VMSharedTypeIndex is not registered in the Engine! Wrong \
2018             engine? Didn't root the index somewhere?",
2019        );
2020        Self::from_registered_type(ty)
2021    }
2022
2023    pub(crate) fn from_registered_type(registered_type: RegisteredType) -> Self {
2024        debug_assert!(registered_type.is_array());
2025        Self { registered_type }
2026    }
2027}
2028
2029/// The type of a WebAssembly function.
2030///
2031/// WebAssembly functions can have 0 or more parameters and results.
2032///
2033/// # Subtyping and Equality
2034///
2035/// `FuncType` does not implement `Eq`, because reference types have a subtyping
2036/// relationship, and so 99.99% of the time you actually want to check whether
2037/// one type matches (i.e. is a subtype of) another type. You can use the
2038/// [`FuncType::matches`] and [`Func::matches_ty`][crate::Func::matches_ty]
2039/// methods to perform these types of checks. If, however, you are in that 0.01%
2040/// scenario where you need to check precise equality between types, you can use
2041/// the [`FuncType::eq`] method.
2042#[derive(Debug, Clone, Hash)]
2043pub struct FuncType {
2044    registered_type: RegisteredType,
2045}
2046
2047impl Display for FuncType {
2048    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2049        write!(f, "(type (func")?;
2050        if self.params().len() > 0 {
2051            write!(f, " (param")?;
2052            for p in self.params() {
2053                write!(f, " {p}")?;
2054            }
2055            write!(f, ")")?;
2056        }
2057        if self.results().len() > 0 {
2058            write!(f, " (result")?;
2059            for r in self.results() {
2060                write!(f, " {r}")?;
2061            }
2062            write!(f, ")")?;
2063        }
2064        write!(f, "))")
2065    }
2066}
2067
2068impl FuncType {
2069    /// Creates a new function type from the given parameters and results.
2070    ///
2071    /// The function type returned will represent a function which takes
2072    /// `params` as arguments and returns `results` when it is finished.
2073    ///
2074    /// The resulting function type will be final and without a supertype.
2075    ///
2076    /// # Panics
2077    ///
2078    /// Panics if any parameter or value type is not associated with the given
2079    /// engine.
2080    pub fn new(
2081        engine: &Engine,
2082        params: impl IntoIterator<Item = ValType>,
2083        results: impl IntoIterator<Item = ValType>,
2084    ) -> FuncType {
2085        Self::with_finality_and_supertype(engine, Finality::Final, None, params, results)
2086            .expect("cannot fail without a supertype")
2087    }
2088
2089    /// Create a new function type with the given finality, supertype, parameter
2090    /// types, and result types.
2091    ///
2092    /// Returns an error if the supertype is final, or if this function type
2093    /// does not match the supertype.
2094    ///
2095    /// # Panics
2096    ///
2097    /// Panics if any parameter or value type is not associated with the given
2098    /// engine.
2099    pub fn with_finality_and_supertype(
2100        engine: &Engine,
2101        finality: Finality,
2102        supertype: Option<&Self>,
2103        params: impl IntoIterator<Item = ValType>,
2104        results: impl IntoIterator<Item = ValType>,
2105    ) -> Result<Self> {
2106        let params = params.into_iter();
2107        let results = results.into_iter();
2108
2109        let mut wasmtime_params = Vec::with_capacity({
2110            let size_hint = params.size_hint();
2111            let cap = size_hint.1.unwrap_or(size_hint.0);
2112            // Only reserve space if we have a supertype, as that is the only time
2113            // that this vec is used.
2114            supertype.is_some() as usize * cap
2115        });
2116
2117        let mut wasmtime_results = Vec::with_capacity({
2118            let size_hint = results.size_hint();
2119            let cap = size_hint.1.unwrap_or(size_hint.0);
2120            // Same as above.
2121            supertype.is_some() as usize * cap
2122        });
2123
2124        // Keep any of our parameters' and results' `RegisteredType`s alive
2125        // across `Self::from_wasm_func_type`. If one of our given `ValType`s is
2126        // the only thing keeping a type in the registry, we don't want to
2127        // unregister it when we convert the `ValType` into a `WasmValType` just
2128        // before we register our new `WasmFuncType` that will reference it.
2129        let mut registrations = smallvec::SmallVec::<[_; 4]>::new();
2130
2131        let mut to_wasm_type = |ty: ValType, vec: &mut Vec<_>| {
2132            assert!(ty.comes_from_same_engine(engine));
2133
2134            if supertype.is_some() {
2135                vec.push(ty.clone());
2136            }
2137
2138            if let Some(r) = ty.as_ref() {
2139                if let Some(r) = r.heap_type().as_registered_type() {
2140                    registrations.push(r.clone());
2141                }
2142            }
2143
2144            ty.to_wasm_type()
2145        };
2146
2147        let wasm_func_ty = WasmFuncType::new(
2148            params
2149                .map(|p| to_wasm_type(p, &mut wasmtime_params))
2150                .collect(),
2151            results
2152                .map(|r| to_wasm_type(r, &mut wasmtime_results))
2153                .collect(),
2154        );
2155
2156        if let Some(supertype) = supertype {
2157            assert!(supertype.comes_from_same_engine(engine));
2158            ensure!(
2159                supertype.finality().is_non_final(),
2160                "cannot create a subtype of a final supertype"
2161            );
2162            ensure!(
2163                Self::matches_impl(
2164                    wasmtime_params.iter().cloned(),
2165                    supertype.params(),
2166                    wasmtime_results.iter().cloned(),
2167                    supertype.results()
2168                ),
2169                "function type must match its supertype: found (func{params}{results}), expected \
2170                 {supertype}",
2171                params = if wasmtime_params.is_empty() {
2172                    String::new()
2173                } else {
2174                    let mut s = format!(" (params");
2175                    for p in &wasmtime_params {
2176                        write!(&mut s, " {p}").unwrap();
2177                    }
2178                    s.push(')');
2179                    s
2180                },
2181                results = if wasmtime_results.is_empty() {
2182                    String::new()
2183                } else {
2184                    let mut s = format!(" (results");
2185                    for r in &wasmtime_results {
2186                        write!(&mut s, " {r}").unwrap();
2187                    }
2188                    s.push(')');
2189                    s
2190                },
2191            );
2192        }
2193
2194        Ok(Self::from_wasm_func_type(
2195            engine,
2196            finality.is_final(),
2197            supertype.map(|ty| ty.type_index().into()),
2198            wasm_func_ty,
2199        ))
2200    }
2201
2202    /// Get the engine that this function type is associated with.
2203    pub fn engine(&self) -> &Engine {
2204        self.registered_type.engine()
2205    }
2206
2207    /// Get the finality of this function type.
2208    pub fn finality(&self) -> Finality {
2209        match self.registered_type.is_final {
2210            true => Finality::Final,
2211            false => Finality::NonFinal,
2212        }
2213    }
2214
2215    /// Get the supertype of this function type, if any.
2216    pub fn supertype(&self) -> Option<Self> {
2217        self.registered_type
2218            .supertype
2219            .map(|ty| Self::from_shared_type_index(self.engine(), ty.unwrap_engine_type_index()))
2220    }
2221
2222    /// Get the `i`th parameter type.
2223    ///
2224    /// Returns `None` if `i` is out of bounds.
2225    pub fn param(&self, i: usize) -> Option<ValType> {
2226        let engine = self.engine();
2227        self.registered_type
2228            .unwrap_func()
2229            .params()
2230            .get(i)
2231            .map(|ty| ValType::from_wasm_type(engine, ty))
2232    }
2233
2234    /// Returns the list of parameter types for this function.
2235    #[inline]
2236    pub fn params(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
2237        let engine = self.engine();
2238        self.registered_type
2239            .unwrap_func()
2240            .params()
2241            .iter()
2242            .map(|ty| ValType::from_wasm_type(engine, ty))
2243    }
2244
2245    /// Get the `i`th result type.
2246    ///
2247    /// Returns `None` if `i` is out of bounds.
2248    pub fn result(&self, i: usize) -> Option<ValType> {
2249        let engine = self.engine();
2250        self.registered_type
2251            .unwrap_func()
2252            .returns()
2253            .get(i)
2254            .map(|ty| ValType::from_wasm_type(engine, ty))
2255    }
2256
2257    /// Returns the list of result types for this function.
2258    #[inline]
2259    pub fn results(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
2260        let engine = self.engine();
2261        self.registered_type
2262            .unwrap_func()
2263            .returns()
2264            .iter()
2265            .map(|ty| ValType::from_wasm_type(engine, ty))
2266    }
2267
2268    /// Does this function type match the other function type?
2269    ///
2270    /// That is, is this function type a subtype of the other function type?
2271    ///
2272    /// # Panics
2273    ///
2274    /// Panics if either type is associated with a different engine from the
2275    /// other.
2276    pub fn matches(&self, other: &FuncType) -> bool {
2277        assert!(self.comes_from_same_engine(other.engine()));
2278
2279        // Avoid matching on structure for subtyping checks when we have
2280        // precisely the same type.
2281        if self.type_index() == other.type_index() {
2282            return true;
2283        }
2284
2285        Self::matches_impl(
2286            self.params(),
2287            other.params(),
2288            self.results(),
2289            other.results(),
2290        )
2291    }
2292
2293    fn matches_impl(
2294        a_params: impl ExactSizeIterator<Item = ValType>,
2295        b_params: impl ExactSizeIterator<Item = ValType>,
2296        a_results: impl ExactSizeIterator<Item = ValType>,
2297        b_results: impl ExactSizeIterator<Item = ValType>,
2298    ) -> bool {
2299        a_params.len() == b_params.len()
2300            && a_results.len() == b_results.len()
2301            // Params are contravariant and results are covariant. For more
2302            // details and a refresher on variance, read
2303            // https://github.com/bytecodealliance/wasm-tools/blob/f1d89a4/crates/wasmparser/src/readers/core/types/matches.rs#L137-L174
2304            && a_params
2305                .zip(b_params)
2306                .all(|(a, b)| b.matches(&a))
2307            && a_results
2308                .zip(b_results)
2309                .all(|(a, b)| a.matches(&b))
2310    }
2311
2312    /// Is function type `a` precisely equal to function type `b`?
2313    ///
2314    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
2315    /// are not exactly the same function type.
2316    ///
2317    /// # Panics
2318    ///
2319    /// Panics if either type is associated with a different engine from the
2320    /// other.
2321    pub fn eq(a: &FuncType, b: &FuncType) -> bool {
2322        assert!(a.comes_from_same_engine(b.engine()));
2323        a.type_index() == b.type_index()
2324    }
2325
2326    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
2327        Engine::same(self.registered_type.engine(), engine)
2328    }
2329
2330    pub(crate) fn type_index(&self) -> VMSharedTypeIndex {
2331        self.registered_type.index()
2332    }
2333
2334    pub(crate) fn as_wasm_func_type(&self) -> &WasmFuncType {
2335        self.registered_type.unwrap_func()
2336    }
2337
2338    pub(crate) fn into_registered_type(self) -> RegisteredType {
2339        self.registered_type
2340    }
2341
2342    /// Construct a `FuncType` from a `WasmFuncType`.
2343    ///
2344    /// This method should only be used when something has already registered --
2345    /// and is *keeping registered* -- any other concrete Wasm types referenced
2346    /// by the given `WasmFuncType`.
2347    ///
2348    /// For example, this method may be called to convert a function type from
2349    /// within a Wasm module's `ModuleTypes` since the Wasm module itself is
2350    /// holding a strong reference to all of its types, including any `(ref null
2351    /// <index>)` types used in the function's parameters and results.
2352    pub(crate) fn from_wasm_func_type(
2353        engine: &Engine,
2354        is_final: bool,
2355        supertype: Option<EngineOrModuleTypeIndex>,
2356        ty: WasmFuncType,
2357    ) -> FuncType {
2358        let ty = RegisteredType::new(
2359            engine,
2360            WasmSubType {
2361                is_final,
2362                supertype,
2363                composite_type: WasmCompositeType::Func(ty),
2364            },
2365        );
2366        Self {
2367            registered_type: ty,
2368        }
2369    }
2370
2371    pub(crate) fn from_shared_type_index(engine: &Engine, index: VMSharedTypeIndex) -> FuncType {
2372        let ty = RegisteredType::root(engine, index).expect(
2373            "VMSharedTypeIndex is not registered in the Engine! Wrong \
2374             engine? Didn't root the index somewhere?",
2375        );
2376        Self::from_registered_type(ty)
2377    }
2378
2379    pub(crate) fn from_registered_type(registered_type: RegisteredType) -> Self {
2380        debug_assert!(registered_type.is_func());
2381        Self { registered_type }
2382    }
2383}
2384
2385// Global Types
2386
2387/// A WebAssembly global descriptor.
2388///
2389/// This type describes an instance of a global in a WebAssembly module. Globals
2390/// are local to an [`Instance`](crate::Instance) and are either immutable or
2391/// mutable.
2392#[derive(Debug, Clone, Hash)]
2393pub struct GlobalType {
2394    content: ValType,
2395    mutability: Mutability,
2396}
2397
2398impl GlobalType {
2399    /// Creates a new global descriptor of the specified `content` type and
2400    /// whether or not it's mutable.
2401    pub fn new(content: ValType, mutability: Mutability) -> GlobalType {
2402        GlobalType {
2403            content,
2404            mutability,
2405        }
2406    }
2407
2408    /// Returns the value type of this global descriptor.
2409    pub fn content(&self) -> &ValType {
2410        &self.content
2411    }
2412
2413    /// Returns whether or not this global is mutable.
2414    pub fn mutability(&self) -> Mutability {
2415        self.mutability
2416    }
2417
2418    pub(crate) fn to_wasm_type(&self) -> Global {
2419        let wasm_ty = self.content().to_wasm_type();
2420        let mutability = matches!(self.mutability(), Mutability::Var);
2421        Global {
2422            wasm_ty,
2423            mutability,
2424        }
2425    }
2426
2427    /// Returns `None` if the wasmtime global has a type that we can't
2428    /// represent, but that should only very rarely happen and indicate a bug.
2429    pub(crate) fn from_wasmtime_global(engine: &Engine, global: &Global) -> GlobalType {
2430        let ty = ValType::from_wasm_type(engine, &global.wasm_ty);
2431        let mutability = if global.mutability {
2432            Mutability::Var
2433        } else {
2434            Mutability::Const
2435        };
2436        GlobalType::new(ty, mutability)
2437    }
2438}
2439
2440// Table Types
2441
2442/// A descriptor for a table in a WebAssembly module.
2443///
2444/// Tables are contiguous chunks of a specific element, typically a `funcref` or
2445/// an `externref`. The most common use for tables is a function table through
2446/// which `call_indirect` can invoke other functions.
2447#[derive(Debug, Clone, Hash)]
2448pub struct TableType {
2449    // Keep a `wasmtime::RefType` so that `TableType::element` doesn't need to
2450    // take an `&Engine`.
2451    element: RefType,
2452    ty: Table,
2453}
2454
2455impl TableType {
2456    /// Creates a new table descriptor which will contain the specified
2457    /// `element` and have the `limits` applied to its length.
2458    pub fn new(element: RefType, min: u32, max: Option<u32>) -> TableType {
2459        let wasm_ty = element.to_wasm_type();
2460
2461        debug_assert!(
2462            wasm_ty.is_canonicalized_for_runtime_usage(),
2463            "should be canonicalized for runtime usage: {wasm_ty:?}"
2464        );
2465
2466        TableType {
2467            element,
2468            ty: Table {
2469                wasm_ty,
2470                minimum: min,
2471                maximum: max,
2472            },
2473        }
2474    }
2475
2476    /// Returns the element value type of this table.
2477    pub fn element(&self) -> &RefType {
2478        &self.element
2479    }
2480
2481    /// Returns minimum number of elements this table must have
2482    pub fn minimum(&self) -> u32 {
2483        self.ty.minimum
2484    }
2485
2486    /// Returns the optionally-specified maximum number of elements this table
2487    /// can have.
2488    ///
2489    /// If this returns `None` then the table is not limited in size.
2490    pub fn maximum(&self) -> Option<u32> {
2491        self.ty.maximum
2492    }
2493
2494    pub(crate) fn from_wasmtime_table(engine: &Engine, table: &Table) -> TableType {
2495        let element = RefType::from_wasm_type(engine, &table.wasm_ty);
2496        TableType {
2497            element,
2498            ty: *table,
2499        }
2500    }
2501
2502    pub(crate) fn wasmtime_table(&self) -> &Table {
2503        &self.ty
2504    }
2505}
2506
2507// Memory Types
2508
2509/// A builder for [`MemoryType`][crate::MemoryType]s.
2510///
2511/// A new builder can be constructed via its `Default` implementation.
2512///
2513/// When you're done configuring, get the underlying
2514/// [`MemoryType`][crate::MemoryType] by calling the
2515/// [`build`][crate::MemoryTypeBuilder::build] method.
2516///
2517/// # Example
2518///
2519/// ```
2520/// # fn foo() -> wasmtime::Result<()> {
2521/// use wasmtime::MemoryTypeBuilder;
2522///
2523/// let memory_type = MemoryTypeBuilder::default()
2524///     // Set the minimum size, in pages.
2525///     .min(4096)
2526///     // Set the maximum size, in pages.
2527///     .max(Some(4096))
2528///     // Set the page size to 1 byte (aka 2**0).
2529///     .page_size_log2(0)
2530///     // Get the underlying memory type.
2531///     .build()?;
2532/// #   Ok(())
2533/// # }
2534/// ```
2535pub struct MemoryTypeBuilder {
2536    ty: Memory,
2537}
2538
2539impl Default for MemoryTypeBuilder {
2540    fn default() -> Self {
2541        MemoryTypeBuilder {
2542            ty: Memory {
2543                minimum: 0,
2544                maximum: None,
2545                shared: false,
2546                memory64: false,
2547                page_size_log2: Memory::DEFAULT_PAGE_SIZE_LOG2,
2548            },
2549        }
2550    }
2551}
2552
2553impl MemoryTypeBuilder {
2554    fn validate(&self) -> Result<()> {
2555        if self.ty.maximum.map_or(false, |max| max < self.ty.minimum) {
2556            bail!("maximum page size cannot be smaller than the minimum page size");
2557        }
2558
2559        match self.ty.page_size_log2 {
2560            0 | Memory::DEFAULT_PAGE_SIZE_LOG2 => {}
2561            x => bail!(
2562                "page size must be 2**16 or 2**0, but was given 2**{x}; note \
2563                 that future Wasm extensions might allow any power of two page \
2564                 size, but only 2**16 and 2**0 are currently valid",
2565            ),
2566        }
2567
2568        if self.ty.shared && self.ty.maximum.is_none() {
2569            bail!("shared memories must have a maximum size");
2570        }
2571
2572        let absolute_max = self.ty.max_size_based_on_index_type();
2573        let min = self
2574            .ty
2575            .minimum_byte_size()
2576            .err2anyhow()
2577            .context("memory's minimum byte size must fit in a u64")?;
2578        if min > absolute_max {
2579            bail!("minimum size is too large for this memory type's index type");
2580        }
2581        if self
2582            .ty
2583            .maximum_byte_size()
2584            .map_or(false, |max| max > absolute_max)
2585        {
2586            bail!("maximum size is too large for this memory type's index type");
2587        }
2588
2589        Ok(())
2590    }
2591
2592    /// Set the minimum size, in units of pages, for the memory type being
2593    /// built.
2594    ///
2595    /// The default minimum is `0`.
2596    pub fn min(&mut self, minimum: u64) -> &mut Self {
2597        self.ty.minimum = minimum;
2598        self
2599    }
2600
2601    /// Set the maximum size, in units of pages, for the memory type being
2602    /// built.
2603    ///
2604    /// The default maximum is `None`.
2605    pub fn max(&mut self, maximum: Option<u64>) -> &mut Self {
2606        self.ty.maximum = maximum;
2607        self
2608    }
2609
2610    /// Set whether this is a 64-bit memory or not.
2611    ///
2612    /// If a memory is not a 64-bit memory, then it is a 32-bit memory.
2613    ///
2614    /// The default is `false`, aka 32-bit memories.
2615    ///
2616    /// Note that 64-bit memories are part of [the memory64
2617    /// proposal](https://github.com/WebAssembly/memory64) for WebAssembly which
2618    /// is not fully standardized yet.
2619    pub fn memory64(&mut self, memory64: bool) -> &mut Self {
2620        self.ty.memory64 = memory64;
2621        self
2622    }
2623
2624    /// Set the sharedness for the memory type being built.
2625    ///
2626    /// The default is `false`, aka unshared.
2627    ///
2628    /// Note that shared memories are part of [the threads
2629    /// proposal](https://github.com/WebAssembly/threads) for WebAssembly which
2630    /// is not fully standardized yet.
2631    pub fn shared(&mut self, shared: bool) -> &mut Self {
2632        self.ty.shared = shared;
2633        self
2634    }
2635
2636    /// Set the log base 2 of the page size, in bytes, for the memory type being
2637    /// built.
2638    ///
2639    /// The default value is `16`, which results in the default Wasm page size
2640    /// of 64KiB (aka 2<sup>16</sup> or 65536).
2641    ///
2642    /// Other than `16`, the only valid value is `0`, which results in a page
2643    /// size of one byte (aka 2<sup>0</sup>). Single-byte page sizes can be used
2644    /// to get fine-grained control over a Wasm memory's resource consumption
2645    /// and run Wasm in embedded environments with less than 64KiB of RAM, for
2646    /// example.
2647    ///
2648    /// Future extensions to the core WebAssembly language might relax these
2649    /// constraints and introduce more valid page sizes, such as any power of
2650    /// two between 1 and 65536 inclusive.
2651    ///
2652    /// Note that non-default page sizes are part of [the custom-page-sizes
2653    /// proposal](https://github.com/WebAssembly/custom-page-sizes) for
2654    /// WebAssembly which is not fully standardized yet.
2655    pub fn page_size_log2(&mut self, page_size_log2: u8) -> &mut Self {
2656        self.ty.page_size_log2 = page_size_log2;
2657        self
2658    }
2659
2660    /// Get the underlying memory type that this builder has been building.
2661    ///
2662    /// # Errors
2663    ///
2664    /// Returns an error if the configured memory type is invalid, for example
2665    /// if the maximum size is smaller than the minimum size.
2666    pub fn build(&self) -> Result<MemoryType> {
2667        self.validate()?;
2668        Ok(MemoryType { ty: self.ty })
2669    }
2670}
2671
2672/// A descriptor for a WebAssembly memory type.
2673///
2674/// Memories are described in units of pages (64KB) and represent contiguous
2675/// chunks of addressable memory.
2676#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2677pub struct MemoryType {
2678    ty: Memory,
2679}
2680
2681impl MemoryType {
2682    /// Creates a new descriptor for a 32-bit WebAssembly memory given the
2683    /// specified limits of the memory.
2684    ///
2685    /// The `minimum` and `maximum` values here are specified in units of
2686    /// WebAssembly pages, which are 64KiB by default. Use
2687    /// [`MemoryTypeBuilder`][crate::MemoryTypeBuilder] if you want a
2688    /// non-default page size.
2689    ///
2690    /// # Panics
2691    ///
2692    /// Panics if the minimum is greater than the maximum or if the minimum or
2693    /// maximum number of pages can result in a byte size that is not
2694    /// addressable with a 32-bit integer.
2695    pub fn new(minimum: u32, maximum: Option<u32>) -> MemoryType {
2696        MemoryTypeBuilder::default()
2697            .min(minimum.into())
2698            .max(maximum.map(Into::into))
2699            .build()
2700            .unwrap()
2701    }
2702
2703    /// Creates a new descriptor for a 64-bit WebAssembly memory given the
2704    /// specified limits of the memory.
2705    ///
2706    /// The `minimum` and `maximum` values here are specified in units of
2707    /// WebAssembly pages, which are 64KiB by default. Use
2708    /// [`MemoryTypeBuilder`][crate::MemoryTypeBuilder] if you want a
2709    /// non-default page size.
2710    ///
2711    /// Note that 64-bit memories are part of [the memory64
2712    /// proposal](https://github.com/WebAssembly/memory64) for WebAssembly which
2713    /// is not fully standardized yet.
2714    ///
2715    /// # Panics
2716    ///
2717    /// Panics if the minimum is greater than the maximum or if the minimum or
2718    /// maximum number of pages can result in a byte size that is not
2719    /// addressable with a 64-bit integer.
2720    pub fn new64(minimum: u64, maximum: Option<u64>) -> MemoryType {
2721        MemoryTypeBuilder::default()
2722            .memory64(true)
2723            .min(minimum)
2724            .max(maximum)
2725            .build()
2726            .unwrap()
2727    }
2728
2729    /// Creates a new descriptor for shared WebAssembly memory given the
2730    /// specified limits of the memory.
2731    ///
2732    /// The `minimum` and `maximum` values here are specified in units of
2733    /// WebAssembly pages, which are 64KiB by default. Use
2734    /// [`MemoryTypeBuilder`][crate::MemoryTypeBuilder] if you want a
2735    /// non-default page size.
2736    ///
2737    /// Note that shared memories are part of [the threads
2738    /// proposal](https://github.com/WebAssembly/threads) for WebAssembly which
2739    /// is not fully standardized yet.
2740    ///
2741    /// # Panics
2742    ///
2743    /// Panics if the minimum is greater than the maximum or if the minimum or
2744    /// maximum number of pages can result in a byte size that is not
2745    /// addressable with a 32-bit integer.
2746    pub fn shared(minimum: u32, maximum: u32) -> MemoryType {
2747        MemoryTypeBuilder::default()
2748            .shared(true)
2749            .min(minimum.into())
2750            .max(Some(maximum.into()))
2751            .build()
2752            .unwrap()
2753    }
2754
2755    /// Returns whether this is a 64-bit memory or not.
2756    ///
2757    /// Note that 64-bit memories are part of the memory64 proposal for
2758    /// WebAssembly which is not standardized yet.
2759    pub fn is_64(&self) -> bool {
2760        self.ty.memory64
2761    }
2762
2763    /// Returns whether this is a shared memory or not.
2764    ///
2765    /// Note that shared memories are part of the threads proposal for
2766    /// WebAssembly which is not standardized yet.
2767    pub fn is_shared(&self) -> bool {
2768        self.ty.shared
2769    }
2770
2771    /// Returns minimum number of WebAssembly pages this memory must have.
2772    ///
2773    /// Note that the return value, while a `u64`, will always fit into a `u32`
2774    /// for 32-bit memories.
2775    pub fn minimum(&self) -> u64 {
2776        self.ty.minimum
2777    }
2778
2779    /// Returns the optionally-specified maximum number of pages this memory
2780    /// can have.
2781    ///
2782    /// If this returns `None` then the memory is not limited in size.
2783    ///
2784    /// Note that the return value, while a `u64`, will always fit into a `u32`
2785    /// for 32-bit memories.
2786    pub fn maximum(&self) -> Option<u64> {
2787        self.ty.maximum
2788    }
2789
2790    /// This memory's page size, in bytes.
2791    pub fn page_size(&self) -> u64 {
2792        self.ty.page_size()
2793    }
2794
2795    /// The log2 of this memory's page size, in bytes.
2796    pub fn page_size_log2(&self) -> u8 {
2797        self.ty.page_size_log2
2798    }
2799
2800    pub(crate) fn from_wasmtime_memory(memory: &Memory) -> MemoryType {
2801        MemoryType { ty: *memory }
2802    }
2803
2804    pub(crate) fn wasmtime_memory(&self) -> &Memory {
2805        &self.ty
2806    }
2807}
2808
2809// Import Types
2810
2811/// A descriptor for an imported value into a wasm module.
2812///
2813/// This type is primarily accessed from the
2814/// [`Module::imports`](crate::Module::imports) API. Each [`ImportType`]
2815/// describes an import into the wasm module with the module/name that it's
2816/// imported from as well as the type of item that's being imported.
2817#[derive(Clone)]
2818pub struct ImportType<'module> {
2819    /// The module of the import.
2820    module: &'module str,
2821
2822    /// The field of the import.
2823    name: &'module str,
2824
2825    /// The type of the import.
2826    ty: EntityType,
2827    types: &'module ModuleTypes,
2828    engine: &'module Engine,
2829}
2830
2831impl<'module> ImportType<'module> {
2832    /// Creates a new import descriptor which comes from `module` and `name` and
2833    /// is of type `ty`.
2834    pub(crate) fn new(
2835        module: &'module str,
2836        name: &'module str,
2837        ty: EntityType,
2838        types: &'module ModuleTypes,
2839        engine: &'module Engine,
2840    ) -> ImportType<'module> {
2841        assert!(ty.is_canonicalized_for_runtime_usage());
2842        ImportType {
2843            module,
2844            name,
2845            ty,
2846            types,
2847            engine,
2848        }
2849    }
2850
2851    /// Returns the module name that this import is expected to come from.
2852    pub fn module(&self) -> &'module str {
2853        self.module
2854    }
2855
2856    /// Returns the field name of the module that this import is expected to
2857    /// come from.
2858    pub fn name(&self) -> &'module str {
2859        self.name
2860    }
2861
2862    /// Returns the expected type of this import.
2863    pub fn ty(&self) -> ExternType {
2864        ExternType::from_wasmtime(self.engine, self.types, &self.ty)
2865    }
2866}
2867
2868impl<'module> fmt::Debug for ImportType<'module> {
2869    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2870        f.debug_struct("ImportType")
2871            .field("module", &self.module())
2872            .field("name", &self.name())
2873            .field("ty", &self.ty())
2874            .finish()
2875    }
2876}
2877
2878// Export Types
2879
2880/// A descriptor for an exported WebAssembly value.
2881///
2882/// This type is primarily accessed from the
2883/// [`Module::exports`](crate::Module::exports) accessor and describes what
2884/// names are exported from a wasm module and the type of the item that is
2885/// exported.
2886#[derive(Clone)]
2887pub struct ExportType<'module> {
2888    /// The name of the export.
2889    name: &'module str,
2890
2891    /// The type of the export.
2892    ty: EntityType,
2893    types: &'module ModuleTypes,
2894    engine: &'module Engine,
2895}
2896
2897impl<'module> ExportType<'module> {
2898    /// Creates a new export which is exported with the given `name` and has the
2899    /// given `ty`.
2900    pub(crate) fn new(
2901        name: &'module str,
2902        ty: EntityType,
2903        types: &'module ModuleTypes,
2904        engine: &'module Engine,
2905    ) -> ExportType<'module> {
2906        ExportType {
2907            name,
2908            ty,
2909            types,
2910            engine,
2911        }
2912    }
2913
2914    /// Returns the name by which this export is known.
2915    pub fn name(&self) -> &'module str {
2916        self.name
2917    }
2918
2919    /// Returns the type of this export.
2920    pub fn ty(&self) -> ExternType {
2921        ExternType::from_wasmtime(self.engine, self.types, &self.ty)
2922    }
2923}
2924
2925impl<'module> fmt::Debug for ExportType<'module> {
2926    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2927        f.debug_struct("ExportType")
2928            .field("name", &self.name().to_owned())
2929            .field("ty", &self.ty())
2930            .finish()
2931    }
2932}