Skip to main content

wasmtime/runtime/component/
linker.rs

1#[cfg(feature = "component-model-async")]
2use crate::component::concurrent::Accessor;
3use crate::component::func::HostFunc;
4use crate::component::instance::RuntimeImport;
5use crate::component::matching::{InstanceType, TypeChecker};
6use crate::component::types;
7use crate::component::{
8    Component, ComponentNamedList, Instance, InstancePre, Lift, Lower, ResourceType, Val,
9};
10use crate::prelude::*;
11use crate::{AsContextMut, Engine, Module, StoreContextMut};
12use alloc::sync::Arc;
13use core::marker;
14#[cfg(feature = "component-model-async")]
15use core::pin::Pin;
16use wasmtime_environ::component::{NameMap, NameMapIntern};
17use wasmtime_environ::{Atom, PrimaryMap, StringPool};
18
19/// A type used to instantiate [`Component`]s.
20///
21/// This type is used to both link components together as well as supply host
22/// functionality to components. Values are defined in a [`Linker`] by their
23/// import name and then components are instantiated with a [`Linker`] using the
24/// names provided for name resolution of the component's imports.
25///
26/// # Names and Semver
27///
28/// Names defined in a [`Linker`] correspond to import names in the Component
29/// Model. Names in the Component Model are allowed to be semver-qualified, for
30/// example:
31///
32/// * `wasi:cli/stdout@0.2.0`
33/// * `wasi:http/types@0.2.0-rc-2023-10-25`
34/// * `my:custom/plugin@1.0.0-pre.2`
35///
36/// These version strings are taken into account when looking up names within a
37/// [`Linker`]. You're allowed to define any number of versions within a
38/// [`Linker`] still, for example you can define `a:b/c@0.2.0`, `a:b/c@0.2.1`,
39/// and `a:b/c@0.3.0` all at the same time.
40///
41/// Specifically though when names are looked up within a linker, for example
42/// during instantiation, semver-compatible names are automatically consulted.
43/// This means that if you define `a:b/c@0.2.1` in a [`Linker`] but a component
44/// imports `a:b/c@0.2.0` then that import will resolve to the `0.2.1` version.
45///
46/// This lookup behavior relies on hosts being well-behaved when using Semver,
47/// specifically that interfaces once defined are never changed. This reflects
48/// how Semver works at the Component Model layer, and it's assumed that if
49/// versions are present then hosts are respecting this.
50///
51/// Note that this behavior goes the other direction, too. If a component
52/// imports `a:b/c@0.2.1` and the host has provided `a:b/c@0.2.0` then that
53/// will also resolve correctly. This is because if an API was defined at 0.2.0
54/// and 0.2.1 then it must be the same API.
55///
56/// This behavior is intended to make it easier for hosts to upgrade WASI and
57/// for guests to upgrade WASI. So long as the actual "meat" of the
58/// functionality is defined then it should align correctly and components can
59/// be instantiated.
60pub struct Linker<T: 'static> {
61    engine: Engine,
62    strings: StringPool,
63    map: NameMap<Atom, Definition>,
64    path: Vec<Atom>,
65    allow_shadowing: bool,
66    _marker: marker::PhantomData<fn() -> T>,
67}
68
69impl<T: 'static> Clone for Linker<T> {
70    fn clone(&self) -> Linker<T> {
71        Linker {
72            engine: self.engine.clone(),
73            strings: self.strings.clone_panic_on_oom(),
74            map: self.map.clone_panic_on_oom(),
75            path: self.path.clone(),
76            allow_shadowing: self.allow_shadowing,
77            _marker: self._marker,
78        }
79    }
80}
81
82/// Structure representing an "instance" being defined within a linker.
83///
84/// Instances do not need to be actual [`Instance`]s and instead are defined by
85/// a "bag of named items", so each [`LinkerInstance`] can further define items
86/// internally.
87pub struct LinkerInstance<'a, T: 'static> {
88    engine: &'a Engine,
89    path: &'a mut Vec<Atom>,
90    path_len: usize,
91    strings: &'a mut StringPool,
92    map: &'a mut NameMap<Atom, Definition>,
93    allow_shadowing: bool,
94    _marker: marker::PhantomData<fn() -> T>,
95}
96
97#[derive(Debug)]
98pub(crate) enum Definition {
99    Instance(NameMap<Atom, Definition>),
100    Func(Arc<HostFunc>),
101    Module(Module),
102    Resource(ResourceType, Arc<crate::func::HostFunc>),
103}
104
105impl TryClone for Definition {
106    fn try_clone(&self) -> Result<Self, OutOfMemory> {
107        Ok(match self {
108            Self::Instance(i) => Self::Instance(i.try_clone()?),
109            Self::Func(f) => Self::Func(f.try_clone()?),
110            Self::Module(m) => Self::Module(m.clone()),
111            Self::Resource(r, f) => Self::Resource(*r, f.try_clone()?),
112        })
113    }
114}
115
116impl<T: 'static> Linker<T> {
117    /// Creates a new linker for the [`Engine`] specified with no items defined
118    /// within it.
119    pub fn new(engine: &Engine) -> Linker<T> {
120        Linker {
121            engine: engine.clone(),
122            strings: StringPool::default(),
123            map: NameMap::default(),
124            allow_shadowing: false,
125            path: Vec::new(),
126            _marker: marker::PhantomData,
127        }
128    }
129
130    /// Returns the [`Engine`] this is connected to.
131    pub fn engine(&self) -> &Engine {
132        &self.engine
133    }
134
135    /// Configures whether or not name-shadowing is allowed.
136    ///
137    /// By default name shadowing is not allowed and it's an error to redefine
138    /// the same name within a linker.
139    pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
140        self.allow_shadowing = allow;
141        self
142    }
143
144    /// Returns the "root instance" of this linker, used to define names into
145    /// the root namespace.
146    pub fn root(&mut self) -> LinkerInstance<'_, T> {
147        LinkerInstance {
148            engine: &self.engine,
149            path: &mut self.path,
150            path_len: 0,
151            strings: &mut self.strings,
152            map: &mut self.map,
153            allow_shadowing: self.allow_shadowing,
154            _marker: self._marker,
155        }
156    }
157
158    /// Returns a builder for the named instance specified.
159    ///
160    /// # Errors
161    ///
162    /// Returns an error if `name` is already defined within the linker.
163    pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
164        self.root().into_instance(name)
165    }
166
167    fn typecheck<'a>(&'a self, component: &'a Component) -> Result<TypeChecker<'a>> {
168        let mut cx = TypeChecker {
169            engine: &self.engine,
170            types: component.types(),
171            strings: &self.strings,
172            imported_resources: try_new::<Arc<_>>(TryPrimaryMap::new())?,
173        };
174
175        // Walk over the component's list of import names and use that to lookup
176        // the definition within this linker that it corresponds to. When found
177        // perform a typecheck against the component's expected type.
178        let env_component = component.env_component();
179        for (_idx, (name, ty)) in env_component.import_types.iter() {
180            let import = self.map.get(name, &self.strings);
181            cx.definition(&ty.ty, import).with_context(|| {
182                format!(
183                    "component imports {desc} `{name}`, but \
184                     a matching implementation was not found in the linker",
185                    desc = ty.ty.desc()
186                )
187            })?;
188        }
189        Ok(cx)
190    }
191
192    /// Returns the [`types::Component`] corresponding to `component` with resource
193    /// types imported by it replaced using imports present in [`Self`].
194    ///
195    /// # Errors
196    ///
197    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
198    /// memory allocation fails. See the `OutOfMemory` type's documentation for
199    /// details on Wasmtime's out-of-memory handling.
200    pub fn substituted_component_type(&self, component: &Component) -> Result<types::Component> {
201        let cx = self.typecheck(&component)?;
202        Ok(types::Component::from(
203            component.ty(),
204            &InstanceType {
205                types: cx.types,
206                resources: Some(&cx.imported_resources),
207            },
208        ))
209    }
210
211    /// Performs a "pre-instantiation" to resolve the imports of the
212    /// [`Component`] specified with the items defined within this linker.
213    ///
214    /// This method will perform as much work as possible short of actually
215    /// instantiating an instance. Internally this will use the names defined
216    /// within this linker to satisfy the imports of the [`Component`] provided.
217    /// Additionally this will perform type-checks against the component's
218    /// imports against all items defined within this linker.
219    ///
220    /// Note that unlike internally in components where subtyping at the
221    /// interface-types layer is supported this is not supported here. Items
222    /// defined in this linker must match the component's imports precisely.
223    ///
224    /// # Errors
225    ///
226    /// Returns an error if this linker doesn't define a name that the
227    /// `component` imports or if a name defined doesn't match the type of the
228    /// item imported by the `component` provided.
229    ///
230    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
231    /// memory allocation fails. See the `OutOfMemory` type's documentation for
232    /// details on Wasmtime's out-of-memory handling.
233    pub fn instantiate_pre(&self, component: &Component) -> Result<InstancePre<T>> {
234        let cx = self.typecheck(&component)?;
235
236        // A successful typecheck resolves all of the imported resources used by
237        // this InstancePre. We keep a clone of this table in the InstancePre
238        // so that we can construct an InstanceType for typechecking.
239        let imported_resources = cx.imported_resources.clone();
240
241        // Now that all imports are known to be defined and satisfied by this
242        // linker a list of "flat" import items (aka no instances) is created
243        // using the import map within the component created at
244        // component-compile-time.
245        let env_component = component.env_component();
246        let mut imports = PrimaryMap::with_capacity(env_component.imports.len());
247        for (idx, (import, names)) in env_component.imports.iter() {
248            let (root, _) = &env_component.import_types[*import];
249
250            // This is the flattening process where we go from a definition
251            // optionally through a list of exported names to get to the final
252            // item.
253            let mut cur = self.map.get(root, &self.strings).unwrap();
254            for name in names {
255                cur = match cur {
256                    Definition::Instance(map) => map.get(&name, &self.strings).unwrap(),
257                    _ => unreachable!(),
258                };
259            }
260            let import = match cur {
261                Definition::Module(m) => RuntimeImport::Module(m.clone()),
262                Definition::Func(f) => RuntimeImport::Func(f.clone()),
263                Definition::Resource(t, dtor) => RuntimeImport::Resource {
264                    ty: *t,
265                    dtor: dtor.clone(),
266                    dtor_funcref: component.resource_drop_func_ref(dtor),
267                },
268
269                // This is guaranteed by the compilation process that "leaf"
270                // runtime imports are never instances.
271                Definition::Instance(_) => unreachable!(),
272            };
273            let i = imports.push(import);
274            assert_eq!(i, idx);
275        }
276        Ok(unsafe {
277            InstancePre::new_unchecked(
278                component.clone(),
279                try_new::<Arc<_>>(imports)?,
280                imported_resources,
281            )
282        })
283    }
284
285    /// Instantiates the [`Component`] provided into the `store` specified.
286    ///
287    /// This function will use the items defined within this [`Linker`] to
288    /// satisfy the imports of the [`Component`] provided as necessary. For more
289    /// information about this see [`Linker::instantiate_pre`] as well.
290    ///
291    /// # Errors
292    ///
293    /// Returns an error if this [`Linker`] doesn't define an import that
294    /// `component` requires or if it is of the wrong type. Additionally this
295    /// can return an error if something goes wrong during instantiation such as
296    /// a runtime trap or a runtime limit being exceeded.
297    ///
298    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
299    /// memory allocation fails. See the `OutOfMemory` type's documentation for
300    /// details on Wasmtime's out-of-memory handling.
301    pub fn instantiate(
302        &self,
303        mut store: impl AsContextMut<Data = T>,
304        component: &Component,
305    ) -> Result<Instance> {
306        let store = store.as_context_mut();
307        store.0.validate_sync_call()?;
308        self.instantiate_pre(component)?.instantiate(store)
309    }
310
311    /// Instantiates the [`Component`] provided into the `store` specified.
312    ///
313    /// This is exactly like [`Linker::instantiate`] except for [asynchronous
314    /// execution](crate#async).
315    ///
316    /// # Errors
317    ///
318    /// Returns an error if this [`Linker`] doesn't define an import that
319    /// `component` requires or if it is of the wrong type. Additionally this
320    /// can return an error if something goes wrong during instantiation such as
321    /// a runtime trap or a runtime limit being exceeded.
322    ///
323    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
324    /// memory allocation fails. See the `OutOfMemory` type's documentation for
325    /// details on Wasmtime's out-of-memory handling.
326    #[cfg(feature = "async")]
327    pub async fn instantiate_async(
328        &self,
329        store: impl AsContextMut<Data = T>,
330        component: &Component,
331    ) -> Result<Instance>
332    where
333        T: Send,
334    {
335        self.instantiate_pre(component)?
336            .instantiate_async(store)
337            .await
338    }
339
340    /// Implement any imports of the given [`Component`] with a function which traps.
341    ///
342    /// By default a [`Linker`] will error when unknown imports are encountered when instantiating a [`Component`].
343    /// This changes this behavior from an instant error to a trap that will happen if the import is called.
344    ///
345    /// # Errors
346    ///
347    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
348    /// memory allocation fails. See the `OutOfMemory` type's documentation for
349    /// details on Wasmtime's out-of-memory handling.
350    pub fn define_unknown_imports_as_traps(&mut self, component: &Component) -> Result<()> {
351        use wasmtime_environ::component::ComponentTypes;
352        use wasmtime_environ::component::TypeDef;
353        // Recursively stub out all imports of the component with a function that traps.
354        fn stub_item<T>(
355            linker: &mut LinkerInstance<T>,
356            item_name: &str,
357            item_def: &TypeDef,
358            parent_instance: Option<&str>,
359            types: &ComponentTypes,
360        ) -> Result<()> {
361            // Skip if the item isn't an instance and has already been defined in the linker.
362            if !matches!(item_def, TypeDef::ComponentInstance(_)) && linker.get(item_name).is_some()
363            {
364                return Ok(());
365            }
366
367            match item_def {
368                TypeDef::ComponentFunc(_func_idx) => {
369                    let fully_qualified_name = match parent_instance {
370                        Some(parent) => {
371                            let mut s = TryString::new();
372                            s.push_str(parent)?;
373                            s.push('#')?;
374                            s.push_str(item_name)?;
375                            s
376                        }
377                        None => {
378                            let mut s = TryString::new();
379                            s.push_str(item_name)?;
380                            s
381                        }
382                    };
383
384                    // An `async func`-typed import can never be satisfied by
385                    // `func_new` (only a sync-typed import can) — see
386                    // `typecheck_async`'s doc comment. Stub it with
387                    // `func_new_concurrent` instead so unsatisfied async
388                    // imports can be stubbed-as-traps too, not just sync
389                    // ones; if concurrency support isn't enabled there's no
390                    // way to stub it here, so fall through to `func_new` and
391                    // let instantiation fail with that same explanatory
392                    // error.
393                    #[cfg(feature = "component-model-async")]
394                    if types[*_func_idx].async_ && linker.engine.tunables().concurrency_support {
395                        linker.func_new_concurrent(&item_name, move |_, _, _, _| {
396                            let fully_qualified_name = fully_qualified_name.try_clone();
397                            Box::pin(async move {
398                                let fully_qualified_name = fully_qualified_name?;
399                                bail!(
400                                    "unknown import: `{fully_qualified_name}` has not been defined"
401                                )
402                            })
403                        })?;
404                        return Ok(());
405                    }
406
407                    linker.func_new(&item_name, move |_, _, _, _| {
408                        bail!("unknown import: `{fully_qualified_name}` has not been defined")
409                    })?;
410                }
411                TypeDef::ComponentInstance(i) => {
412                    let instance = &types[*i];
413                    let mut linker_instance = linker.instance(item_name)?;
414                    for (export_name, export) in instance.exports.iter() {
415                        stub_item(
416                            &mut linker_instance,
417                            export_name,
418                            &export.ty,
419                            Some(item_name),
420                            types,
421                        )?;
422                    }
423                }
424                TypeDef::Resource(_) => {
425                    let ty = crate::component::ResourceType::host::<()>();
426                    linker.resource(item_name, ty, |_, _| Ok(()))?;
427                }
428                TypeDef::Component(_) | TypeDef::Module(_) => {
429                    bail!("unable to define {} imports as traps", item_def.desc())
430                }
431                _ => {}
432            }
433            Ok(())
434        }
435
436        for (_, (import_name, import_type)) in &component.env_component().import_types {
437            stub_item(
438                &mut self.root(),
439                import_name,
440                &import_type.ty,
441                None,
442                component.types(),
443            )?;
444        }
445        Ok(())
446    }
447}
448
449impl<T: 'static> LinkerInstance<'_, T> {
450    fn as_mut(&mut self) -> LinkerInstance<'_, T> {
451        LinkerInstance {
452            engine: self.engine,
453            path: self.path,
454            path_len: self.path_len,
455            strings: self.strings,
456            map: self.map,
457            allow_shadowing: self.allow_shadowing,
458            _marker: self._marker,
459        }
460    }
461
462    /// Defines a new host-provided function into this [`LinkerInstance`].
463    ///
464    /// This method is used to give host functions to wasm components. The
465    /// `func` provided will be callable from linked components with the type
466    /// signature dictated by `Params` and `Return`. The `Params` is a tuple of
467    /// types that will come from wasm and `Return` is a value coming from the
468    /// host going back to wasm.
469    ///
470    /// Additionally the `func` takes a
471    /// [`StoreContextMut`](crate::StoreContextMut) as its first parameter.
472    ///
473    /// Note that `func` must be an `Fn` and must also be `Send + Sync +
474    /// 'static`. Shared state within a func is typically accessed with the `T`
475    /// type parameter from [`Store<T>`](crate::Store) which is accessible
476    /// through the leading [`StoreContextMut<'_, T>`](crate::StoreContextMut)
477    /// argument which can be provided to the `func` given here.
478    ///
479    /// # Blocking / Async Behavior
480    ///
481    /// The host function `func` provided here is a blocking function from the
482    /// perspective of WebAssembly. WebAssembly, and Rust, will be blocked until
483    /// `func` completes.
484    ///
485    /// To define a function which is async on the host, but blocking to the
486    /// guest, see the [`func_wrap_async`] method.
487    ///
488    /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
489    ///
490    /// # Errors
491    ///
492    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
493    /// memory allocation fails. See the `OutOfMemory` type's documentation for
494    /// details on Wasmtime's out-of-memory handling.
495    //
496    // TODO: needs more words and examples
497    pub fn func_wrap<F, Params, Return>(&mut self, name: &str, func: F) -> Result<()>
498    where
499        F: Fn(StoreContextMut<T>, Params) -> Result<Return> + Send + Sync + 'static,
500        Params: ComponentNamedList + Lift + 'static,
501        Return: ComponentNamedList + Lower + 'static,
502    {
503        self.insert(name, Definition::Func(HostFunc::func_wrap(func)?))?;
504        Ok(())
505    }
506
507    /// Defines a new host-provided async function into this [`LinkerInstance`].
508    ///
509    /// This function is similar to [`Self::func_wrap`] except it takes an async
510    /// host function instead of a blocking host function. The `F` function here
511    /// is intended to be:
512    ///
513    /// ```ignore
514    /// F: AsyncFn(StoreContextMut<'_, T>, Params) -> Result<Return>
515    /// ```
516    ///
517    /// however the returned future must be `Send` which is not possible to
518    /// bound at this time. This will be switched to an async closure once Rust
519    /// supports it.
520    ///
521    /// # Blocking / Async Behavior
522    ///
523    /// The function defined which WebAssembly calls will still appear as
524    /// blocking from the perspective of WebAssembly itself. The host, however,
525    /// can perform asynchronous operations without blocking the thread
526    /// performing a call.
527    ///
528    /// When defining host functions with this function, WebAssembly is invoked
529    /// on a separate stack within a Wasmtime-managed fiber (through the
530    /// `call_async`-style of invocation). This means that if the future
531    /// returned by `F` is not immediately ready then the fiber will be
532    /// suspended to block WebAssembly but not the host. When the future
533    /// becomes ready again the fiber will be resumed to continue execution
534    /// within WebAssembly.
535    ///
536    /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
537    #[cfg(feature = "async")]
538    pub fn func_wrap_async<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
539    where
540        F: Fn(
541                StoreContextMut<'_, T>,
542                Params,
543            ) -> Box<dyn Future<Output = Result<Return>> + Send + '_>
544            + Send
545            + Sync
546            + 'static,
547        Params: ComponentNamedList + Lift + 'static,
548        Return: ComponentNamedList + Lower + 'static,
549    {
550        self.insert(name, Definition::Func(HostFunc::func_wrap_async(f)?))?;
551        Ok(())
552    }
553
554    /// Defines a new host-provided async function into this [`LinkerInstance`].
555    ///
556    /// This function defines a host function available to call from
557    /// WebAssembly. WebAssembly may additionally make multiple invocations of
558    /// this function concurrently all at the same time. This function requires
559    /// the [`Config::wasm_component_model_async`] feature to be enabled.
560    ///
561    /// The function `f` provided will be invoked when called by WebAssembly.
562    /// WebAssembly components may then call `f` multiple times while previous
563    /// invocations of `f` are already running. Additionally while `f` is
564    /// running other host functions may be invoked.
565    ///
566    /// The `F` function here is intended to be:
567    ///
568    /// ```ignore
569    /// F: AsyncFn(&Accessor<T>, Params) -> Result<Return>
570    /// ```
571    ///
572    /// however the returned future must be `Send` which is not possible to
573    /// bound at this time. This will be switched to an async closure once Rust
574    /// supports it.
575    ///
576    /// The closure `f` is provided an [`Accessor`] which can be used to acquire
577    /// temporary, blocking, access to a [`StoreContextMut`] (through
578    /// [`Access`](crate::component::Access]). This models how a store is not
579    /// available to `f` across `await` points but it is temporarily available
580    /// while actively being polled.
581    ///
582    /// # Blocking / Async Behavior
583    ///
584    /// Unlike [`Self::func_wrap`] and [`Self::func_wrap_async`] this function
585    /// is asynchronous even from the perspective of guest WebAssembly. This
586    /// means that if `f` is not immediately resolved then the call from
587    /// WebAssembly will still return immediately (assuming it was lowered with
588    /// `async`). The closure `f` should not block the current thread and
589    /// should only perform blocking via `async` meaning that `f` won't block
590    /// either WebAssembly nor the host.
591    ///
592    /// Note that WebAssembly components can lower host functions both with and
593    /// without `async`. That means that even if a host function is defined in
594    /// the "concurrent" mode here a guest may still lower it synchronously. In
595    /// this situation Wasmtime will manage blocking the guest while the closure
596    /// `f` provided here completes. If a guest lowers this function with
597    /// `async`, though, then no blocking will happen.
598    ///
599    /// [`Config::wasm_component_model_async`]: crate::Config::wasm_component_model_async
600    /// [`func_wrap_async`]: LinkerInstance::func_wrap_async
601    #[cfg(feature = "component-model-async")]
602    pub fn func_wrap_concurrent<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
603    where
604        T: 'static,
605        F: Fn(&Accessor<T>, Params) -> Pin<Box<dyn Future<Output = Result<Return>> + Send + '_>>
606            + Send
607            + Sync
608            + 'static,
609        Params: ComponentNamedList + Lift + 'static,
610        Return: ComponentNamedList + Lower + 'static,
611    {
612        if !self.engine.tunables().concurrency_support {
613            bail!("concurrent host functions require `Config::concurrency_support`");
614        }
615        self.insert(name, Definition::Func(HostFunc::func_wrap_concurrent(f)?))?;
616        Ok(())
617    }
618
619    /// Define a new host-provided function using dynamically typed values.
620    ///
621    /// The `name` provided is the name of the function to define and the
622    /// `func` provided is the host-defined closure to invoke when this
623    /// function is called.
624    ///
625    /// This function is the "dynamic" version of defining a host function as
626    /// compared to [`LinkerInstance::func_wrap`]. With
627    /// [`LinkerInstance::func_wrap`] a function's type is statically known but
628    /// with this method the `func` argument's type isn't known ahead of time.
629    /// That means that `func` can be by imported component so long as it's
630    /// imported as a matching name.
631    ///
632    /// Type information will be available at execution time, however. For
633    /// example when `func` is invoked the second argument, a `&[Val]` list,
634    /// contains [`Val`] entries that say what type they are. Additionally the
635    /// third argument, `&mut [Val]`, is the expected number of results. Note
636    /// that the expected types of the results cannot be learned during the
637    /// execution of `func`. Learning that would require runtime introspection
638    /// of a component.
639    ///
640    /// Return values, stored in the third argument of `&mut [Val]`, are
641    /// type-checked at runtime to ensure that they have the appropriate type.
642    /// A trap will be raised if they do not have the right type.
643    ///
644    /// # Examples
645    ///
646    /// ```
647    /// use wasmtime::{Store, Engine};
648    /// use wasmtime::component::{Component, Linker, Val};
649    ///
650    /// # fn main() -> wasmtime::Result<()> {
651    /// let engine = Engine::default();
652    /// let component = Component::new(
653    ///     &engine,
654    ///     r#"
655    ///         (component
656    ///             (import "thunk" (func $thunk))
657    ///             (import "is-even" (func $is-even (param "x" u32) (result bool)))
658    ///
659    ///             (core module $m
660    ///                 (import "" "thunk" (func $thunk))
661    ///                 (import "" "is-even" (func $is-even (param i32) (result i32)))
662    ///
663    ///                 (func (export "run")
664    ///                     call $thunk
665    ///
666    ///                     (call $is-even (i32.const 1))
667    ///                     if unreachable end
668    ///
669    ///                     (call $is-even (i32.const 2))
670    ///                     i32.eqz
671    ///                     if unreachable end
672    ///                 )
673    ///             )
674    ///             (core func $thunk (canon lower (func $thunk)))
675    ///             (core func $is-even (canon lower (func $is-even)))
676    ///             (core instance $i (instantiate $m
677    ///                 (with "" (instance
678    ///                     (export "thunk" (func $thunk))
679    ///                     (export "is-even" (func $is-even))
680    ///                 ))
681    ///             ))
682    ///
683    ///             (func (export "run") (canon lift (core func $i "run")))
684    ///         )
685    ///     "#,
686    /// )?;
687    ///
688    /// let mut linker = Linker::<()>::new(&engine);
689    ///
690    /// // Sample function that takes no arguments.
691    /// linker.root().func_new("thunk", |_store, _ty, params, results| {
692    ///     assert!(params.is_empty());
693    ///     assert!(results.is_empty());
694    ///     println!("Look ma, host hands!");
695    ///     Ok(())
696    /// })?;
697    ///
698    /// // This function takes one argument and returns one result.
699    /// linker.root().func_new("is-even", |_store, _ty, params, results| {
700    ///     assert_eq!(params.len(), 1);
701    ///     let param = match params[0] {
702    ///         Val::U32(n) => n,
703    ///         _ => panic!("unexpected type"),
704    ///     };
705    ///
706    ///     assert_eq!(results.len(), 1);
707    ///     results[0] = Val::Bool(param % 2 == 0);
708    ///     Ok(())
709    /// })?;
710    ///
711    /// let mut store = Store::new(&engine, ());
712    /// let instance = linker.instantiate(&mut store, &component)?;
713    /// let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
714    /// run.call(&mut store, ())?;
715    /// # Ok(())
716    /// # }
717    /// ```
718    ///
719    /// # Errors
720    ///
721    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
722    /// memory allocation fails. See the `OutOfMemory` type's documentation for
723    /// details on Wasmtime's out-of-memory handling.
724    pub fn func_new(
725        &mut self,
726        name: &str,
727        func: impl Fn(StoreContextMut<'_, T>, types::ComponentFunc, &[Val], &mut [Val]) -> Result<()>
728        + Send
729        + Sync
730        + 'static,
731    ) -> Result<()> {
732        self.insert(name, Definition::Func(HostFunc::func_new(func)?))?;
733        Ok(())
734    }
735
736    /// Define a new host-provided async function using dynamic types.
737    ///
738    /// As [`Self::func_wrap_async`] is a dual of [`Self::func_wrap`], this
739    /// function is the dual of [`Self::func_new`].
740    ///
741    /// For documentation on blocking behavior see [`Self::func_wrap_async`].
742    #[cfg(feature = "async")]
743    pub fn func_new_async<F>(&mut self, name: &str, func: F) -> Result<()>
744    where
745        F: for<'a> Fn(
746                StoreContextMut<'a, T>,
747                types::ComponentFunc,
748                &'a [Val],
749                &'a mut [Val],
750            ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
751            + Send
752            + Sync
753            + 'static,
754    {
755        self.insert(name, Definition::Func(HostFunc::func_new_async(func)?))?;
756        Ok(())
757    }
758
759    /// Define a new host-provided async function using dynamic types.
760    ///
761    /// As [`Self::func_wrap_concurrent`] is a dual of [`Self::func_wrap`], this
762    /// function is the dual of [`Self::func_new`].
763    ///
764    /// For documentation on async/blocking behavior see
765    /// [`Self::func_wrap_concurrent`].
766    #[cfg(feature = "component-model-async")]
767    pub fn func_new_concurrent<F>(&mut self, name: &str, f: F) -> Result<()>
768    where
769        T: 'static,
770        F: for<'a> Fn(
771                &'a Accessor<T>,
772                types::ComponentFunc,
773                &'a [Val],
774                &'a mut [Val],
775            ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>
776            + Send
777            + Sync
778            + 'static,
779    {
780        if !self.engine.tunables().concurrency_support {
781            bail!("concurrent host functions require `Config::concurrency_support`");
782        }
783        self.insert(name, Definition::Func(HostFunc::func_new_concurrent(f)?))?;
784        Ok(())
785    }
786
787    /// Defines a [`Module`] within this instance.
788    ///
789    /// This can be used to provide a core wasm [`Module`] as an import to a
790    /// component. The [`Module`] provided is saved within the linker for the
791    /// specified `name` in this instance.
792    ///
793    /// # Errors
794    ///
795    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
796    /// memory allocation fails. See the `OutOfMemory` type's documentation for
797    /// details on Wasmtime's out-of-memory handling.
798    pub fn module(&mut self, name: &str, module: &Module) -> Result<()> {
799        self.insert(name, Definition::Module(module.clone()))?;
800        Ok(())
801    }
802
803    /// Defines a new resource of a given [`ResourceType`] in this linker.
804    ///
805    /// This function is used to specify resources defined in the host.
806    ///
807    /// The `name` argument is the name to define the resource within this
808    /// linker.
809    ///
810    /// The `dtor` provided is a destructor that will get invoked when an owned
811    /// version of this resource is destroyed from the guest. Note that this
812    /// destructor is not called when a host-owned resource is destroyed as it's
813    /// assumed the host knows how to handle destroying its own resources.
814    ///
815    /// The `dtor` closure is provided the store state as the first argument
816    /// along with the representation of the resource that was just destroyed.
817    ///
818    /// [`Resource<U>`]: crate::component::Resource
819    ///
820    /// # Errors
821    ///
822    /// The provided `dtor` closure returns an error if something goes wrong
823    /// when a guest calls the `dtor` to drop a `Resource<T>` such as
824    /// a runtime trap or a runtime limit being exceeded.
825    ///
826    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error when
827    /// memory allocation fails. See the `OutOfMemory` type's documentation for
828    /// details on Wasmtime's out-of-memory handling.
829    pub fn resource(
830        &mut self,
831        name: &str,
832        ty: ResourceType,
833        dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static,
834    ) -> Result<()> {
835        let dtor = try_new::<Arc<_>>(crate::func::HostFunc::wrap(
836            &self.engine,
837            move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.as_context_mut(), param),
838        )?)?;
839        self.insert(name, Definition::Resource(ty, dtor))?;
840        Ok(())
841    }
842
843    /// Identical to [`Self::resource`], except that it takes an async destructor.
844    #[cfg(feature = "async")]
845    pub fn resource_async<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
846    where
847        T: Send,
848        F: Fn(StoreContextMut<'_, T>, u32) -> Box<dyn Future<Output = Result<()>> + Send + '_>
849            + Send
850            + Sync
851            + 'static,
852    {
853        let dtor = try_new::<Arc<_>>(crate::func::HostFunc::wrap_async(
854            &self.engine,
855            move |cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.into(), param),
856        )?)?;
857        self.insert(name, Definition::Resource(ty, dtor))?;
858        Ok(())
859    }
860
861    /// Identical to [`Self::resource`], except that it takes a concurrent destructor.
862    #[cfg(feature = "component-model-async")]
863    pub fn resource_concurrent<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
864    where
865        T: Send + 'static,
866        F: Fn(&Accessor<T>, u32) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>>
867            + Send
868            + Sync
869            + 'static,
870    {
871        if !self.engine.tunables().concurrency_support {
872            bail!("concurrent host functions require `Config::concurrency_support`");
873        }
874        // TODO: This isn't really concurrent -- it requires exclusive access to
875        // the store for the duration of the call, preventing guest code from
876        // running until it completes.  We should make it concurrent and clean
877        // up the implementation to avoid using e.g. `Accessor::new` and
878        // `tls::set` directly.
879        let dtor = Arc::new(dtor);
880        let dtor = Arc::new(crate::func::HostFunc::wrap_async(
881            &self.engine,
882            move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| {
883                let dtor = dtor.clone();
884                Box::new(async move {
885                    let mut store = cx.as_context_mut();
886                    let accessor =
887                        &Accessor::new(crate::store::StoreToken::new(store.as_context_mut()));
888                    let mut future = core::pin::pin!(dtor(accessor, param));
889                    core::future::poll_fn(|cx| {
890                        crate::component::concurrent::tls::set(store.0, || future.as_mut().poll(cx))
891                    })
892                    .await
893                })
894            },
895        )?);
896        self.insert(name, Definition::Resource(ty, dtor))?;
897        Ok(())
898    }
899
900    /// Defines a nested instance within this instance.
901    ///
902    /// This can be used to describe arbitrarily nested levels of instances
903    /// within a linker to satisfy nested instance exports of components.
904    pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
905        self.as_mut().into_instance(name)
906    }
907
908    /// Same as [`LinkerInstance::instance`] except with different lifetime
909    /// parameters.
910    pub fn into_instance(mut self, name: &str) -> Result<Self> {
911        let atom = self.strings.intern(name)?;
912
913        // If this item is already an instance then don't stomp over it with a
914        // new empty instance (or fail due to shadowing being disallowed).
915        // Instead continue through to below to explicitly allow re-opening an
916        // instance multiple times over separate API calls.
917        //
918        // If this item isn't defined, or is defined as anything other than an
919        // instance, however, the insert a fresh new instance and see what
920        // happens as a result.
921        match self.map.raw_get_mut(&atom) {
922            Some(Definition::Instance(_)) => {}
923            _ => {
924                self.insert(name, Definition::Instance(NameMap::default()))?;
925            }
926        }
927        self.map = match self.map.raw_get_mut(&atom) {
928            Some(Definition::Instance(map)) => map,
929            _ => unreachable!(),
930        };
931        self.path.truncate(self.path_len);
932        self.path.push(atom);
933        self.path_len += 1;
934        Ok(self)
935    }
936
937    fn insert(&mut self, name: &str, item: Definition) -> Result<Atom> {
938        self.map
939            .insert(name, self.strings, self.allow_shadowing, item)
940    }
941
942    fn get(&self, name: &str) -> Option<&Definition> {
943        self.map.get(name, self.strings)
944    }
945}