Skip to main content

wasmtime/runtime/
linker.rs

1use crate::error::OutOfMemory;
2use crate::func::HostFunc;
3use crate::instance::InstancePre;
4use crate::store::StoreOpaque;
5use crate::{
6    AsContext, AsContextMut, Caller, Engine, Extern, ExternType, Func, FuncType, ImportType,
7    Instance, IntoFunc, Module, Result, StoreContextMut, Val, ValRaw, prelude::*,
8};
9use alloc::sync::Arc;
10use core::fmt::{self, Debug};
11#[cfg(feature = "async")]
12use core::future::Future;
13use core::marker;
14use core::mem::MaybeUninit;
15use log::warn;
16use wasmtime_environ::{Atom, StringPool};
17
18/// Structure used to link wasm modules/instances together.
19///
20/// This structure is used to assist in instantiating a [`Module`]. A [`Linker`]
21/// is a way of performing name resolution to make instantiating a module easier
22/// than specifying positional imports to [`Instance::new`]. [`Linker`] is a
23/// name-based resolver where names are dynamically defined and then used to
24/// instantiate a [`Module`].
25///
26/// An important method is [`Linker::instantiate`] which takes a module to
27/// instantiate into the provided store. This method will automatically select
28/// all the right imports for the [`Module`] to be instantiated, and will
29/// otherwise return an error if an import isn't satisfied.
30///
31/// ## Name Resolution
32///
33/// As mentioned previously, `Linker` is a form of name resolver. It will be
34/// using the string-based names of imports on a module to attempt to select a
35/// matching item to hook up to it. This name resolution has two-levels of
36/// namespaces, a module level and a name level. Each item is defined within a
37/// module and then has its own name. This basically follows the wasm standard
38/// for modularization.
39///
40/// Names in a `Linker` cannot be defined twice, but allowing duplicates by
41/// shadowing the previous definition can be controlled with the
42/// [`Linker::allow_shadowing`] method.
43///
44/// ## Commands and Reactors
45///
46/// The [`Linker`] type provides conveniences for working with WASI Commands and
47/// Reactors through the [`Linker::module`] method. This will automatically
48/// handle instantiation and calling `_start` and such as appropriate
49/// depending on the inferred type of module.
50///
51/// ## Type parameter `T`
52///
53/// It's worth pointing out that the type parameter `T` on [`Linker<T>`] does
54/// not represent that `T` is stored within a [`Linker`]. Rather the `T` is used
55/// to ensure that linker-defined functions and stores instantiated into all use
56/// the same matching `T` as host state.
57///
58/// ## Multiple `Store`s
59///
60/// The [`Linker`] type is designed to be compatible, in some scenarios, with
61/// instantiation in multiple [`Store`]s. Specifically host-defined functions
62/// created in [`Linker`] with [`Linker::func_new`], [`Linker::func_wrap`], and
63/// their async versions are compatible to instantiate into any [`Store`]. This
64/// enables programs which want to instantiate lots of modules to create one
65/// [`Linker`] value at program start up and use that continuously for each
66/// [`Store`] created over the lifetime of the program.
67///
68/// Note that once [`Store`]-owned items, such as [`Global`], are defined within
69/// a [`Linker`] then it is no longer compatible with any [`Store`]. At that
70/// point only the [`Store`] that owns the [`Global`] can be used to instantiate
71/// modules.
72///
73/// ## Multiple `Engine`s
74///
75/// The [`Linker`] type is not compatible with usage between multiple [`Engine`]
76/// values. An [`Engine`] is provided when a [`Linker`] is created and only
77/// stores and items which originate from that [`Engine`] can be used with this
78/// [`Linker`]. If more than one [`Engine`] is used with a [`Linker`] then that
79/// may cause a panic at runtime, similar to how if a [`Func`] is used with the
80/// wrong [`Store`] that can also panic at runtime.
81///
82/// [`Store`]: crate::Store
83/// [`Global`]: crate::Global
84pub struct Linker<T> {
85    engine: Engine,
86    pool: StringPool,
87    map: TryHashMap<ImportKey, Definition>,
88    allow_shadowing: bool,
89    allow_unknown_exports: bool,
90    _marker: marker::PhantomData<fn() -> T>,
91}
92
93impl<T> Debug for Linker<T> {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        f.debug_struct("Linker").finish_non_exhaustive()
96    }
97}
98
99impl<T> Clone for Linker<T> {
100    fn clone(&self) -> Linker<T> {
101        Linker {
102            engine: self.engine.clone(),
103            pool: self.pool.clone_panic_on_oom(),
104            map: self.map.clone_panic_on_oom(),
105            allow_shadowing: self.allow_shadowing,
106            allow_unknown_exports: self.allow_unknown_exports,
107            _marker: self._marker,
108        }
109    }
110}
111
112#[derive(Copy, Clone, Hash, PartialEq, Eq)]
113struct ImportKey {
114    module: Atom,
115    name: Option<Atom>,
116}
117
118impl TryClone for ImportKey {
119    #[inline]
120    fn try_clone(&self) -> Result<Self, OutOfMemory> {
121        Ok(*self)
122    }
123}
124
125#[derive(Clone)]
126pub(crate) enum Definition {
127    Extern(Extern, DefinitionType),
128    HostFunc(Arc<HostFunc>),
129}
130
131impl TryClone for Definition {
132    fn try_clone(&self) -> core::result::Result<Self, OutOfMemory> {
133        Ok(self.clone())
134    }
135}
136
137/// This is a sort of slimmed down `ExternType` which notably doesn't have a
138/// `FuncType`, which is an allocation, and additionally retains the current
139/// size of the table/memory.
140#[derive(Clone, Copy, Debug)]
141pub(crate) enum DefinitionType {
142    Func(wasmtime_environ::VMSharedTypeIndex),
143    Global(wasmtime_environ::Global),
144    // Note that tables and memories store not only the original type
145    // information but additionally the current size of the table/memory, as
146    // this is used during linking since the min size specified in the type may
147    // no longer be the current size of the table/memory.
148    Table(wasmtime_environ::Table, u64),
149    Memory(wasmtime_environ::Memory, u64),
150    Tag(wasmtime_environ::Tag),
151}
152
153impl<T> Linker<T> {
154    /// Creates a new [`Linker`].
155    ///
156    /// The linker will define functions within the context of the `engine`
157    /// provided and can only instantiate modules for a [`Store`][crate::Store]
158    /// that is also defined within the same [`Engine`]. Usage of stores with
159    /// different [`Engine`]s may cause a panic when used with this [`Linker`].
160    pub fn new(engine: &Engine) -> Linker<T> {
161        Linker {
162            engine: engine.clone(),
163            map: TryHashMap::new(),
164            pool: StringPool::new(),
165            allow_shadowing: false,
166            allow_unknown_exports: false,
167            _marker: marker::PhantomData,
168        }
169    }
170
171    /// Returns the [`Engine`] this is connected to.
172    pub fn engine(&self) -> &Engine {
173        &self.engine
174    }
175
176    /// Configures whether this [`Linker`] will shadow previous duplicate
177    /// definitions of the same signature.
178    ///
179    /// By default a [`Linker`] will disallow duplicate definitions of the same
180    /// signature. This method, however, can be used to instead allow duplicates
181    /// and have the latest definition take precedence when linking modules.
182    ///
183    /// # Examples
184    ///
185    /// ```
186    /// # use wasmtime::*;
187    /// # fn main() -> Result<()> {
188    /// # let engine = Engine::default();
189    /// let mut linker = Linker::<()>::new(&engine);
190    /// linker.func_wrap("", "", || {})?;
191    ///
192    /// // by default, duplicates are disallowed
193    /// assert!(linker.func_wrap("", "", || {}).is_err());
194    ///
195    /// // but shadowing can be configured to be allowed as well
196    /// linker.allow_shadowing(true);
197    /// linker.func_wrap("", "", || {})?;
198    /// # Ok(())
199    /// # }
200    /// ```
201    pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
202        self.allow_shadowing = allow;
203        self
204    }
205
206    /// Configures whether this [`Linker`] will allow unknown exports from
207    /// command modules.
208    ///
209    /// By default a [`Linker`] will error when unknown exports are encountered
210    /// in a command module while using [`Linker::module`].
211    ///
212    /// This method can be used to allow unknown exports from command modules.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// # use wasmtime::*;
218    /// # fn main() -> Result<()> {
219    /// # let engine = Engine::default();
220    /// # let module = Module::new(&engine, "(module)")?;
221    /// # let mut store = Store::new(&engine, ());
222    /// let mut linker = Linker::new(&engine);
223    /// linker.allow_unknown_exports(true);
224    /// linker.module(&mut store, "mod", &module)?;
225    /// # Ok(())
226    /// # }
227    /// ```
228    pub fn allow_unknown_exports(&mut self, allow: bool) -> &mut Self {
229        self.allow_unknown_exports = allow;
230        self
231    }
232
233    /// Implement any imports of the given [`Module`] with a function which traps.
234    ///
235    /// By default a [`Linker`] will error when unknown imports are encountered
236    /// in a command module while using [`Linker::module`].
237    ///
238    /// This method can be used to allow unknown imports from command modules.
239    ///
240    /// # Examples
241    ///
242    /// ```
243    /// # use wasmtime::*;
244    /// # fn main() -> Result<()> {
245    /// # let engine = Engine::default();
246    /// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
247    /// # let mut store = Store::new(&engine, ());
248    /// let mut linker = Linker::new(&engine);
249    /// linker.define_unknown_imports_as_traps(&module)?;
250    /// linker.instantiate(&mut store, &module)?;
251    /// # Ok(())
252    /// # }
253    /// ```
254    pub fn define_unknown_imports_as_traps(&mut self, module: &Module) -> Result<()>
255    where
256        T: 'static,
257    {
258        for import in module.imports() {
259            if let Err(import_err) = self._get_by_import(&import) {
260                if let ExternType::Func(func_ty) = import_err.ty() {
261                    self.func_new(import.module(), import.name(), func_ty, move |_, _, _| {
262                        bail!(import_err.clone());
263                    })?;
264                }
265            }
266        }
267        Ok(())
268    }
269
270    /// Implement any function imports of the [`Module`] with a function that
271    /// ignores its arguments and returns default values.
272    ///
273    /// Default values are either zero or null, depending on the value type.
274    ///
275    /// This method can be used to allow unknown imports from command modules.
276    ///
277    /// # Example
278    ///
279    /// ```
280    /// # use wasmtime::*;
281    /// # fn main() -> Result<()> {
282    /// # let engine = Engine::default();
283    /// # let module = Module::new(&engine, "(module (import \"unknown\" \"import\" (func)))")?;
284    /// # let mut store = Store::new(&engine, ());
285    /// let mut linker = Linker::new(&engine);
286    /// linker.define_unknown_imports_as_default_values(&mut store, &module)?;
287    /// linker.instantiate(&mut store, &module)?;
288    /// # Ok(())
289    /// # }
290    /// ```
291    pub fn define_unknown_imports_as_default_values(
292        &mut self,
293        mut store: impl AsContextMut<Data = T>,
294        module: &Module,
295    ) -> Result<()>
296    where
297        T: 'static,
298    {
299        let mut store = store.as_context_mut();
300        for import in module.imports() {
301            if let Err(import_err) = self._get_by_import(&import) {
302                let default_extern =
303                    import_err.ty().default_value(&mut store).with_context(|| {
304                        format_err!(
305                            "no default value exists for `{}::{}` with type `{:?}`",
306                            import.module(),
307                            import.name(),
308                            import_err.ty(),
309                        )
310                    })?;
311                self.define(
312                    store.as_context(),
313                    import.module(),
314                    import.name(),
315                    default_extern,
316                )?;
317            }
318        }
319        Ok(())
320    }
321
322    /// Defines a new item in this [`Linker`].
323    ///
324    /// This method will add a new definition, by name, to this instance of
325    /// [`Linker`]. The `module` and `name` provided are what to name the
326    /// `item`.
327    ///
328    /// # Errors
329    ///
330    /// Returns an error if the `module` and `name` already identify an item
331    /// of the same type as the `item` provided and if shadowing is disallowed.
332    /// For more information see the documentation on [`Linker`].
333    ///
334    /// # Examples
335    ///
336    /// ```
337    /// # use wasmtime::*;
338    /// # fn main() -> Result<()> {
339    /// # let engine = Engine::default();
340    /// # let mut store = Store::new(&engine, ());
341    /// let mut linker = Linker::new(&engine);
342    /// let ty = GlobalType::new(ValType::I32, Mutability::Const);
343    /// let global = Global::new(&mut store, ty, Val::I32(0x1234))?;
344    /// linker.define(&store, "host", "offset", global)?;
345    ///
346    /// let wat = r#"
347    ///     (module
348    ///         (import "host" "offset" (global i32))
349    ///         (memory 1)
350    ///         (data (global.get 0) "foo")
351    ///     )
352    /// "#;
353    /// let module = Module::new(&engine, wat)?;
354    /// linker.instantiate(&mut store, &module)?;
355    /// # Ok(())
356    /// # }
357    /// ```
358    pub fn define(
359        &mut self,
360        store: impl AsContext<Data = T>,
361        module: &str,
362        name: &str,
363        item: impl Into<Extern>,
364    ) -> Result<&mut Self>
365    where
366        T: 'static,
367    {
368        let store = store.as_context();
369        let key = self.import_key(module, Some(name))?;
370        self.insert(key, Definition::new(store.0, item.into()))?;
371        Ok(self)
372    }
373
374    /// Same as [`Linker::define`], except only the name of the import is
375    /// provided, not a module name as well.
376    ///
377    /// This is only relevant when working with the module linking proposal
378    /// where one-level names are allowed (in addition to two-level names).
379    /// Otherwise this method need not be used.
380    pub fn define_name(
381        &mut self,
382        store: impl AsContext<Data = T>,
383        name: &str,
384        item: impl Into<Extern>,
385    ) -> Result<&mut Self>
386    where
387        T: 'static,
388    {
389        let store = store.as_context();
390        let key = self.import_key(name, None)?;
391        self.insert(key, Definition::new(store.0, item.into()))?;
392        Ok(self)
393    }
394
395    fn func_insert(&mut self, module: &str, name: &str, func: HostFunc) -> Result<&mut Self>
396    where
397        T: 'static,
398    {
399        let key = self.import_key(module, Some(name))?;
400        self.insert(key, Definition::HostFunc(try_new(func)?))?;
401        Ok(self)
402    }
403
404    /// Creates a [`Func::new`]-style function named in this linker.
405    ///
406    /// For more information see [`Linker::func_wrap`].
407    ///
408    /// # Panics
409    ///
410    /// Panics if the given function type is not associated with the same engine
411    /// as this linker.
412    pub fn func_new(
413        &mut self,
414        module: &str,
415        name: &str,
416        ty: FuncType,
417        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static,
418    ) -> Result<&mut Self>
419    where
420        T: 'static,
421    {
422        self.func_insert(module, name, HostFunc::new(&self.engine, ty, func)?)
423    }
424
425    /// Creates a [`Func::new_unchecked`]-style function named in this linker.
426    ///
427    /// For more information see [`Linker::func_wrap`].
428    ///
429    /// # Panics
430    ///
431    /// Panics if the given function type is not associated with the same engine
432    /// as this linker.
433    ///
434    /// # Safety
435    ///
436    /// See [`Func::new_unchecked`] for more safety information.
437    pub unsafe fn func_new_unchecked(
438        &mut self,
439        module: &str,
440        name: &str,
441        ty: FuncType,
442        func: impl Fn(Caller<'_, T>, &mut [MaybeUninit<ValRaw>]) -> Result<()> + Send + Sync + 'static,
443    ) -> Result<&mut Self>
444    where
445        T: 'static,
446    {
447        // SAFETY: the contract of this function is the same as `new_unchecked`.
448        let func = unsafe { HostFunc::new_unchecked(&self.engine, ty, func)? };
449        self.func_insert(module, name, func)
450    }
451
452    /// Creates a [`Func::new_async`]-style function named in this linker.
453    ///
454    /// For more information see [`Linker::func_wrap`].
455    ///
456    /// # Panics
457    ///
458    /// This method panics in the following situations:
459    ///
460    /// * If the given function type is not associated with the same engine as
461    ///   this linker.
462    #[cfg(feature = "async")]
463    pub fn func_new_async<F>(
464        &mut self,
465        module: &str,
466        name: &str,
467        ty: FuncType,
468        func: F,
469    ) -> Result<&mut Self>
470    where
471        F: for<'a> Fn(
472                Caller<'a, T>,
473                &'a [Val],
474                &'a mut [Val],
475            ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
476            + Send
477            + Sync
478            + 'static,
479        T: Send + 'static,
480    {
481        self.func_insert(module, name, HostFunc::new_async(&self.engine, ty, func)?)
482    }
483
484    /// Define a host function within this linker.
485    ///
486    /// For information about how the host function operates, see
487    /// [`Func::wrap`]. That includes information about translating Rust types
488    /// to WebAssembly native types.
489    ///
490    /// This method creates a host-provided function in this linker under the
491    /// provided name. This method is distinct in its capability to create a
492    /// [`Store`](crate::Store)-independent function. This means that the
493    /// function defined here can be used to instantiate instances in multiple
494    /// different stores, or in other words the function can be loaded into
495    /// different stores.
496    ///
497    /// Note that the capability mentioned here applies to all other
498    /// host-function-defining-methods on [`Linker`] as well. All of them can be
499    /// used to create instances of [`Func`] within multiple stores. In a
500    /// multithreaded program, for example, this means that the host functions
501    /// could be called concurrently if different stores are executing on
502    /// different threads.
503    ///
504    /// # Errors
505    ///
506    /// Returns an error if the `module` and `name` already identify an item
507    /// of the same type as the `item` provided and if shadowing is disallowed.
508    /// For more information see the documentation on [`Linker`].
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// # use wasmtime::*;
514    /// # fn main() -> Result<()> {
515    /// # let engine = Engine::default();
516    /// let mut linker = Linker::new(&engine);
517    /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
518    /// linker.func_wrap("host", "log_i32", |x: i32| println!("{}", x))?;
519    /// linker.func_wrap("host", "log_str", |caller: Caller<'_, ()>, ptr: i32, len: i32| {
520    ///     // ...
521    /// })?;
522    ///
523    /// let wat = r#"
524    ///     (module
525    ///         (import "host" "double" (func (param i32) (result i32)))
526    ///         (import "host" "log_i32" (func (param i32)))
527    ///         (import "host" "log_str" (func (param i32 i32)))
528    ///     )
529    /// "#;
530    /// let module = Module::new(&engine, wat)?;
531    ///
532    /// // instantiate in multiple different stores
533    /// for _ in 0..10 {
534    ///     let mut store = Store::new(&engine, ());
535    ///     linker.instantiate(&mut store, &module)?;
536    /// }
537    /// # Ok(())
538    /// # }
539    /// ```
540    pub fn func_wrap<Params, Args>(
541        &mut self,
542        module: &str,
543        name: &str,
544        func: impl IntoFunc<T, Params, Args>,
545    ) -> Result<&mut Self>
546    where
547        T: 'static,
548    {
549        self.func_insert(module, name, func.into_func(&self.engine)?)
550    }
551
552    /// Asynchronous analog of [`Linker::func_wrap`].
553    #[cfg(feature = "async")]
554    pub fn func_wrap_async<F, Params: crate::WasmTyList, Args: crate::WasmRet>(
555        &mut self,
556        module: &str,
557        name: &str,
558        func: F,
559    ) -> Result<&mut Self>
560    where
561        F: for<'a> Fn(Caller<'a, T>, Params) -> Box<dyn Future<Output = Args> + Send + 'a>
562            + Send
563            + Sync
564            + 'static,
565        T: Send + 'static,
566    {
567        self.func_insert(module, name, HostFunc::wrap_async(&self.engine, func)?)
568    }
569
570    /// Convenience wrapper to define an entire [`Instance`] in this linker.
571    ///
572    /// This function is a convenience wrapper around [`Linker::define`] which
573    /// will define all exports on `instance` into this linker. The module name
574    /// for each export is `module_name`, and the name for each export is the
575    /// name in the instance itself.
576    ///
577    /// Note that when this API is used the [`Linker`] is no longer compatible
578    /// with multi-[`Store`][crate::Store] instantiation because the items
579    /// defined within this store will belong to the `store` provided, and only
580    /// the `store` provided.
581    ///
582    /// # Errors
583    ///
584    /// Returns an error if the any item is redefined twice in this linker (for
585    /// example the same `module_name` was already defined) and shadowing is
586    /// disallowed, or if `instance` comes from a different
587    /// [`Store`](crate::Store) than this [`Linker`] originally was created
588    /// with.
589    ///
590    /// # Panics
591    ///
592    /// Panics if `instance` does not belong to `store`.
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// # use wasmtime::*;
598    /// # fn main() -> Result<()> {
599    /// # let engine = Engine::default();
600    /// # let mut store = Store::new(&engine, ());
601    /// let mut linker = Linker::new(&engine);
602    ///
603    /// // Instantiate a small instance...
604    /// let wat = r#"(module (func (export "run") ))"#;
605    /// let module = Module::new(&engine, wat)?;
606    /// let instance = linker.instantiate(&mut store, &module)?;
607    ///
608    /// // ... and inform the linker that the name of this instance is
609    /// // `instance1`. This defines the `instance1::run` name for our next
610    /// // module to use.
611    /// linker.instance(&mut store, "instance1", instance)?;
612    ///
613    /// let wat = r#"
614    ///     (module
615    ///         (import "instance1" "run" (func $instance1_run))
616    ///         (func (export "run")
617    ///             call $instance1_run
618    ///         )
619    ///     )
620    /// "#;
621    /// let module = Module::new(&engine, wat)?;
622    /// let instance = linker.instantiate(&mut store, &module)?;
623    /// # Ok(())
624    /// # }
625    /// ```
626    pub fn instance(
627        &mut self,
628        mut store: impl AsContextMut<Data = T>,
629        module_name: &str,
630        instance: Instance,
631    ) -> Result<&mut Self>
632    where
633        T: 'static,
634    {
635        let mut store = store.as_context_mut();
636        let exports: TryVec<_> = instance
637            .exports(&mut store)
638            .map(|e| {
639                Ok((
640                    self.import_key(module_name, Some(e.name()))?,
641                    e.into_extern(),
642                ))
643            })
644            .try_collect::<_, Error>()?;
645        for (key, export) in exports {
646            self.insert(key, Definition::new(store.0, export))?;
647        }
648        Ok(self)
649    }
650
651    /// Define automatic instantiations of a [`Module`] in this linker.
652    ///
653    /// This automatically handles [Commands and Reactors] instantiation and
654    /// initialization.
655    ///
656    /// Exported functions of a Command module may be called directly, however
657    /// instead of having a single instance which is reused for each call,
658    /// each call creates a new instance, which lives for the duration of the
659    /// call. The imports of the Command are resolved once, and reused for
660    /// each instantiation, so all dependencies need to be present at the time
661    /// when `Linker::module` is called.
662    ///
663    /// For Reactors, a single instance is created, and an initialization
664    /// function is called, and then its exports may be called.
665    ///
666    /// Ordinary modules which don't declare themselves to be either Commands
667    /// or Reactors are treated as Reactors without any initialization calls.
668    ///
669    /// [Commands and Reactors]: https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi
670    ///
671    /// # Errors
672    ///
673    /// Returns an error if the any item is redefined twice in this linker (for
674    /// example the same `module_name` was already defined) and shadowing is
675    /// disallowed, if `instance` comes from a different
676    /// [`Store`](crate::Store) than this [`Linker`] originally was created
677    /// with, or if a Reactor initialization function traps.
678    ///
679    /// # Panics
680    ///
681    /// Panics if any item used to instantiate the provided [`Module`] is not
682    /// owned by `store`, or if the `store` provided comes from a different
683    /// [`Engine`] than this [`Linker`].
684    ///
685    /// # Examples
686    ///
687    /// ```
688    /// # use wasmtime::*;
689    /// # fn main() -> Result<()> {
690    /// # let engine = Engine::default();
691    /// # let mut store = Store::new(&engine, ());
692    /// let mut linker = Linker::new(&engine);
693    ///
694    /// // Instantiate a small instance and inform the linker that the name of
695    /// // this instance is `instance1`. This defines the `instance1::run` name
696    /// // for our next module to use.
697    /// let wat = r#"(module (func (export "run") ))"#;
698    /// let module = Module::new(&engine, wat)?;
699    /// linker.module(&mut store, "instance1", &module)?;
700    ///
701    /// let wat = r#"
702    ///     (module
703    ///         (import "instance1" "run" (func $instance1_run))
704    ///         (func (export "run")
705    ///             call $instance1_run
706    ///         )
707    ///     )
708    /// "#;
709    /// let module = Module::new(&engine, wat)?;
710    /// let instance = linker.instantiate(&mut store, &module)?;
711    /// # Ok(())
712    /// # }
713    /// ```
714    ///
715    /// For a Command, a new instance is created for each call.
716    ///
717    /// ```
718    /// # use wasmtime::*;
719    /// # fn main() -> Result<()> {
720    /// # let engine = Engine::default();
721    /// # let mut store = Store::new(&engine, ());
722    /// let mut linker = Linker::new(&engine);
723    ///
724    /// // Create a Command that attempts to count the number of times it is run, but is
725    /// // foiled by each call getting a new instance.
726    /// let wat = r#"
727    ///     (module
728    ///         (global $counter (mut i32) (i32.const 0))
729    ///         (func (export "_start")
730    ///             (global.set $counter (i32.add (global.get $counter) (i32.const 1)))
731    ///         )
732    ///         (func (export "read_counter") (result i32)
733    ///             (global.get $counter)
734    ///         )
735    ///     )
736    /// "#;
737    /// let module = Module::new(&engine, wat)?;
738    /// linker.module(&mut store, "commander", &module)?;
739    /// let run = linker.get_default(&mut store, "")?
740    ///     .typed::<(), ()>(&store)?
741    ///     .clone();
742    /// run.call(&mut store, ())?;
743    /// run.call(&mut store, ())?;
744    /// run.call(&mut store, ())?;
745    ///
746    /// let wat = r#"
747    ///     (module
748    ///         (import "commander" "_start" (func $commander_start))
749    ///         (import "commander" "read_counter" (func $commander_read_counter (result i32)))
750    ///         (func (export "run") (result i32)
751    ///             call $commander_start
752    ///             call $commander_start
753    ///             call $commander_start
754    ///             call $commander_read_counter
755    ///         )
756    ///     )
757    /// "#;
758    /// let module = Module::new(&engine, wat)?;
759    /// linker.module(&mut store, "", &module)?;
760    /// let run = linker.get(&mut store, "", "run").unwrap().into_func().unwrap();
761    /// let count = run.typed::<(), i32>(&store)?.call(&mut store, ())?;
762    /// assert_eq!(count, 0, "a Command should get a fresh instance on each invocation");
763    ///
764    /// # Ok(())
765    /// # }
766    /// ```
767    pub fn module(
768        &mut self,
769        mut store: impl AsContextMut<Data = T>,
770        module_name: &str,
771        module: &Module,
772    ) -> Result<&mut Self>
773    where
774        T: 'static,
775    {
776        // NB: this is intended to function the same as `Linker::module_async`,
777        // they should be kept in sync.
778
779        // This assert isn't strictly necessary since it'll bottom out in the
780        // `HostFunc::to_func` method anyway. This is placed earlier for this
781        // function though to prevent the functions created here from delaying
782        // the panic until they're called.
783        assert!(
784            Engine::same(&self.engine, store.as_context().engine()),
785            "different engines for this linker and the store provided"
786        );
787        match ModuleKind::categorize(module)? {
788            ModuleKind::Command => {
789                self.command(
790                    store,
791                    module_name,
792                    module,
793                    |store, func_ty, export_name, instance_pre| {
794                        Func::new(
795                            store,
796                            func_ty.clone(),
797                            move |mut caller, params, results| {
798                                // Create a new instance for this command execution.
799                                let instance = instance_pre.instantiate(&mut caller)?;
800
801                                // `unwrap()` everything here because we know the instance contains a
802                                // function export with the given name and signature because we're
803                                // iterating over the module it was instantiated from.
804                                instance
805                                    .get_export(&mut caller, &export_name)
806                                    .unwrap()
807                                    .into_func()
808                                    .unwrap()
809                                    .call(&mut caller, params, results)?;
810
811                                Ok(())
812                            },
813                        )
814                    },
815                )
816            }
817            ModuleKind::Reactor => {
818                let instance = self.instantiate(&mut store, &module)?;
819
820                if let Some(export) = instance.get_export(&mut store, "_initialize") {
821                    if let Extern::Func(func) = export {
822                        func.typed::<(), ()>(&store)
823                            .and_then(|f| f.call(&mut store, ()))
824                            .context("calling the Reactor initialization function")?;
825                    }
826                }
827
828                self.instance(store, module_name, instance)
829            }
830        }
831    }
832
833    /// Define automatic instantiations of a [`Module`] in this linker.
834    ///
835    /// This is the same as [`Linker::module`], except for async `Store`s.
836    #[cfg(feature = "async")]
837    pub async fn module_async(
838        &mut self,
839        mut store: impl AsContextMut<Data = T>,
840        module_name: &str,
841        module: &Module,
842    ) -> Result<&mut Self>
843    where
844        T: Send + 'static,
845    {
846        // NB: this is intended to function the same as `Linker::module`, they
847        // should be kept in sync.
848        assert!(
849            Engine::same(&self.engine, store.as_context().engine()),
850            "different engines for this linker and the store provided"
851        );
852        match ModuleKind::categorize(module)? {
853            ModuleKind::Command => self.command(
854                store,
855                module_name,
856                module,
857                |store, func_ty, export_name, instance_pre| {
858                    let upvars = Arc::new((instance_pre, export_name));
859                    Func::new_async(
860                        store,
861                        func_ty.clone(),
862                        move |mut caller, params, results| {
863                            let upvars = upvars.clone();
864                            Box::new(async move {
865                                let (instance_pre, export_name) = &*upvars;
866                                let instance = instance_pre.instantiate_async(&mut caller).await?;
867
868                                instance
869                                    .get_export(&mut caller, &export_name)
870                                    .unwrap()
871                                    .into_func()
872                                    .unwrap()
873                                    .call_async(&mut caller, params, results)
874                                    .await?;
875                                Ok(())
876                            })
877                        },
878                    )
879                },
880            ),
881            ModuleKind::Reactor => {
882                let instance = self.instantiate_async(&mut store, &module).await?;
883
884                if let Some(export) = instance.get_export(&mut store, "_initialize") {
885                    if let Extern::Func(func) = export {
886                        let func = func
887                            .typed::<(), ()>(&store)
888                            .context("loading the Reactor initialization function")?;
889                        func.call_async(&mut store, ())
890                            .await
891                            .context("calling the Reactor initialization function")?;
892                    }
893                }
894
895                self.instance(store, module_name, instance)
896            }
897        }
898    }
899
900    fn command(
901        &mut self,
902        mut store: impl AsContextMut<Data = T>,
903        module_name: &str,
904        module: &Module,
905        mk_func: impl Fn(&mut StoreContextMut<T>, &FuncType, String, InstancePre<T>) -> Func,
906    ) -> Result<&mut Self>
907    where
908        T: 'static,
909    {
910        let mut store = store.as_context_mut();
911        for export in module.exports() {
912            if let Some(func_ty) = export.ty().func() {
913                let instance_pre = self.instantiate_pre(module)?;
914                let export_name = export.name().to_owned();
915                let func = mk_func(&mut store, func_ty, export_name, instance_pre);
916                let key = self.import_key(module_name, Some(export.name()))?;
917                self.insert(key, Definition::new(store.0, func.into()))?;
918            } else if export.name() == "memory" && export.ty().memory().is_some() {
919                // Allow an exported "memory" memory for now.
920            } else if export.name() == "__indirect_function_table" && export.ty().table().is_some()
921            {
922                // Allow an exported "__indirect_function_table" table for now.
923            } else if export.name() == "table" && export.ty().table().is_some() {
924                // Allow an exported "table" table for now.
925            } else if export.name() == "__data_end" && export.ty().global().is_some() {
926                // Allow an exported "__data_end" memory for compatibility with toolchains
927                // which use --export-dynamic, which unfortunately doesn't work the way
928                // we want it to.
929                warn!("command module exporting '__data_end' is deprecated");
930            } else if export.name() == "__heap_base" && export.ty().global().is_some() {
931                // Allow an exported "__data_end" memory for compatibility with toolchains
932                // which use --export-dynamic, which unfortunately doesn't work the way
933                // we want it to.
934                warn!("command module exporting '__heap_base' is deprecated");
935            } else if export.name() == "__dso_handle" && export.ty().global().is_some() {
936                // Allow an exported "__dso_handle" memory for compatibility with toolchains
937                // which use --export-dynamic, which unfortunately doesn't work the way
938                // we want it to.
939                warn!("command module exporting '__dso_handle' is deprecated")
940            } else if export.name() == "__rtti_base" && export.ty().global().is_some() {
941                // Allow an exported "__rtti_base" memory for compatibility with
942                // AssemblyScript.
943                warn!(
944                    "command module exporting '__rtti_base' is deprecated; pass `--runtime half` to the AssemblyScript compiler"
945                );
946            } else if !self.allow_unknown_exports {
947                bail!("command export '{}' is not a function", export.name());
948            }
949        }
950
951        Ok(self)
952    }
953
954    /// Aliases one item's name as another.
955    ///
956    /// This method will alias an item with the specified `module` and `name`
957    /// under a new name of `as_module` and `as_name`.
958    ///
959    /// # Errors
960    ///
961    /// Returns an error if any shadowing violations happen while defining new
962    /// items, or if the original item wasn't defined.
963    pub fn alias(
964        &mut self,
965        module: &str,
966        name: &str,
967        as_module: &str,
968        as_name: &str,
969    ) -> Result<&mut Self> {
970        let src = self.import_key(module, Some(name))?;
971        let dst = self.import_key(as_module, Some(as_name))?;
972        match self.map.get(&src).cloned() {
973            Some(item) => self.insert(dst, item)?,
974            None => bail!("no item named `{module}::{name}` defined"),
975        }
976        Ok(self)
977    }
978
979    /// Aliases one module's name as another.
980    ///
981    /// This method will alias all currently defined under `module` to also be
982    /// defined under the name `as_module` too.
983    ///
984    /// # Errors
985    ///
986    /// Returns an error if any shadowing violations happen while defining new
987    /// items.
988    pub fn alias_module(&mut self, module: &str, as_module: &str) -> Result<()> {
989        let module = self.pool.insert(module)?;
990        let as_module = self.pool.insert(as_module)?;
991        let items: TryVec<_> = self
992            .map
993            .iter()
994            .filter(|(key, _def)| key.module == module)
995            .map(|(key, def)| Ok((key.name, def.clone())))
996            .try_collect::<_, Error>()?;
997        for (name, item) in items {
998            self.insert(
999                ImportKey {
1000                    module: as_module,
1001                    name,
1002                },
1003                item,
1004            )?;
1005        }
1006        Ok(())
1007    }
1008
1009    fn insert(&mut self, key: ImportKey, item: Definition) -> Result<()> {
1010        if !self.allow_shadowing && self.map.contains_key(&key) {
1011            let module = &self.pool[key.module];
1012            match key.name.and_then(|n| self.pool.get(n)) {
1013                Some(name) => bail!("import of `{module}::{name}` defined twice"),
1014                None => bail!("import of `{module}` defined twice"),
1015            }
1016        }
1017
1018        self.map.insert(key, item)?;
1019        Ok(())
1020    }
1021
1022    fn import_key(&mut self, module: &str, name: Option<&str>) -> Result<ImportKey, OutOfMemory> {
1023        Ok(ImportKey {
1024            module: self.pool.insert(module)?,
1025            name: name.map(|name| self.pool.insert(name)).transpose()?,
1026        })
1027    }
1028
1029    /// Attempts to instantiate the `module` provided.
1030    ///
1031    /// This method will attempt to assemble a list of imports that correspond
1032    /// to the imports required by the [`Module`] provided. This list
1033    /// of imports is then passed to [`Instance::new`] to continue the
1034    /// instantiation process.
1035    ///
1036    /// Each import of `module` will be looked up in this [`Linker`] and must
1037    /// have previously been defined. If it was previously defined with an
1038    /// incorrect signature or if it was not previously defined then an error
1039    /// will be returned because the import can not be satisfied.
1040    ///
1041    /// Per the WebAssembly spec, instantiation includes running the module's
1042    /// start function, if it has one (not to be confused with the `_start`
1043    /// function, which is not run).
1044    ///
1045    /// # Errors
1046    ///
1047    /// This method can fail because an import may not be found, or because
1048    /// instantiation itself may fail. For information on instantiation
1049    /// failures see [`Instance::new`]. If an import is not found, the error
1050    /// may be downcast to an [`UnknownImportError`].
1051    ///
1052    ///
1053    /// # Panics
1054    ///
1055    /// Panics if any item used to instantiate `module` is not owned by
1056    /// `store`. Additionally this will panic if the [`Engine`] that the `store`
1057    /// belongs to is different than this [`Linker`].
1058    ///
1059    /// # Examples
1060    ///
1061    /// ```
1062    /// # use wasmtime::*;
1063    /// # fn main() -> Result<()> {
1064    /// # let engine = Engine::default();
1065    /// # let mut store = Store::new(&engine, ());
1066    /// let mut linker = Linker::new(&engine);
1067    /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
1068    ///
1069    /// let wat = r#"
1070    ///     (module
1071    ///         (import "host" "double" (func (param i32) (result i32)))
1072    ///     )
1073    /// "#;
1074    /// let module = Module::new(&engine, wat)?;
1075    /// linker.instantiate(&mut store, &module)?;
1076    /// # Ok(())
1077    /// # }
1078    /// ```
1079    pub fn instantiate(
1080        &self,
1081        mut store: impl AsContextMut<Data = T>,
1082        module: &Module,
1083    ) -> Result<Instance>
1084    where
1085        T: 'static,
1086    {
1087        self._instantiate_pre(module, Some(store.as_context_mut().0))?
1088            .instantiate(store)
1089    }
1090
1091    /// Attempts to instantiate the `module` provided. This is the same as
1092    /// [`Linker::instantiate`], except for async `Store`s.
1093    #[cfg(feature = "async")]
1094    pub async fn instantiate_async(
1095        &self,
1096        mut store: impl AsContextMut<Data = T>,
1097        module: &Module,
1098    ) -> Result<Instance>
1099    where
1100        T: Send + 'static,
1101    {
1102        self._instantiate_pre(module, Some(store.as_context_mut().0))?
1103            .instantiate_async(store)
1104            .await
1105    }
1106
1107    /// Performs all checks necessary for instantiating `module` with this
1108    /// linker, except that instantiation doesn't actually finish.
1109    ///
1110    /// This method is used for front-loading type-checking information as well
1111    /// as collecting the imports to use to instantiate a module with. The
1112    /// returned [`InstancePre`] represents a ready-to-be-instantiated module,
1113    /// which can also be instantiated multiple times if desired.
1114    ///
1115    /// # Errors
1116    ///
1117    /// Returns an error which may be downcast to an [`UnknownImportError`] if
1118    /// the module has any unresolvable imports.
1119    ///
1120    /// # Examples
1121    ///
1122    /// ```
1123    /// # use wasmtime::*;
1124    /// # fn main() -> Result<()> {
1125    /// # let engine = Engine::default();
1126    /// # let mut store = Store::new(&engine, ());
1127    /// let mut linker = Linker::new(&engine);
1128    /// linker.func_wrap("host", "double", |x: i32| x * 2)?;
1129    ///
1130    /// let wat = r#"
1131    ///     (module
1132    ///         (import "host" "double" (func (param i32) (result i32)))
1133    ///     )
1134    /// "#;
1135    /// let module = Module::new(&engine, wat)?;
1136    /// let instance_pre = linker.instantiate_pre(&module)?;
1137    ///
1138    /// // Finish instantiation after the type-checking has all completed...
1139    /// let instance = instance_pre.instantiate(&mut store)?;
1140    ///
1141    /// // ... and we can even continue to keep instantiating if desired!
1142    /// instance_pre.instantiate(&mut store)?;
1143    /// instance_pre.instantiate(&mut store)?;
1144    ///
1145    /// // Note that functions defined in a linker with `func_wrap` and similar
1146    /// // constructors are not owned by any particular `Store`, so we can also
1147    /// // instantiate our `instance_pre` in other stores because no imports
1148    /// // belong to the original store.
1149    /// let mut new_store = Store::new(&engine, ());
1150    /// instance_pre.instantiate(&mut new_store)?;
1151    /// # Ok(())
1152    /// # }
1153    /// ```
1154    pub fn instantiate_pre(&self, module: &Module) -> Result<InstancePre<T>>
1155    where
1156        T: 'static,
1157    {
1158        self._instantiate_pre(module, None)
1159    }
1160
1161    /// This is split out to optionally take a `store` so that when the
1162    /// `.instantiate` API is used we can get fresh up-to-date type information
1163    /// for memories and their current size, if necessary.
1164    ///
1165    /// Note that providing a `store` here is not required for correctness
1166    /// per-se. If one is not provided, such as the with the `instantiate_pre`
1167    /// API, then the type information used for memories and tables will reflect
1168    /// their size when inserted into the linker rather than their current size.
1169    /// This isn't expected to be much of a problem though since
1170    /// per-store-`Linker` types are likely using `.instantiate(..)` and
1171    /// per-`Engine` linkers don't have memories/tables in them.
1172    fn _instantiate_pre(
1173        &self,
1174        module: &Module,
1175        store: Option<&StoreOpaque>,
1176    ) -> Result<InstancePre<T>>
1177    where
1178        T: 'static,
1179    {
1180        let mut imports: TryVec<_> = module
1181            .imports()
1182            .map(|import| Ok(self._get_by_import(&import)?))
1183            .try_collect::<_, Error>()?;
1184        if let Some(store) = store {
1185            for import in imports.iter_mut() {
1186                import.update_size(store);
1187            }
1188        }
1189        unsafe { InstancePre::new(module, imports) }
1190    }
1191
1192    /// Returns an iterator over all items defined in this `Linker`, in
1193    /// arbitrary order.
1194    ///
1195    /// The iterator returned will yield 3-tuples where the first two elements
1196    /// are the module name and item name for the external item, and the third
1197    /// item is the item itself that is defined.
1198    ///
1199    /// Note that multiple `Extern` items may be defined for the same
1200    /// module/name pair.
1201    ///
1202    /// # Panics
1203    ///
1204    /// This function will panic if the `store` provided does not come from the
1205    /// same [`Engine`] that this linker was created with.
1206    pub fn iter<'a: 'p, 'p>(
1207        &'a self,
1208        mut store: impl AsContextMut<Data = T> + 'p,
1209    ) -> impl Iterator<Item = (&'a str, &'a str, Extern)> + 'p
1210    where
1211        T: 'static,
1212    {
1213        self.map.iter().map(move |(key, item)| {
1214            let store = store.as_context_mut();
1215            (
1216                &self.pool[key.module],
1217                &self.pool[key.name.unwrap()],
1218                // Should be safe since `T` is connecting the linker and store
1219                unsafe { item.to_extern(store.0) },
1220            )
1221        })
1222    }
1223
1224    /// Looks up a previously defined value in this [`Linker`], identified by
1225    /// the names provided.
1226    ///
1227    /// Returns `None` if this name was not previously defined in this
1228    /// [`Linker`].
1229    ///
1230    /// # Panics
1231    ///
1232    /// This function will panic if the `store` provided does not come from the
1233    /// same [`Engine`] that this linker was created with.
1234    pub fn get(
1235        &self,
1236        mut store: impl AsContextMut<Data = T>,
1237        module: &str,
1238        name: &str,
1239    ) -> Option<Extern>
1240    where
1241        T: 'static,
1242    {
1243        let store = store.as_context_mut().0;
1244        // Should be safe since `T` is connecting the linker and store
1245        Some(unsafe { self._get(module, name)?.to_extern(store) })
1246    }
1247
1248    fn _get(&self, module: &str, name: &str) -> Option<&Definition> {
1249        let key = ImportKey {
1250            module: self.pool.get_atom(module)?,
1251            name: Some(self.pool.get_atom(name)?),
1252        };
1253        self.map.get(&key)
1254    }
1255
1256    /// Looks up a value in this `Linker` which matches the `import` type
1257    /// provided.
1258    ///
1259    /// Returns `None` if no match was found.
1260    ///
1261    /// # Panics
1262    ///
1263    /// This function will panic if the `store` provided does not come from the
1264    /// same [`Engine`] that this linker was created with.
1265    pub fn get_by_import(
1266        &self,
1267        mut store: impl AsContextMut<Data = T>,
1268        import: &ImportType,
1269    ) -> Option<Extern>
1270    where
1271        T: 'static,
1272    {
1273        let store = store.as_context_mut().0;
1274        // Should be safe since `T` is connecting the linker and store
1275        Some(unsafe { self._get_by_import(import).ok()?.to_extern(store) })
1276    }
1277
1278    fn _get_by_import(&self, import: &ImportType) -> Result<Definition, UnknownImportError> {
1279        match self._get(import.module(), import.name()) {
1280            Some(item) => Ok(item.clone()),
1281            None => Err(UnknownImportError::new(import)),
1282        }
1283    }
1284
1285    /// Returns the "default export" of a module.
1286    ///
1287    /// An export with an empty string is considered to be a "default export".
1288    /// "_start" is also recognized for compatibility.
1289    ///
1290    /// # Panics
1291    ///
1292    /// Panics if the default function found is not owned by `store`. This
1293    /// function will also panic if the `store` provided does not come from the
1294    /// same [`Engine`] that this linker was created with.
1295    pub fn get_default(&self, mut store: impl AsContextMut<Data = T>, module: &str) -> Result<Func>
1296    where
1297        T: 'static,
1298    {
1299        if let Some(external) = self.get(&mut store, module, "") {
1300            if let Extern::Func(func) = external {
1301                return Ok(func);
1302            }
1303            bail!("default export in '{module}' is not a function");
1304        }
1305
1306        // For compatibility, also recognize "_start".
1307        if let Some(external) = self.get(&mut store, module, "_start") {
1308            if let Extern::Func(func) = external {
1309                return Ok(func);
1310            }
1311            bail!("`_start` in '{module}' is not a function");
1312        }
1313
1314        // Otherwise return a no-op function.
1315        Ok(Func::wrap(store, || {}))
1316    }
1317}
1318
1319impl<T: 'static> Default for Linker<T> {
1320    fn default() -> Linker<T> {
1321        Linker::new(&Engine::default())
1322    }
1323}
1324
1325impl Definition {
1326    fn new(store: &StoreOpaque, item: Extern) -> Definition {
1327        let ty = DefinitionType::from(store, &item);
1328        Definition::Extern(item, ty)
1329    }
1330
1331    pub(crate) fn ty(&self) -> DefinitionType {
1332        match self {
1333            Definition::Extern(_, ty) => *ty,
1334            Definition::HostFunc(func) => DefinitionType::Func(func.sig_index()),
1335        }
1336    }
1337
1338    /// Inserts this definition into the `store` provided.
1339    ///
1340    /// # Safety
1341    ///
1342    /// Note the unsafety here is due to calling `HostFunc::to_func`. The
1343    /// requirement here is that the `T` that was originally used to create the
1344    /// `HostFunc` matches the `T` on the store.
1345    pub(crate) unsafe fn to_extern(&self, store: &mut StoreOpaque) -> Extern {
1346        match self {
1347            Definition::Extern(e, _) => e.clone(),
1348            // SAFETY: the contract of this function is the same as what's
1349            // required of `to_func`, that `T` of the store matches the `T` of
1350            // this original definition.
1351            Definition::HostFunc(func) => unsafe { func.to_func(store).into() },
1352        }
1353    }
1354
1355    pub(crate) fn comes_from_same_store(&self, store: &StoreOpaque) -> bool {
1356        match self {
1357            Definition::Extern(e, _) => e.comes_from_same_store(store),
1358            Definition::HostFunc(_func) => true,
1359        }
1360    }
1361
1362    fn update_size(&mut self, store: &StoreOpaque) {
1363        match self {
1364            Definition::Extern(Extern::Memory(m), DefinitionType::Memory(_, size)) => {
1365                *size = m.internal_size(store);
1366            }
1367            Definition::Extern(Extern::SharedMemory(m), DefinitionType::Memory(_, size)) => {
1368                *size = m.size();
1369            }
1370            Definition::Extern(Extern::Table(m), DefinitionType::Table(_, size)) => {
1371                *size = m._size(store);
1372            }
1373            _ => {}
1374        }
1375    }
1376}
1377
1378impl DefinitionType {
1379    pub(crate) fn from(store: &StoreOpaque, item: &Extern) -> DefinitionType {
1380        match item {
1381            Extern::Func(f) => DefinitionType::Func(f.type_index(store)),
1382            Extern::Table(t) => DefinitionType::Table(*t.wasmtime_ty(store), t._size(store)),
1383            Extern::Global(t) => DefinitionType::Global(*t.wasmtime_ty(store)),
1384            Extern::Memory(t) => {
1385                DefinitionType::Memory(*t.wasmtime_ty(store), t.internal_size(store))
1386            }
1387            Extern::SharedMemory(t) => DefinitionType::Memory(*t.ty().wasmtime_memory(), t.size()),
1388            Extern::Tag(t) => DefinitionType::Tag(*t.wasmtime_ty(store)),
1389        }
1390    }
1391
1392    pub(crate) fn desc(&self) -> &'static str {
1393        match self {
1394            DefinitionType::Func(_) => "function",
1395            DefinitionType::Table(..) => "table",
1396            DefinitionType::Memory(..) => "memory",
1397            DefinitionType::Global(_) => "global",
1398            DefinitionType::Tag(_) => "tag",
1399        }
1400    }
1401}
1402
1403/// Modules can be interpreted either as Commands or Reactors.
1404enum ModuleKind {
1405    /// The instance is a Command, meaning an instance is created for each
1406    /// exported function and lives for the duration of the function call.
1407    Command,
1408
1409    /// The instance is a Reactor, meaning one instance is created which
1410    /// may live across multiple calls.
1411    Reactor,
1412}
1413
1414impl ModuleKind {
1415    /// Determine whether the given module is a Command or a Reactor.
1416    fn categorize(module: &Module) -> Result<ModuleKind> {
1417        let command_start = module.get_export("_start");
1418        let reactor_start = module.get_export("_initialize");
1419        match (command_start, reactor_start) {
1420            (Some(command_start), None) => {
1421                if let Some(_) = command_start.func() {
1422                    Ok(ModuleKind::Command)
1423                } else {
1424                    bail!("`_start` must be a function")
1425                }
1426            }
1427            (None, Some(reactor_start)) => {
1428                if let Some(_) = reactor_start.func() {
1429                    Ok(ModuleKind::Reactor)
1430                } else {
1431                    bail!("`_initialize` must be a function")
1432                }
1433            }
1434            (None, None) => {
1435                // Module declares neither of the recognized functions, so treat
1436                // it as a reactor with no initialization function.
1437                Ok(ModuleKind::Reactor)
1438            }
1439            (Some(_), Some(_)) => {
1440                // Module declares itself to be both a Command and a Reactor.
1441                bail!("Program cannot be both a Command and a Reactor")
1442            }
1443        }
1444    }
1445}
1446
1447/// Error for an unresolvable import.
1448///
1449/// Returned - wrapped in an [`Error`][crate::Error] - by
1450/// [`Linker::instantiate`] and related methods for modules with unresolvable
1451/// imports.
1452#[derive(Clone, Debug)]
1453pub struct UnknownImportError {
1454    module: String,
1455    name: String,
1456    ty: ExternType,
1457}
1458
1459impl UnknownImportError {
1460    fn new(import: &ImportType) -> Self {
1461        Self {
1462            module: import.module().to_string(),
1463            name: import.name().to_string(),
1464            ty: import.ty(),
1465        }
1466    }
1467
1468    /// Returns the module name that the unknown import was expected to come from.
1469    pub fn module(&self) -> &str {
1470        &self.module
1471    }
1472
1473    /// Returns the field name of the module that the unknown import was expected to come from.
1474    pub fn name(&self) -> &str {
1475        &self.name
1476    }
1477
1478    /// Returns the type of the unknown import.
1479    pub fn ty(&self) -> ExternType {
1480        self.ty.clone()
1481    }
1482}
1483
1484impl fmt::Display for UnknownImportError {
1485    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1486        write!(
1487            f,
1488            "unknown import: `{}::{}` has not been defined",
1489            self.module, self.name,
1490        )
1491    }
1492}
1493
1494impl core::error::Error for UnknownImportError {}