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);
1800        Self::from_registered_type(ty)
1801    }
1802
1803    pub(crate) fn from_registered_type(registered_type: RegisteredType) -> Self {
1804        debug_assert!(registered_type.is_struct());
1805        Self { registered_type }
1806    }
1807}
1808
1809/// The type of a WebAssembly array.
1810///
1811/// WebAssembly arrays are dynamically-sized, but not resizable. They contain
1812/// either unpacked [`Val`][crate::Val]s or packed 8-/16-bit integers.
1813///
1814/// # Subtyping and Equality
1815///
1816/// `ArrayType` does not implement `Eq`, because reference types have a
1817/// subtyping relationship, and so 99.99% of the time you actually want to check
1818/// whether one type matches (i.e. is a subtype of) another type. You can use
1819/// the [`ArrayType::matches`] method to perform these types of checks. If,
1820/// however, you are in that 0.01% scenario where you need to check precise
1821/// equality between types, you can use the [`ArrayType::eq`] method.
1822//
1823// TODO: Once we have array values, update above docs with a reference to the
1824// future `Array::matches_ty` method
1825#[derive(Debug, Clone, Hash)]
1826pub struct ArrayType {
1827    registered_type: RegisteredType,
1828}
1829
1830impl fmt::Display for ArrayType {
1831    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1832        let field_ty = self.field_type();
1833        write!(f, "(array (field {field_ty}))")?;
1834        Ok(())
1835    }
1836}
1837
1838impl ArrayType {
1839    /// Construct a new `ArrayType` with the given field type's mutability and
1840    /// storage type.
1841    ///
1842    /// The new `ArrayType` will be final and without a supertype.
1843    ///
1844    /// The result will be associated with the given engine, and attempts to use
1845    /// it with other engines will panic (for example, checking whether it is a
1846    /// subtype of another array type that is associated with a different
1847    /// engine).
1848    ///
1849    /// # Panics
1850    ///
1851    /// Panics if the given field type is not associated with the given engine.
1852    pub fn new(engine: &Engine, field_type: FieldType) -> Self {
1853        Self::with_finality_and_supertype(engine, Finality::Final, None, field_type)
1854            .expect("cannot fail without a supertype")
1855    }
1856
1857    /// Construct a new `StructType` with the given finality, supertype, and
1858    /// fields.
1859    ///
1860    /// The result will be associated with the given engine, and attempts to use
1861    /// it with other engines will panic (for example, checking whether it is a
1862    /// subtype of another struct type that is associated with a different
1863    /// engine).
1864    ///
1865    /// Returns an error if the supertype is final, or if this type does not
1866    /// match the supertype.
1867    ///
1868    /// # Panics
1869    ///
1870    /// Panics if the given field type is not associated with the given engine.
1871    pub fn with_finality_and_supertype(
1872        engine: &Engine,
1873        finality: Finality,
1874        supertype: Option<&Self>,
1875        field_type: FieldType,
1876    ) -> Result<Self> {
1877        if let Some(supertype) = supertype {
1878            assert!(supertype.comes_from_same_engine(engine));
1879            ensure!(
1880                supertype.finality().is_non_final(),
1881                "cannot create a subtype of a final supertype"
1882            );
1883            ensure!(
1884                field_type.matches(&supertype.field_type()),
1885                "array field type must match its supertype's field type"
1886            );
1887        }
1888
1889        // Same as in `FuncType::new`: we must prevent any `RegisteredType` in
1890        // `field_type` from being reclaimed while constructing this array type.
1891        let _registration = field_type
1892            .element_type
1893            .as_val_type()
1894            .and_then(|v| v.as_ref())
1895            .and_then(|r| r.heap_type().as_registered_type());
1896
1897        assert!(field_type.comes_from_same_engine(engine));
1898        let wasm_ty = WasmArrayType(field_type.to_wasm_field_type());
1899
1900        Ok(Self::from_wasm_array_type(
1901            engine,
1902            finality.is_final(),
1903            supertype.map(|ty| ty.type_index().into()),
1904            wasm_ty,
1905        ))
1906    }
1907
1908    /// Get the engine that this array type is associated with.
1909    pub fn engine(&self) -> &Engine {
1910        self.registered_type.engine()
1911    }
1912
1913    /// Get the finality of this array type.
1914    pub fn finality(&self) -> Finality {
1915        match self.registered_type.is_final {
1916            true => Finality::Final,
1917            false => Finality::NonFinal,
1918        }
1919    }
1920
1921    /// Get the supertype of this array type, if any.
1922    pub fn supertype(&self) -> Option<Self> {
1923        self.registered_type
1924            .supertype
1925            .map(|ty| Self::from_shared_type_index(self.engine(), ty.unwrap_engine_type_index()))
1926    }
1927
1928    /// Get this array's underlying field type.
1929    ///
1930    /// The field type contains information about both this array type's
1931    /// mutability and the storage type used for its elements.
1932    pub fn field_type(&self) -> FieldType {
1933        FieldType::from_wasm_field_type(self.engine(), &self.as_wasm_array_type().0)
1934    }
1935
1936    /// Get this array type's mutability and whether its instances' elements can
1937    /// be updated or not.
1938    ///
1939    /// This is a convenience method providing a short-hand for
1940    /// `my_array_type.field_type().mutability()`.
1941    pub fn mutability(&self) -> Mutability {
1942        if self.as_wasm_array_type().0.mutable {
1943            Mutability::Var
1944        } else {
1945            Mutability::Const
1946        }
1947    }
1948
1949    /// Get the storage type used for this array type's elements.
1950    ///
1951    /// This is a convenience method providing a short-hand for
1952    /// `my_array_type.field_type().element_type()`.
1953    pub fn element_type(&self) -> StorageType {
1954        StorageType::from_wasm_storage_type(
1955            self.engine(),
1956            &self.registered_type.unwrap_array().0.element_type,
1957        )
1958    }
1959
1960    /// Does this array type match the other array type?
1961    ///
1962    /// That is, is this function type a subtype of the other array type?
1963    ///
1964    /// # Panics
1965    ///
1966    /// Panics if either type is associated with a different engine from the
1967    /// other.
1968    pub fn matches(&self, other: &ArrayType) -> bool {
1969        assert!(self.comes_from_same_engine(other.engine()));
1970
1971        self.engine()
1972            .signatures()
1973            .is_subtype(self.type_index(), other.type_index())
1974    }
1975
1976    /// Is array type `a` precisely equal to array type `b`?
1977    ///
1978    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
1979    /// are not exactly the same array type.
1980    ///
1981    /// # Panics
1982    ///
1983    /// Panics if either type is associated with a different engine from the
1984    /// other.
1985    pub fn eq(a: &ArrayType, b: &ArrayType) -> bool {
1986        assert!(a.comes_from_same_engine(b.engine()));
1987        a.type_index() == b.type_index()
1988    }
1989
1990    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
1991        Engine::same(self.registered_type.engine(), engine)
1992    }
1993
1994    #[cfg(feature = "gc")]
1995    pub(crate) fn registered_type(&self) -> &RegisteredType {
1996        &self.registered_type
1997    }
1998
1999    pub(crate) fn type_index(&self) -> VMSharedTypeIndex {
2000        self.registered_type.index()
2001    }
2002
2003    pub(crate) fn as_wasm_array_type(&self) -> &WasmArrayType {
2004        self.registered_type.unwrap_array()
2005    }
2006
2007    /// Construct a `ArrayType` from a `WasmArrayType`.
2008    ///
2009    /// This method should only be used when something has already registered --
2010    /// and is *keeping registered* -- any other concrete Wasm types referenced
2011    /// by the given `WasmArrayType`.
2012    ///
2013    /// For example, this method may be called to convert an array type from
2014    /// within a Wasm module's `ModuleTypes` since the Wasm module itself is
2015    /// holding a strong reference to all of its types, including any `(ref null
2016    /// <index>)` types used as the element type for this array type.
2017    pub(crate) fn from_wasm_array_type(
2018        engine: &Engine,
2019        is_final: bool,
2020        supertype: Option<EngineOrModuleTypeIndex>,
2021        ty: WasmArrayType,
2022    ) -> ArrayType {
2023        let ty = RegisteredType::new(
2024            engine,
2025            WasmSubType {
2026                is_final,
2027                supertype,
2028                composite_type: WasmCompositeType {
2029                    shared: false,
2030                    inner: WasmCompositeInnerType::Array(ty),
2031                },
2032            },
2033        );
2034        Self {
2035            registered_type: ty,
2036        }
2037    }
2038
2039    pub(crate) fn from_shared_type_index(engine: &Engine, index: VMSharedTypeIndex) -> ArrayType {
2040        let ty = RegisteredType::root(engine, index);
2041        Self::from_registered_type(ty)
2042    }
2043
2044    pub(crate) fn from_registered_type(registered_type: RegisteredType) -> Self {
2045        debug_assert!(registered_type.is_array());
2046        Self { registered_type }
2047    }
2048}
2049
2050/// The type of a WebAssembly function.
2051///
2052/// WebAssembly functions can have 0 or more parameters and results.
2053///
2054/// # Subtyping and Equality
2055///
2056/// `FuncType` does not implement `Eq`, because reference types have a subtyping
2057/// relationship, and so 99.99% of the time you actually want to check whether
2058/// one type matches (i.e. is a subtype of) another type. You can use the
2059/// [`FuncType::matches`] and [`Func::matches_ty`][crate::Func::matches_ty]
2060/// methods to perform these types of checks. If, however, you are in that 0.01%
2061/// scenario where you need to check precise equality between types, you can use
2062/// the [`FuncType::eq`] method.
2063#[derive(Debug, Clone, Hash)]
2064pub struct FuncType {
2065    registered_type: RegisteredType,
2066}
2067
2068impl Display for FuncType {
2069    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2070        write!(f, "(type (func")?;
2071        if self.params().len() > 0 {
2072            write!(f, " (param")?;
2073            for p in self.params() {
2074                write!(f, " {p}")?;
2075            }
2076            write!(f, ")")?;
2077        }
2078        if self.results().len() > 0 {
2079            write!(f, " (result")?;
2080            for r in self.results() {
2081                write!(f, " {r}")?;
2082            }
2083            write!(f, ")")?;
2084        }
2085        write!(f, "))")
2086    }
2087}
2088
2089impl FuncType {
2090    /// Creates a new function type from the given parameters and results.
2091    ///
2092    /// The function type returned will represent a function which takes
2093    /// `params` as arguments and returns `results` when it is finished.
2094    ///
2095    /// The resulting function type will be final and without a supertype.
2096    ///
2097    /// # Panics
2098    ///
2099    /// Panics if any parameter or value type is not associated with the given
2100    /// engine.
2101    pub fn new(
2102        engine: &Engine,
2103        params: impl IntoIterator<Item = ValType>,
2104        results: impl IntoIterator<Item = ValType>,
2105    ) -> FuncType {
2106        Self::with_finality_and_supertype(engine, Finality::Final, None, params, results)
2107            .expect("cannot fail without a supertype")
2108    }
2109
2110    /// Create a new function type with the given finality, supertype, parameter
2111    /// types, and result types.
2112    ///
2113    /// Returns an error if the supertype is final, or if this function type
2114    /// does not match the supertype.
2115    ///
2116    /// # Panics
2117    ///
2118    /// Panics if any parameter or value type is not associated with the given
2119    /// engine.
2120    pub fn with_finality_and_supertype(
2121        engine: &Engine,
2122        finality: Finality,
2123        supertype: Option<&Self>,
2124        params: impl IntoIterator<Item = ValType>,
2125        results: impl IntoIterator<Item = ValType>,
2126    ) -> Result<Self> {
2127        let params = params.into_iter();
2128        let results = results.into_iter();
2129
2130        let mut wasmtime_params = Vec::with_capacity({
2131            let size_hint = params.size_hint();
2132            let cap = size_hint.1.unwrap_or(size_hint.0);
2133            // Only reserve space if we have a supertype, as that is the only time
2134            // that this vec is used.
2135            supertype.is_some() as usize * cap
2136        });
2137
2138        let mut wasmtime_results = Vec::with_capacity({
2139            let size_hint = results.size_hint();
2140            let cap = size_hint.1.unwrap_or(size_hint.0);
2141            // Same as above.
2142            supertype.is_some() as usize * cap
2143        });
2144
2145        // Keep any of our parameters' and results' `RegisteredType`s alive
2146        // across `Self::from_wasm_func_type`. If one of our given `ValType`s is
2147        // the only thing keeping a type in the registry, we don't want to
2148        // unregister it when we convert the `ValType` into a `WasmValType` just
2149        // before we register our new `WasmFuncType` that will reference it.
2150        let mut registrations = smallvec::SmallVec::<[_; 4]>::new();
2151
2152        let mut to_wasm_type = |ty: ValType, vec: &mut Vec<_>| {
2153            assert!(ty.comes_from_same_engine(engine));
2154
2155            if supertype.is_some() {
2156                vec.push(ty.clone());
2157            }
2158
2159            if let Some(r) = ty.as_ref() {
2160                if let Some(r) = r.heap_type().as_registered_type() {
2161                    registrations.push(r.clone());
2162                }
2163            }
2164
2165            ty.to_wasm_type()
2166        };
2167
2168        let wasm_func_ty = WasmFuncType::new(
2169            params
2170                .map(|p| to_wasm_type(p, &mut wasmtime_params))
2171                .collect(),
2172            results
2173                .map(|r| to_wasm_type(r, &mut wasmtime_results))
2174                .collect(),
2175        );
2176
2177        if let Some(supertype) = supertype {
2178            assert!(supertype.comes_from_same_engine(engine));
2179            ensure!(
2180                supertype.finality().is_non_final(),
2181                "cannot create a subtype of a final supertype"
2182            );
2183            ensure!(
2184                Self::matches_impl(
2185                    wasmtime_params.iter().cloned(),
2186                    supertype.params(),
2187                    wasmtime_results.iter().cloned(),
2188                    supertype.results()
2189                ),
2190                "function type must match its supertype: found (func{params}{results}), expected \
2191                 {supertype}",
2192                params = if wasmtime_params.is_empty() {
2193                    String::new()
2194                } else {
2195                    let mut s = format!(" (params");
2196                    for p in &wasmtime_params {
2197                        write!(&mut s, " {p}").unwrap();
2198                    }
2199                    s.push(')');
2200                    s
2201                },
2202                results = if wasmtime_results.is_empty() {
2203                    String::new()
2204                } else {
2205                    let mut s = format!(" (results");
2206                    for r in &wasmtime_results {
2207                        write!(&mut s, " {r}").unwrap();
2208                    }
2209                    s.push(')');
2210                    s
2211                },
2212            );
2213        }
2214
2215        Ok(Self::from_wasm_func_type(
2216            engine,
2217            finality.is_final(),
2218            supertype.map(|ty| ty.type_index().into()),
2219            wasm_func_ty,
2220        ))
2221    }
2222
2223    /// Get the engine that this function type is associated with.
2224    pub fn engine(&self) -> &Engine {
2225        self.registered_type.engine()
2226    }
2227
2228    /// Get the finality of this function type.
2229    pub fn finality(&self) -> Finality {
2230        match self.registered_type.is_final {
2231            true => Finality::Final,
2232            false => Finality::NonFinal,
2233        }
2234    }
2235
2236    /// Get the supertype of this function type, if any.
2237    pub fn supertype(&self) -> Option<Self> {
2238        self.registered_type
2239            .supertype
2240            .map(|ty| Self::from_shared_type_index(self.engine(), ty.unwrap_engine_type_index()))
2241    }
2242
2243    /// Get the `i`th parameter type.
2244    ///
2245    /// Returns `None` if `i` is out of bounds.
2246    pub fn param(&self, i: usize) -> Option<ValType> {
2247        let engine = self.engine();
2248        self.registered_type
2249            .unwrap_func()
2250            .params()
2251            .get(i)
2252            .map(|ty| ValType::from_wasm_type(engine, ty))
2253    }
2254
2255    /// Returns the list of parameter types for this function.
2256    #[inline]
2257    pub fn params(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
2258        let engine = self.engine();
2259        self.registered_type
2260            .unwrap_func()
2261            .params()
2262            .iter()
2263            .map(|ty| ValType::from_wasm_type(engine, ty))
2264    }
2265
2266    /// Get the `i`th result type.
2267    ///
2268    /// Returns `None` if `i` is out of bounds.
2269    pub fn result(&self, i: usize) -> Option<ValType> {
2270        let engine = self.engine();
2271        self.registered_type
2272            .unwrap_func()
2273            .returns()
2274            .get(i)
2275            .map(|ty| ValType::from_wasm_type(engine, ty))
2276    }
2277
2278    /// Returns the list of result types for this function.
2279    #[inline]
2280    pub fn results(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
2281        let engine = self.engine();
2282        self.registered_type
2283            .unwrap_func()
2284            .returns()
2285            .iter()
2286            .map(|ty| ValType::from_wasm_type(engine, ty))
2287    }
2288
2289    /// Does this function type match the other function type?
2290    ///
2291    /// That is, is this function type a subtype of the other function type?
2292    ///
2293    /// # Panics
2294    ///
2295    /// Panics if either type is associated with a different engine from the
2296    /// other.
2297    pub fn matches(&self, other: &FuncType) -> bool {
2298        assert!(self.comes_from_same_engine(other.engine()));
2299
2300        // Avoid matching on structure for subtyping checks when we have
2301        // precisely the same type.
2302        if self.type_index() == other.type_index() {
2303            return true;
2304        }
2305
2306        Self::matches_impl(
2307            self.params(),
2308            other.params(),
2309            self.results(),
2310            other.results(),
2311        )
2312    }
2313
2314    fn matches_impl(
2315        a_params: impl ExactSizeIterator<Item = ValType>,
2316        b_params: impl ExactSizeIterator<Item = ValType>,
2317        a_results: impl ExactSizeIterator<Item = ValType>,
2318        b_results: impl ExactSizeIterator<Item = ValType>,
2319    ) -> bool {
2320        a_params.len() == b_params.len()
2321            && a_results.len() == b_results.len()
2322            // Params are contravariant and results are covariant. For more
2323            // details and a refresher on variance, read
2324            // https://github.com/bytecodealliance/wasm-tools/blob/f1d89a4/crates/wasmparser/src/readers/core/types/matches.rs#L137-L174
2325            && a_params
2326                .zip(b_params)
2327                .all(|(a, b)| b.matches(&a))
2328            && a_results
2329                .zip(b_results)
2330                .all(|(a, b)| a.matches(&b))
2331    }
2332
2333    /// Is function type `a` precisely equal to function type `b`?
2334    ///
2335    /// Returns `false` even if `a` is a subtype of `b` or vice versa, if they
2336    /// are not exactly the same function type.
2337    ///
2338    /// # Panics
2339    ///
2340    /// Panics if either type is associated with a different engine from the
2341    /// other.
2342    pub fn eq(a: &FuncType, b: &FuncType) -> bool {
2343        assert!(a.comes_from_same_engine(b.engine()));
2344        a.type_index() == b.type_index()
2345    }
2346
2347    pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
2348        Engine::same(self.registered_type.engine(), engine)
2349    }
2350
2351    pub(crate) fn type_index(&self) -> VMSharedTypeIndex {
2352        self.registered_type.index()
2353    }
2354
2355    #[cfg(feature = "gc")]
2356    pub(crate) fn as_wasm_func_type(&self) -> &WasmFuncType {
2357        self.registered_type.unwrap_func()
2358    }
2359
2360    pub(crate) fn into_registered_type(self) -> RegisteredType {
2361        self.registered_type
2362    }
2363
2364    /// Construct a `FuncType` from a `WasmFuncType`.
2365    ///
2366    /// This method should only be used when something has already registered --
2367    /// and is *keeping registered* -- any other concrete Wasm types referenced
2368    /// by the given `WasmFuncType`.
2369    ///
2370    /// For example, this method may be called to convert a function type from
2371    /// within a Wasm module's `ModuleTypes` since the Wasm module itself is
2372    /// holding a strong reference to all of its types, including any `(ref null
2373    /// <index>)` types used in the function's parameters and results.
2374    pub(crate) fn from_wasm_func_type(
2375        engine: &Engine,
2376        is_final: bool,
2377        supertype: Option<EngineOrModuleTypeIndex>,
2378        ty: WasmFuncType,
2379    ) -> FuncType {
2380        let ty = RegisteredType::new(
2381            engine,
2382            WasmSubType {
2383                is_final,
2384                supertype,
2385                composite_type: WasmCompositeType {
2386                    shared: false,
2387                    inner: WasmCompositeInnerType::Func(ty),
2388                },
2389            },
2390        );
2391        Self {
2392            registered_type: ty,
2393        }
2394    }
2395
2396    pub(crate) fn from_shared_type_index(engine: &Engine, index: VMSharedTypeIndex) -> FuncType {
2397        let ty = RegisteredType::root(engine, index);
2398        Self::from_registered_type(ty)
2399    }
2400
2401    pub(crate) fn from_registered_type(registered_type: RegisteredType) -> Self {
2402        debug_assert!(registered_type.is_func());
2403        Self { registered_type }
2404    }
2405}
2406
2407// Global Types
2408
2409/// A WebAssembly global descriptor.
2410///
2411/// This type describes an instance of a global in a WebAssembly module. Globals
2412/// are local to an [`Instance`](crate::Instance) and are either immutable or
2413/// mutable.
2414#[derive(Debug, Clone, Hash)]
2415pub struct GlobalType {
2416    content: ValType,
2417    mutability: Mutability,
2418}
2419
2420impl GlobalType {
2421    /// Creates a new global descriptor of the specified `content` type and
2422    /// whether or not it's mutable.
2423    pub fn new(content: ValType, mutability: Mutability) -> GlobalType {
2424        GlobalType {
2425            content,
2426            mutability,
2427        }
2428    }
2429
2430    /// Returns the value type of this global descriptor.
2431    pub fn content(&self) -> &ValType {
2432        &self.content
2433    }
2434
2435    /// Returns whether or not this global is mutable.
2436    pub fn mutability(&self) -> Mutability {
2437        self.mutability
2438    }
2439
2440    pub(crate) fn to_wasm_type(&self) -> Global {
2441        let wasm_ty = self.content().to_wasm_type();
2442        let mutability = matches!(self.mutability(), Mutability::Var);
2443        Global {
2444            wasm_ty,
2445            mutability,
2446        }
2447    }
2448
2449    /// Returns `None` if the wasmtime global has a type that we can't
2450    /// represent, but that should only very rarely happen and indicate a bug.
2451    pub(crate) fn from_wasmtime_global(engine: &Engine, global: &Global) -> GlobalType {
2452        let ty = ValType::from_wasm_type(engine, &global.wasm_ty);
2453        let mutability = if global.mutability {
2454            Mutability::Var
2455        } else {
2456            Mutability::Const
2457        };
2458        GlobalType::new(ty, mutability)
2459    }
2460}
2461
2462// Tag Types
2463
2464/// A descriptor for a tag in a WebAssembly module.
2465///
2466/// This type describes an instance of a tag in a WebAssembly
2467/// module. Tags are local to an [`Instance`](crate::Instance).
2468#[derive(Debug, Clone, Hash)]
2469pub struct TagType {
2470    ty: FuncType,
2471}
2472
2473impl TagType {
2474    /// Creates a new global descriptor of the specified type.
2475    pub fn new(ty: FuncType) -> TagType {
2476        TagType { ty }
2477    }
2478
2479    /// Returns the underlying function type of this tag descriptor.
2480    pub fn ty(&self) -> &FuncType {
2481        &self.ty
2482    }
2483
2484    pub(crate) fn from_wasmtime_tag(engine: &Engine, tag: &Tag) -> TagType {
2485        let ty = FuncType::from_shared_type_index(engine, tag.signature.unwrap_engine_type_index());
2486        TagType { ty }
2487    }
2488}
2489
2490// Table Types
2491
2492/// A descriptor for a table in a WebAssembly module.
2493///
2494/// Tables are contiguous chunks of a specific element, typically a `funcref` or
2495/// an `externref`. The most common use for tables is a function table through
2496/// which `call_indirect` can invoke other functions.
2497#[derive(Debug, Clone, Hash)]
2498pub struct TableType {
2499    // Keep a `wasmtime::RefType` so that `TableType::element` doesn't need to
2500    // take an `&Engine`.
2501    element: RefType,
2502    ty: Table,
2503}
2504
2505impl TableType {
2506    /// Creates a new table descriptor which will contain the specified
2507    /// `element` and have the `limits` applied to its length.
2508    pub fn new(element: RefType, min: u32, max: Option<u32>) -> TableType {
2509        let ref_type = element.to_wasm_type();
2510
2511        debug_assert!(
2512            ref_type.is_canonicalized_for_runtime_usage(),
2513            "should be canonicalized for runtime usage: {ref_type:?}"
2514        );
2515
2516        let limits = Limits {
2517            min: u64::from(min),
2518            max: max.map(|x| u64::from(x)),
2519        };
2520
2521        TableType {
2522            element,
2523            ty: Table {
2524                idx_type: IndexType::I32,
2525                limits,
2526                ref_type,
2527            },
2528        }
2529    }
2530
2531    /// Crates a new descriptor for a 64-bit table.
2532    ///
2533    /// Note that 64-bit tables are part of the memory64 proposal for
2534    /// WebAssembly which is not standardized yet.
2535    pub fn new64(element: RefType, min: u64, max: Option<u64>) -> TableType {
2536        let ref_type = element.to_wasm_type();
2537
2538        debug_assert!(
2539            ref_type.is_canonicalized_for_runtime_usage(),
2540            "should be canonicalized for runtime usage: {ref_type:?}"
2541        );
2542
2543        TableType {
2544            element,
2545            ty: Table {
2546                ref_type,
2547                idx_type: IndexType::I64,
2548                limits: Limits { min, max },
2549            },
2550        }
2551    }
2552
2553    /// Returns whether or not this table is a 64-bit table.
2554    ///
2555    /// Note that 64-bit tables are part of the memory64 proposal for
2556    /// WebAssembly which is not standardized yet.
2557    pub fn is_64(&self) -> bool {
2558        matches!(self.ty.idx_type, IndexType::I64)
2559    }
2560
2561    /// Returns the element value type of this table.
2562    pub fn element(&self) -> &RefType {
2563        &self.element
2564    }
2565
2566    /// Returns minimum number of elements this table must have
2567    pub fn minimum(&self) -> u64 {
2568        self.ty.limits.min
2569    }
2570
2571    /// Returns the optionally-specified maximum number of elements this table
2572    /// can have.
2573    ///
2574    /// If this returns `None` then the table is not limited in size.
2575    pub fn maximum(&self) -> Option<u64> {
2576        self.ty.limits.max
2577    }
2578
2579    pub(crate) fn from_wasmtime_table(engine: &Engine, table: &Table) -> TableType {
2580        let element = RefType::from_wasm_type(engine, &table.ref_type);
2581        TableType {
2582            element,
2583            ty: *table,
2584        }
2585    }
2586
2587    pub(crate) fn wasmtime_table(&self) -> &Table {
2588        &self.ty
2589    }
2590}
2591
2592// Memory Types
2593
2594/// A builder for [`MemoryType`][crate::MemoryType]s.
2595///
2596/// A new builder can be constructed via its `Default` implementation.
2597///
2598/// When you're done configuring, get the underlying
2599/// [`MemoryType`][crate::MemoryType] by calling the
2600/// [`build`][crate::MemoryTypeBuilder::build] method.
2601///
2602/// # Example
2603///
2604/// ```
2605/// # fn foo() -> wasmtime::Result<()> {
2606/// use wasmtime::MemoryTypeBuilder;
2607///
2608/// let memory_type = MemoryTypeBuilder::new()
2609///     // Set the minimum size, in pages.
2610///     .min(4096)
2611///     // Set the maximum size, in pages.
2612///     .max(Some(4096))
2613///     // Set the page size to 1 byte (aka 2**0).
2614///     .page_size_log2(0)
2615///     // Get the underlying memory type.
2616///     .build()?;
2617/// #   Ok(())
2618/// # }
2619/// ```
2620pub struct MemoryTypeBuilder {
2621    ty: Memory,
2622}
2623
2624impl Default for MemoryTypeBuilder {
2625    fn default() -> Self {
2626        MemoryTypeBuilder {
2627            ty: Memory {
2628                idx_type: IndexType::I32,
2629                limits: Limits { min: 0, max: None },
2630                shared: false,
2631                page_size_log2: Memory::DEFAULT_PAGE_SIZE_LOG2,
2632            },
2633        }
2634    }
2635}
2636
2637impl MemoryTypeBuilder {
2638    /// Create a new builder for a [`MemoryType`] with the default settings.
2639    ///
2640    /// By default memory types have the following properties:
2641    ///
2642    /// * The minimum memory size is 0 pages.
2643    /// * The maximum memory size is unspecified.
2644    /// * Memories use 32-bit indexes.
2645    /// * The page size is 64KiB.
2646    ///
2647    /// Each option can be configured through the methods on the returned
2648    /// builder.
2649    pub fn new() -> MemoryTypeBuilder {
2650        MemoryTypeBuilder::default()
2651    }
2652
2653    fn validate(&self) -> Result<()> {
2654        if self
2655            .ty
2656            .limits
2657            .max
2658            .map_or(false, |max| max < self.ty.limits.min)
2659        {
2660            bail!("maximum page size cannot be smaller than the minimum page size");
2661        }
2662
2663        match self.ty.page_size_log2 {
2664            0 | Memory::DEFAULT_PAGE_SIZE_LOG2 => {}
2665            x => bail!(
2666                "page size must be 2**16 or 2**0, but was given 2**{x}; note \
2667                 that future Wasm extensions might allow any power of two page \
2668                 size, but only 2**16 and 2**0 are currently valid",
2669            ),
2670        }
2671
2672        if self.ty.shared && self.ty.limits.max.is_none() {
2673            bail!("shared memories must have a maximum size");
2674        }
2675
2676        let absolute_max = self.ty.max_size_based_on_index_type();
2677        let min = self
2678            .ty
2679            .minimum_byte_size()
2680            .context("memory's minimum byte size must fit in a u64")?;
2681        if min > absolute_max {
2682            bail!("minimum size is too large for this memory type's index type");
2683        }
2684        if self
2685            .ty
2686            .maximum_byte_size()
2687            .map_or(false, |max| max > absolute_max)
2688        {
2689            bail!("maximum size is too large for this memory type's index type");
2690        }
2691
2692        Ok(())
2693    }
2694
2695    /// Set the minimum size, in units of pages, for the memory type being
2696    /// built.
2697    ///
2698    /// The default minimum is `0`.
2699    pub fn min(&mut self, minimum: u64) -> &mut Self {
2700        self.ty.limits.min = minimum;
2701        self
2702    }
2703
2704    /// Set the maximum size, in units of pages, for the memory type being
2705    /// built.
2706    ///
2707    /// The default maximum is `None`.
2708    pub fn max(&mut self, maximum: Option<u64>) -> &mut Self {
2709        self.ty.limits.max = maximum;
2710        self
2711    }
2712
2713    /// Set whether this is a 64-bit memory or not.
2714    ///
2715    /// If a memory is not a 64-bit memory, then it is a 32-bit memory.
2716    ///
2717    /// The default is `false`, aka 32-bit memories.
2718    ///
2719    /// Note that 64-bit memories are part of [the memory64
2720    /// proposal](https://github.com/WebAssembly/memory64) for WebAssembly which
2721    /// is not fully standardized yet.
2722    pub fn memory64(&mut self, memory64: bool) -> &mut Self {
2723        self.ty.idx_type = match memory64 {
2724            true => IndexType::I64,
2725            false => IndexType::I32,
2726        };
2727        self
2728    }
2729
2730    /// Set the sharedness for the memory type being built.
2731    ///
2732    /// The default is `false`, aka unshared.
2733    ///
2734    /// Note that shared memories are part of [the threads
2735    /// proposal](https://github.com/WebAssembly/threads) for WebAssembly which
2736    /// is not fully standardized yet.
2737    pub fn shared(&mut self, shared: bool) -> &mut Self {
2738        self.ty.shared = shared;
2739        self
2740    }
2741
2742    /// Set the log base 2 of the page size, in bytes, for the memory type being
2743    /// built.
2744    ///
2745    /// The default value is `16`, which results in the default Wasm page size
2746    /// of 64KiB (aka 2<sup>16</sup> or 65536).
2747    ///
2748    /// Other than `16`, the only valid value is `0`, which results in a page
2749    /// size of one byte (aka 2<sup>0</sup>). Single-byte page sizes can be used
2750    /// to get fine-grained control over a Wasm memory's resource consumption
2751    /// and run Wasm in embedded environments with less than 64KiB of RAM, for
2752    /// example.
2753    ///
2754    /// Future extensions to the core WebAssembly language might relax these
2755    /// constraints and introduce more valid page sizes, such as any power of
2756    /// two between 1 and 65536 inclusive.
2757    ///
2758    /// Note that non-default page sizes are part of [the custom-page-sizes
2759    /// proposal](https://github.com/WebAssembly/custom-page-sizes) for
2760    /// WebAssembly which is not fully standardized yet.
2761    pub fn page_size_log2(&mut self, page_size_log2: u8) -> &mut Self {
2762        self.ty.page_size_log2 = page_size_log2;
2763        self
2764    }
2765
2766    /// Get the underlying memory type that this builder has been building.
2767    ///
2768    /// # Errors
2769    ///
2770    /// Returns an error if the configured memory type is invalid, for example
2771    /// if the maximum size is smaller than the minimum size.
2772    pub fn build(&self) -> Result<MemoryType> {
2773        self.validate()?;
2774        Ok(MemoryType { ty: self.ty })
2775    }
2776}
2777
2778/// A descriptor for a WebAssembly memory type.
2779///
2780/// Memories are described in units of pages (64KB) and represent contiguous
2781/// chunks of addressable memory.
2782#[derive(Debug, Clone, Hash, Eq, PartialEq)]
2783pub struct MemoryType {
2784    ty: Memory,
2785}
2786
2787impl MemoryType {
2788    /// Creates a new descriptor for a 32-bit WebAssembly memory given the
2789    /// specified limits of the memory.
2790    ///
2791    /// The `minimum` and `maximum` values here are specified in units of
2792    /// WebAssembly pages, which are 64KiB by default. Use
2793    /// [`MemoryTypeBuilder`][crate::MemoryTypeBuilder] if you want a
2794    /// non-default page size.
2795    ///
2796    /// # Panics
2797    ///
2798    /// Panics if the minimum is greater than the maximum or if the minimum or
2799    /// maximum number of pages can result in a byte size that is not
2800    /// addressable with a 32-bit integer.
2801    pub fn new(minimum: u32, maximum: Option<u32>) -> MemoryType {
2802        MemoryTypeBuilder::default()
2803            .min(minimum.into())
2804            .max(maximum.map(Into::into))
2805            .build()
2806            .unwrap()
2807    }
2808
2809    /// Creates a new descriptor for a 64-bit WebAssembly memory given the
2810    /// specified limits of the memory.
2811    ///
2812    /// The `minimum` and `maximum` values here are specified in units of
2813    /// WebAssembly pages, which are 64KiB by default. Use
2814    /// [`MemoryTypeBuilder`][crate::MemoryTypeBuilder] if you want a
2815    /// non-default page size.
2816    ///
2817    /// Note that 64-bit memories are part of [the memory64
2818    /// proposal](https://github.com/WebAssembly/memory64) for WebAssembly which
2819    /// is not fully standardized yet.
2820    ///
2821    /// # Panics
2822    ///
2823    /// Panics if the minimum is greater than the maximum or if the minimum or
2824    /// maximum number of pages can result in a byte size that is not
2825    /// addressable with a 64-bit integer.
2826    pub fn new64(minimum: u64, maximum: Option<u64>) -> MemoryType {
2827        MemoryTypeBuilder::default()
2828            .memory64(true)
2829            .min(minimum)
2830            .max(maximum)
2831            .build()
2832            .unwrap()
2833    }
2834
2835    /// Creates a new descriptor for shared WebAssembly memory given the
2836    /// specified limits of the memory.
2837    ///
2838    /// The `minimum` and `maximum` values here are specified in units of
2839    /// WebAssembly pages, which are 64KiB by default. Use
2840    /// [`MemoryTypeBuilder`][crate::MemoryTypeBuilder] if you want a
2841    /// non-default page size.
2842    ///
2843    /// Note that shared memories are part of [the threads
2844    /// proposal](https://github.com/WebAssembly/threads) for WebAssembly which
2845    /// is not fully standardized yet.
2846    ///
2847    /// # Panics
2848    ///
2849    /// Panics if the minimum is greater than the maximum or if the minimum or
2850    /// maximum number of pages can result in a byte size that is not
2851    /// addressable with a 32-bit integer.
2852    pub fn shared(minimum: u32, maximum: u32) -> MemoryType {
2853        MemoryTypeBuilder::default()
2854            .shared(true)
2855            .min(minimum.into())
2856            .max(Some(maximum.into()))
2857            .build()
2858            .unwrap()
2859    }
2860
2861    /// Creates a new [`MemoryTypeBuilder`] to configure all the various knobs
2862    /// of the final memory type being created.
2863    ///
2864    /// This is a convenience function for [`MemoryTypeBuilder::new`].
2865    pub fn builder() -> MemoryTypeBuilder {
2866        MemoryTypeBuilder::new()
2867    }
2868
2869    /// Returns whether this is a 64-bit memory or not.
2870    ///
2871    /// Note that 64-bit memories are part of the memory64 proposal for
2872    /// WebAssembly which is not standardized yet.
2873    pub fn is_64(&self) -> bool {
2874        matches!(self.ty.idx_type, IndexType::I64)
2875    }
2876
2877    /// Returns whether this is a shared memory or not.
2878    ///
2879    /// Note that shared memories are part of the threads proposal for
2880    /// WebAssembly which is not standardized yet.
2881    pub fn is_shared(&self) -> bool {
2882        self.ty.shared
2883    }
2884
2885    /// Returns minimum number of WebAssembly pages this memory must have.
2886    ///
2887    /// Note that the return value, while a `u64`, will always fit into a `u32`
2888    /// for 32-bit memories.
2889    pub fn minimum(&self) -> u64 {
2890        self.ty.limits.min
2891    }
2892
2893    /// Returns the optionally-specified maximum number of pages this memory
2894    /// can have.
2895    ///
2896    /// If this returns `None` then the memory is not limited in size.
2897    ///
2898    /// Note that the return value, while a `u64`, will always fit into a `u32`
2899    /// for 32-bit memories.
2900    pub fn maximum(&self) -> Option<u64> {
2901        self.ty.limits.max
2902    }
2903
2904    /// This memory's page size, in bytes.
2905    pub fn page_size(&self) -> u64 {
2906        self.ty.page_size()
2907    }
2908
2909    /// The log2 of this memory's page size, in bytes.
2910    pub fn page_size_log2(&self) -> u8 {
2911        self.ty.page_size_log2
2912    }
2913
2914    pub(crate) fn from_wasmtime_memory(memory: &Memory) -> MemoryType {
2915        MemoryType { ty: *memory }
2916    }
2917
2918    pub(crate) fn wasmtime_memory(&self) -> &Memory {
2919        &self.ty
2920    }
2921}
2922
2923// Import Types
2924
2925/// A descriptor for an imported value into a wasm module.
2926///
2927/// This type is primarily accessed from the
2928/// [`Module::imports`](crate::Module::imports) API. Each [`ImportType`]
2929/// describes an import into the wasm module with the module/name that it's
2930/// imported from as well as the type of item that's being imported.
2931#[derive(Clone)]
2932pub struct ImportType<'module> {
2933    /// The module of the import.
2934    module: &'module str,
2935
2936    /// The field of the import.
2937    name: &'module str,
2938
2939    /// The type of the import.
2940    ty: EntityType,
2941    types: &'module ModuleTypes,
2942    engine: &'module Engine,
2943}
2944
2945impl<'module> ImportType<'module> {
2946    /// Creates a new import descriptor which comes from `module` and `name` and
2947    /// is of type `ty`.
2948    pub(crate) fn new(
2949        module: &'module str,
2950        name: &'module str,
2951        ty: EntityType,
2952        types: &'module ModuleTypes,
2953        engine: &'module Engine,
2954    ) -> ImportType<'module> {
2955        assert!(ty.is_canonicalized_for_runtime_usage());
2956        ImportType {
2957            module,
2958            name,
2959            ty,
2960            types,
2961            engine,
2962        }
2963    }
2964
2965    /// Returns the module name that this import is expected to come from.
2966    pub fn module(&self) -> &'module str {
2967        self.module
2968    }
2969
2970    /// Returns the field name of the module that this import is expected to
2971    /// come from.
2972    pub fn name(&self) -> &'module str {
2973        self.name
2974    }
2975
2976    /// Returns the expected type of this import.
2977    pub fn ty(&self) -> ExternType {
2978        ExternType::from_wasmtime(self.engine, self.types, &self.ty)
2979    }
2980}
2981
2982impl<'module> fmt::Debug for ImportType<'module> {
2983    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2984        f.debug_struct("ImportType")
2985            .field("module", &self.module())
2986            .field("name", &self.name())
2987            .field("ty", &self.ty())
2988            .finish()
2989    }
2990}
2991
2992// Export Types
2993
2994/// A descriptor for an exported WebAssembly value.
2995///
2996/// This type is primarily accessed from the
2997/// [`Module::exports`](crate::Module::exports) accessor and describes what
2998/// names are exported from a wasm module and the type of the item that is
2999/// exported.
3000#[derive(Clone)]
3001pub struct ExportType<'module> {
3002    /// The name of the export.
3003    name: &'module str,
3004
3005    /// The type of the export.
3006    ty: EntityType,
3007    types: &'module ModuleTypes,
3008    engine: &'module Engine,
3009}
3010
3011impl<'module> ExportType<'module> {
3012    /// Creates a new export which is exported with the given `name` and has the
3013    /// given `ty`.
3014    pub(crate) fn new(
3015        name: &'module str,
3016        ty: EntityType,
3017        types: &'module ModuleTypes,
3018        engine: &'module Engine,
3019    ) -> ExportType<'module> {
3020        ExportType {
3021            name,
3022            ty,
3023            types,
3024            engine,
3025        }
3026    }
3027
3028    /// Returns the name by which this export is known.
3029    pub fn name(&self) -> &'module str {
3030        self.name
3031    }
3032
3033    /// Returns the type of this export.
3034    pub fn ty(&self) -> ExternType {
3035        ExternType::from_wasmtime(self.engine, self.types, &self.ty)
3036    }
3037}
3038
3039impl<'module> fmt::Debug for ExportType<'module> {
3040    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3041        f.debug_struct("ExportType")
3042            .field("name", &self.name().to_owned())
3043            .field("ty", &self.ty())
3044            .finish()
3045    }
3046}