Skip to main content

wasmtime/runtime/
linker.rs

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