wasmtime/runtime/
linker.rs

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