Skip to main content

wasmer/entities/function/
inner.rs

1use std::pin::Pin;
2
3use wasmer_types::{FunctionType, RawValue};
4
5#[cfg(feature = "experimental-async")]
6use crate::{AsStoreAsync, AsyncFunctionEnvMut, entities::function::async_host::AsyncHostFunction};
7use crate::{
8    AsStoreMut, AsStoreRef, ExportError, Exportable, Extern, FunctionEnv, FunctionEnvMut,
9    HostFunction, StoreMut, StoreRef, TypedFunction, Value, WasmTypeList, WithEnv, WithoutEnv,
10    error::RuntimeError,
11    macros::backend::{gen_rt_ty, match_rt},
12    vm::{VMExtern, VMExternFunction, VMFuncRef},
13};
14
15/// A WebAssembly `function` instance.
16///
17/// A function instance is the runtime representation of a function.
18/// It effectively is a closure of the original function (defined in either
19/// the host or the WebAssembly module) over the runtime `Instance` of its
20/// originating `Module`.
21///
22/// The module instance is used to resolve references to other definitions
23/// during execution of the function.
24///
25/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances>
26///
27/// # Panics
28/// - Closures (functions with captured environments) are not currently supported
29///   with native functions. Attempting to create a native `Function` with one will
30///   result in a panic.
31///   [Closures as host functions tracking issue](https://github.com/wasmerio/wasmer/issues/1840)
32gen_rt_ty! {
33    #[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
34    #[derive(Debug, Clone, PartialEq, Eq)]
35    pub(crate) BackendFunction(entities::function::Function);
36}
37
38impl BackendFunction {
39    /// Creates a new host `Function` (dynamic) with the provided signature.
40    ///
41    /// If you know the signature of the host function at compile time,
42    /// consider using [`Self::new_typed`] for less runtime overhead.
43    #[inline]
44    pub fn new<FT, F>(store: &mut impl AsStoreMut, ty: FT, func: F) -> Self
45    where
46        FT: Into<FunctionType>,
47        F: Fn(&[Value]) -> Result<Vec<Value>, RuntimeError> + 'static + Send + Sync,
48    {
49        let env = FunctionEnv::new(&mut store.as_store_mut(), ());
50        let wrapped_func = move |_env: FunctionEnvMut<()>,
51                                 args: &[Value]|
52              -> Result<Vec<Value>, RuntimeError> { func(args) };
53        Self::new_with_env(store, &env, ty, wrapped_func)
54    }
55
56    /// Creates a new host `Function` (dynamic) with the provided signature.
57    ///
58    /// If you know the signature of the host function at compile time,
59    /// consider using [`Self::new_typed_with_env`] for less runtime overhead.
60    ///
61    /// Takes a [`FunctionEnv`] that is passed into func. If that is not required,
62    /// [`Self::new`] might be an option as well.
63    ///
64    /// # Examples
65    ///
66    /// ```
67    /// # use wasmer::{Function, FunctionEnv, FunctionType, Type, Store, Value};
68    /// # let mut store = Store::default();
69    /// # let env = FunctionEnv::new(&mut store, ());
70    /// #
71    /// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]);
72    ///
73    /// let f = Function::new_with_env(&mut store, &env, &signature, |_env, args| {
74    ///     let sum = args[0].unwrap_i32() + args[1].unwrap_i32();
75    ///     Ok(vec![Value::I32(sum)])
76    /// });
77    /// ```
78    ///
79    /// With constant signature:
80    ///
81    /// ```
82    /// # use wasmer::{Function, FunctionEnv, FunctionType, Type, Store, Value};
83    /// # let mut store = Store::default();
84    /// # let env = FunctionEnv::new(&mut store, ());
85    /// #
86    /// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]);
87    ///
88    /// let f = Function::new_with_env(&mut store, &env, I32_I32_TO_I32, |_env, args| {
89    ///     let sum = args[0].unwrap_i32() + args[1].unwrap_i32();
90    ///     Ok(vec![Value::I32(sum)])
91    /// });
92    /// ```
93    #[inline]
94    pub fn new_with_env<FT, F, T: Send + 'static>(
95        store: &mut impl AsStoreMut,
96        env: &FunctionEnv<T>,
97        ty: FT,
98        func: F,
99    ) -> Self
100    where
101        FT: Into<FunctionType>,
102        F: Fn(FunctionEnvMut<T>, &[Value]) -> Result<Vec<Value>, RuntimeError>
103            + 'static
104            + Send
105            + Sync,
106    {
107        match &store.as_store_mut().inner.store {
108            #[cfg(feature = "sys")]
109            crate::BackendStore::Sys(_) => Self::Sys(
110                crate::backend::sys::entities::function::Function::new_with_env(
111                    store, env, ty, func,
112                ),
113            ),
114            #[cfg(feature = "v8")]
115            crate::BackendStore::V8(_) => Self::V8(
116                crate::backend::v8::entities::function::Function::new_with_env(
117                    store, env, ty, func,
118                ),
119            ),
120            #[cfg(feature = "js")]
121            crate::BackendStore::Js(_) => Self::Js(
122                crate::backend::js::entities::function::Function::new_with_env(
123                    store, env, ty, func,
124                ),
125            ),
126        }
127    }
128
129    /// Creates a new host `Function` from a native function.
130    #[inline]
131    pub fn new_typed<F, Args, Rets>(store: &mut impl AsStoreMut, func: F) -> Self
132    where
133        F: HostFunction<(), Args, Rets, WithoutEnv> + 'static + Send + Sync,
134        Args: WasmTypeList,
135        Rets: WasmTypeList,
136    {
137        match &store.as_store_mut().inner.store {
138            #[cfg(feature = "sys")]
139            crate::BackendStore::Sys(_) => {
140                Self::Sys(crate::backend::sys::entities::function::Function::new_typed(store, func))
141            }
142            #[cfg(feature = "v8")]
143            crate::BackendStore::V8(_) => Self::V8(
144                crate::backend::v8::entities::function::Function::new_typed(store, func),
145            ),
146            #[cfg(feature = "js")]
147            crate::BackendStore::Js(_) => Self::Js(
148                crate::backend::js::entities::function::Function::new_typed(store, func),
149            ),
150        }
151    }
152
153    /// Creates a new host `Function` with an environment from a typed function.
154    ///
155    /// The function signature is automatically retrieved using the
156    /// Rust typing system.
157    ///
158    /// # Example
159    ///
160    /// ```
161    /// # use wasmer::{Store, Function, FunctionEnv, FunctionEnvMut};
162    /// # let mut store = Store::default();
163    /// # let env = FunctionEnv::new(&mut store, ());
164    /// #
165    /// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
166    ///     a + b
167    /// }
168    ///
169    /// let f = Function::new_typed_with_env(&mut store, &env, sum);
170    /// ```
171    #[inline]
172    pub fn new_typed_with_env<T: Send + 'static, F, Args, Rets>(
173        store: &mut impl AsStoreMut,
174        env: &FunctionEnv<T>,
175        func: F,
176    ) -> Self
177    where
178        F: HostFunction<T, Args, Rets, WithEnv> + 'static + Send + Sync,
179        Args: WasmTypeList,
180        Rets: WasmTypeList,
181    {
182        match &store.as_store_mut().inner.store {
183            #[cfg(feature = "sys")]
184            crate::BackendStore::Sys(s) => Self::Sys(
185                crate::backend::sys::entities::function::Function::new_typed_with_env(
186                    store, env, func,
187                ),
188            ),
189            #[cfg(feature = "v8")]
190            crate::BackendStore::V8(s) => Self::V8(
191                crate::backend::v8::entities::function::Function::new_typed_with_env(
192                    store, env, func,
193                ),
194            ),
195            #[cfg(feature = "js")]
196            crate::BackendStore::Js(s) => Self::Js(
197                crate::backend::js::entities::function::Function::new_typed_with_env(
198                    store, env, func,
199                ),
200            ),
201        }
202    }
203
204    /// Creates a new async host `Function` (dynamic) with the provided
205    /// signature.
206    ///
207    /// If you know the signature of the host function at compile time,
208    /// consider using [`Self::new_typed_async`] for less runtime overhead.
209    ///
210    /// The provided closure returns a future that resolves to the function results.
211    /// When invoked synchronously
212    /// (via [`Function::call`](crate::Function::call)) the future will run to
213    /// completion immediately, provided it doesn't suspend. When invoked through
214    /// [`Function::call_async`](crate::Function::call_async), the future may suspend
215    /// and resume as needed.
216    #[inline]
217    #[cfg(feature = "experimental-async")]
218    pub fn new_async<FT, F, Fut>(store: &mut impl AsStoreMut, ty: FT, func: F) -> Self
219    where
220        FT: Into<FunctionType>,
221        F: Fn(&[Value]) -> Fut + 'static,
222        Fut: Future<Output = Result<Vec<Value>, RuntimeError>> + 'static,
223    {
224        match &store.as_store_mut().inner.store {
225            #[cfg(feature = "sys")]
226            crate::BackendStore::Sys(_) => Self::Sys(
227                crate::backend::sys::entities::function::Function::new_async(store, ty, func),
228            ),
229            #[cfg(feature = "v8")]
230            crate::BackendStore::V8(_) => unsupported_async_backend("v8"),
231            #[cfg(feature = "js")]
232            crate::BackendStore::Js(_) => Self::Js(
233                crate::backend::js::entities::function::Function::new_async(store, ty, func),
234            ),
235        }
236    }
237
238    /// Creates a new async host `Function` (dynamic) with the provided
239    /// signature and environment.
240    ///
241    /// If you know the signature of the host function at compile time,
242    /// consider using [`Self::new_typed_with_env_async`] for less runtime overhead.
243    ///
244    /// Takes an [`AsyncFunctionEnvMut`] that is passed into func. If
245    /// that is not required, [`Self::new_async`] might be an option as well.
246    #[inline]
247    #[cfg(feature = "experimental-async")]
248    pub fn new_with_env_async<FT, F, Fut, T: 'static>(
249        store: &mut impl AsStoreMut,
250        env: &FunctionEnv<T>,
251        ty: FT,
252        func: F,
253    ) -> Self
254    where
255        FT: Into<FunctionType>,
256        F: Fn(AsyncFunctionEnvMut<T>, &[Value]) -> Fut + 'static,
257        Fut: Future<Output = Result<Vec<Value>, RuntimeError>> + 'static,
258    {
259        match &store.as_store_mut().inner.store {
260            #[cfg(feature = "sys")]
261            crate::BackendStore::Sys(_) => Self::Sys(
262                crate::backend::sys::entities::function::Function::new_with_env_async(
263                    store, env, ty, func,
264                ),
265            ),
266            #[cfg(feature = "v8")]
267            crate::BackendStore::V8(_) => unsupported_async_backend("v8"),
268            #[cfg(feature = "js")]
269            crate::BackendStore::Js(_) => Self::Js(
270                crate::backend::js::entities::function::Function::new_with_env_async(
271                    store, env, ty, func,
272                ),
273            ),
274        }
275    }
276
277    /// Creates a new async host `Function` from a native typed function.
278    ///
279    /// The future can return either the raw result tuple or any type that implements
280    /// [`IntoResult`](crate::IntoResult) for the result tuple (e.g. `Result<Rets, E>`).
281    #[inline]
282    #[cfg(feature = "experimental-async")]
283    pub fn new_typed_async<F, Args, Rets>(store: &mut impl AsStoreMut, func: F) -> Self
284    where
285        F: AsyncHostFunction<(), Args, Rets, WithoutEnv> + 'static,
286        Args: WasmTypeList + 'static,
287        Rets: WasmTypeList + 'static,
288    {
289        match &store.as_store_mut().inner.store {
290            #[cfg(feature = "sys")]
291            crate::BackendStore::Sys(_) => Self::Sys(
292                crate::backend::sys::entities::function::Function::new_typed_async(store, func),
293            ),
294            #[cfg(feature = "v8")]
295            crate::BackendStore::V8(_) => unsupported_async_backend("v8"),
296            #[cfg(feature = "js")]
297            crate::BackendStore::Js(_) => Self::Js(
298                crate::backend::js::entities::function::Function::new_typed_async(store, func),
299            ),
300        }
301    }
302
303    /// Creates a new async host `Function` with an environment from a typed function.
304    #[inline]
305    #[cfg(feature = "experimental-async")]
306    pub fn new_typed_with_env_async<T: 'static, F, Args, Rets>(
307        store: &mut impl AsStoreMut,
308        env: &FunctionEnv<T>,
309        func: F,
310    ) -> Self
311    where
312        F: AsyncHostFunction<T, Args, Rets, WithEnv> + 'static,
313        Args: WasmTypeList + 'static,
314        Rets: WasmTypeList + 'static,
315    {
316        match &store.as_store_mut().inner.store {
317            #[cfg(feature = "sys")]
318            crate::BackendStore::Sys(_) => Self::Sys(
319                crate::backend::sys::entities::function::Function::new_typed_with_env_async(
320                    store, env, func,
321                ),
322            ),
323            #[cfg(feature = "v8")]
324            crate::BackendStore::V8(_) => unsupported_async_backend("v8"),
325            #[cfg(feature = "js")]
326            crate::BackendStore::Js(_) => Self::Js(
327                crate::backend::js::entities::function::Function::new_typed_with_env_async(
328                    store, env, func,
329                ),
330            ),
331        }
332    }
333
334    /// Returns the [`FunctionType`] of the `Function`.
335    ///
336    /// # Example
337    ///
338    /// ```
339    /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type};
340    /// # let mut store = Store::default();
341    /// # let env = FunctionEnv::new(&mut store, ());
342    /// #
343    /// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
344    ///     a + b
345    /// }
346    ///
347    /// let f = Function::new_typed_with_env(&mut store, &env, sum);
348    ///
349    /// assert_eq!(f.ty(&mut store).params(), vec![Type::I32, Type::I32]);
350    /// assert_eq!(f.ty(&mut store).results(), vec![Type::I32]);
351    /// ```
352    #[inline]
353    pub fn ty(&self, store: &impl AsStoreRef) -> FunctionType {
354        match_rt!(on self => f {
355            f.ty(store)
356        })
357    }
358
359    /// Returns the number of parameters that this function takes.
360    ///
361    /// # Example
362    ///
363    /// ```
364    /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type};
365    /// # let mut store = Store::default();
366    /// # let env = FunctionEnv::new(&mut store, ());
367    /// #
368    /// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
369    ///     a + b
370    /// }
371    ///
372    /// let f = Function::new_typed_with_env(&mut store, &env, sum);
373    ///
374    /// assert_eq!(f.param_arity(&mut store), 2);
375    /// ```
376    #[inline]
377    pub fn param_arity(&self, store: &impl AsStoreRef) -> usize {
378        self.ty(store).params().len()
379    }
380
381    /// Returns the number of results this function produces.
382    ///
383    /// # Example
384    ///
385    /// ```
386    /// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type};
387    /// # let mut store = Store::default();
388    /// # let env = FunctionEnv::new(&mut store, ());
389    /// #
390    /// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
391    ///     a + b
392    /// }
393    ///
394    /// let f = Function::new_typed_with_env(&mut store, &env, sum);
395    ///
396    /// assert_eq!(f.result_arity(&mut store), 1);
397    /// ```
398    #[inline]
399    pub fn result_arity(&self, store: &impl AsStoreRef) -> usize {
400        self.ty(store).params().len()
401    }
402
403    /// Call the `Function` function.
404    ///
405    /// Depending on where the Function is defined, it will call it.
406    /// 1. If the function is defined inside a WebAssembly, it will call the trampoline
407    ///    for the function signature.
408    /// 2. If the function is defined in the host (in a native way), it will
409    ///    call the trampoline.
410    ///
411    /// # Examples
412    ///
413    /// ```
414    /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value};
415    /// # use wasmer::FunctionEnv;
416    /// # let mut store = Store::default();
417    /// # let env = FunctionEnv::new(&mut store, ());
418    /// # let wasm_bytes = wat2wasm(r#"
419    /// # (module
420    /// #   (func (export "sum") (param $x i32) (param $y i32) (result i32)
421    /// #     local.get $x
422    /// #     local.get $y
423    /// #     i32.add
424    /// #   ))
425    /// # "#.as_bytes()).unwrap();
426    /// # let module = Module::new(&store, wasm_bytes).unwrap();
427    /// # let import_object = imports! {};
428    /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
429    /// #
430    /// let sum = instance.exports.get_function("sum").unwrap();
431    ///
432    /// assert_eq!(sum.call(&mut store, &[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]);
433    /// ```
434    #[inline]
435    pub fn call(
436        &self,
437        store: &mut impl AsStoreMut,
438        params: &[Value],
439    ) -> Result<Box<[Value]>, RuntimeError> {
440        match_rt!(on self => f {
441            f.call(store, params)
442        })
443    }
444
445    #[doc(hidden)]
446    #[allow(missing_docs)]
447    #[inline]
448    pub fn call_raw(
449        &self,
450        store: &mut impl AsStoreMut,
451        params: Vec<RawValue>,
452    ) -> Result<Box<[Value]>, RuntimeError> {
453        match_rt!(on self => f {
454            f.call_raw(store, params)
455        })
456    }
457
458    #[cfg(feature = "experimental-async")]
459    #[allow(clippy::type_complexity)]
460    pub fn call_async(
461        &self,
462        store: &impl AsStoreAsync,
463        params: Vec<Value>,
464    ) -> Pin<Box<dyn Future<Output = Result<Box<[Value]>, RuntimeError>> + 'static>> {
465        match self {
466            #[cfg(feature = "sys")]
467            Self::Sys(f) => f.call_async(store, params),
468            #[cfg(feature = "v8")]
469            Self::V8(_) => unsupported_async_future(),
470            #[cfg(feature = "js")]
471            Self::Js(f) => f.call_async(store, params),
472        }
473    }
474
475    #[inline]
476    pub(crate) fn vm_funcref(&self, store: &impl AsStoreRef) -> VMFuncRef {
477        match self {
478            #[cfg(feature = "sys")]
479            Self::Sys(f) => VMFuncRef::Sys(f.vm_funcref(store)),
480            #[cfg(feature = "v8")]
481            Self::V8(f) => VMFuncRef::V8(f.vm_funcref(store)),
482            #[cfg(feature = "js")]
483            Self::Js(f) => VMFuncRef::Js(f.vm_funcref(store)),
484        }
485    }
486
487    #[inline]
488    pub(crate) unsafe fn from_vm_funcref(store: &mut impl AsStoreMut, funcref: VMFuncRef) -> Self {
489        match &store.as_store_mut().inner.store {
490            #[cfg(feature = "sys")]
491            crate::BackendStore::Sys(s) => Self::Sys(unsafe {
492                crate::backend::sys::entities::function::Function::from_vm_funcref(
493                    store,
494                    funcref.unwrap_sys(),
495                )
496            }),
497            #[cfg(feature = "v8")]
498            crate::BackendStore::V8(s) => Self::V8(unsafe {
499                crate::backend::v8::entities::function::Function::from_vm_funcref(
500                    store,
501                    funcref.unwrap_v_8(),
502                )
503            }),
504            #[cfg(feature = "js")]
505            crate::BackendStore::Js(s) => Self::Js(unsafe {
506                crate::backend::js::entities::function::Function::from_vm_funcref(
507                    store,
508                    funcref.unwrap_js(),
509                )
510            }),
511        }
512    }
513
514    /// Transform this WebAssembly function into a typed function.
515    /// See [`TypedFunction`] to learn more.
516    ///
517    /// # Examples
518    ///
519    /// ```
520    /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value};
521    /// # use wasmer::FunctionEnv;
522    /// # let mut store = Store::default();
523    /// # let env = FunctionEnv::new(&mut store, ());
524    /// # let wasm_bytes = wat2wasm(r#"
525    /// # (module
526    /// #   (func (export "sum") (param $x i32) (param $y i32) (result i32)
527    /// #     local.get $x
528    /// #     local.get $y
529    /// #     i32.add
530    /// #   ))
531    /// # "#.as_bytes()).unwrap();
532    /// # let module = Module::new(&store, wasm_bytes).unwrap();
533    /// # let import_object = imports! {};
534    /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
535    /// #
536    /// let sum = instance.exports.get_function("sum").unwrap();
537    /// let sum_typed: TypedFunction<(i32, i32), i32> = sum.typed(&mut store).unwrap();
538    ///
539    /// assert_eq!(sum_typed.call(&mut store, 1, 2).unwrap(), 3);
540    /// ```
541    ///
542    /// # Errors
543    ///
544    /// If the `Args` generic parameter does not match the exported function
545    /// an error will be raised:
546    ///
547    /// ```should_panic
548    /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value};
549    /// # use wasmer::FunctionEnv;
550    /// # let mut store = Store::default();
551    /// # let env = FunctionEnv::new(&mut store, ());
552    /// # let wasm_bytes = wat2wasm(r#"
553    /// # (module
554    /// #   (func (export "sum") (param $x i32) (param $y i32) (result i32)
555    /// #     local.get $x
556    /// #     local.get $y
557    /// #     i32.add
558    /// #   ))
559    /// # "#.as_bytes()).unwrap();
560    /// # let module = Module::new(&store, wasm_bytes).unwrap();
561    /// # let import_object = imports! {};
562    /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
563    /// #
564    /// let sum = instance.exports.get_function("sum").unwrap();
565    ///
566    /// // This results in an error: `RuntimeError`
567    /// let sum_typed : TypedFunction<(i64, i64), i32> = sum.typed(&mut store).unwrap();
568    /// ```
569    ///
570    /// If the `Rets` generic parameter does not match the exported function
571    /// an error will be raised:
572    ///
573    /// ```should_panic
574    /// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value};
575    /// # use wasmer::FunctionEnv;
576    /// # let mut store = Store::default();
577    /// # let env = FunctionEnv::new(&mut store, ());
578    /// # let wasm_bytes = wat2wasm(r#"
579    /// # (module
580    /// #   (func (export "sum") (param $x i32) (param $y i32) (result i32)
581    /// #     local.get $x
582    /// #     local.get $y
583    /// #     i32.add
584    /// #   ))
585    /// # "#.as_bytes()).unwrap();
586    /// # let module = Module::new(&store, wasm_bytes).unwrap();
587    /// # let import_object = imports! {};
588    /// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
589    /// #
590    /// let sum = instance.exports.get_function("sum").unwrap();
591    ///
592    /// // This results in an error: `RuntimeError`
593    /// let sum_typed: TypedFunction<(i32, i32), i64> = sum.typed(&mut store).unwrap();
594    /// ```
595    #[inline]
596    pub fn typed<Args, Rets>(
597        &self,
598        store: &impl AsStoreRef,
599    ) -> Result<TypedFunction<Args, Rets>, RuntimeError>
600    where
601        Args: WasmTypeList,
602        Rets: WasmTypeList,
603    {
604        let ty = self.ty(store);
605
606        // type check
607        {
608            let expected = ty.params();
609            let given = Args::wasm_types();
610
611            if expected != given {
612                return Err(RuntimeError::new(format!(
613                    "given types (`{given:?}`) for the function arguments don't match the actual types (`{expected:?}`)",
614                )));
615            }
616        }
617
618        {
619            let expected = ty.results();
620            let given = Rets::wasm_types();
621
622            if expected != given {
623                // todo: error result types don't match
624                return Err(RuntimeError::new(format!(
625                    "given types (`{given:?}`) for the function results don't match the actual types (`{expected:?}`)",
626                )));
627            }
628        }
629
630        Ok(TypedFunction::new(store, super::Function(self.clone())))
631    }
632
633    pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternFunction) -> Self {
634        match &store.as_store_mut().inner.store {
635            #[cfg(feature = "sys")]
636            crate::BackendStore::Sys(_) => Self::Sys(
637                crate::backend::sys::entities::function::Function::from_vm_extern(store, vm_extern),
638            ),
639            #[cfg(feature = "v8")]
640            crate::BackendStore::V8(_) => Self::V8(
641                crate::backend::v8::entities::function::Function::from_vm_extern(store, vm_extern),
642            ),
643            #[cfg(feature = "js")]
644            crate::BackendStore::Js(_) => Self::Js(
645                crate::backend::js::entities::function::Function::from_vm_extern(store, vm_extern),
646            ),
647        }
648    }
649
650    /// Checks whether this `Function` can be used with the given store.
651    #[inline]
652    pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
653        match_rt!(on self => f {
654            f.is_from_store(store)
655        })
656    }
657
658    #[inline]
659    pub(crate) fn to_vm_extern(&self) -> VMExtern {
660        match_rt!(on self => f {
661            f.to_vm_extern()
662        })
663    }
664}
665
666#[cold]
667fn unsupported_async_backend(backend: &str) -> ! {
668    panic!(
669        "async host functions are only supported with the `sys` backend (attempted on {backend})"
670    )
671}
672
673#[allow(clippy::type_complexity)]
674pub(super) fn unsupported_async_future<'a>()
675-> Pin<Box<dyn Future<Output = Result<Box<[Value]>, RuntimeError>> + 'a>> {
676    Box::pin(async {
677        Err(RuntimeError::new(
678            "async calls are only supported with the `sys` backend",
679        ))
680    })
681}
682
683impl<'a> Exportable<'a> for BackendFunction {
684    fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
685        match _extern {
686            Extern::Function(func) => Ok(&func.0),
687            _ => Err(ExportError::IncompatibleType),
688        }
689    }
690}