wasmtime/runtime/
types.rs

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