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