wasmtime/runtime/
gc.rs

1#[cfg(feature = "gc")]
2mod enabled;
3#[cfg(feature = "gc")]
4pub use enabled::*;
5
6#[cfg(not(feature = "gc"))]
7mod disabled;
8#[cfg(not(feature = "gc"))]
9pub use disabled::*;
10
11mod noextern;
12pub use noextern::NoExtern;
13
14mod none_ref;
15pub use none_ref::NoneRef;
16
17use core::fmt;
18use core::ops::Deref;
19
20/// A common trait implemented by all garbage-collected reference types.
21///
22/// This is a sealed trait, and may not be implemented for any types outside of
23/// the `wasmtime` crate.
24pub trait GcRef: GcRefImpl {}
25
26impl<T> GcRef for T where T: GcRefImpl {}
27
28/// A trait implemented for GC references that are guaranteed to be rooted:
29///
30/// * [`Rooted<T>`][crate::Rooted]
31/// * [`ManuallyRooted<T>`][crate::ManuallyRooted]
32///
33/// You can use this to abstract over the different kinds of rooted GC
34/// references. Note that `Deref<Target = T>` is a supertrait for
35/// `RootedGcRef<T>`, so all rooted GC references deref to their underlying `T`,
36/// allowing you to call its methods.
37///
38/// This is a sealed trait, and may not be implemented for any types outside of
39/// the `wasmtime` crate.
40pub trait RootedGcRef<T>: RootedGcRefImpl<T> + Deref<Target = T>
41where
42    T: GcRef,
43{
44}
45
46impl<T, U> RootedGcRef<T> for U
47where
48    T: GcRef,
49    U: RootedGcRefImpl<T> + Deref<Target = T>,
50{
51}
52
53/// An error returned when attempting to allocate a GC-managed object, but the
54/// GC heap is out of memory.
55///
56/// This error wraps an inner `T` value -- which is the host value, if any, that
57/// was passed to [`ExternRef::new`][crate::ExternRef::new] -- and you can
58/// recover this value via the
59/// [`into_inner`][crate::GcHeapOutOfMemory::into_inner] method. This lets you
60/// try to allocate the `externref` again, after performing a GC to hopefully
61/// free up space in the heap, or otherwise do whatever you want with the inner
62/// value.
63///
64/// For errors that occur when attempting to allocate non-`externref` objects
65/// when the GC heap is at capacity, the `T` type parameter is just the unit
66/// type `()`.
67pub struct GcHeapOutOfMemory<T> {
68    inner: T,
69    bytes_needed: u64,
70}
71
72impl<T> fmt::Debug for GcHeapOutOfMemory<T> {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        fmt::Display::fmt(self, f)
75    }
76}
77
78impl<T> fmt::Display for GcHeapOutOfMemory<T> {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        write!(
81            f,
82            "GC heap out of memory: no capacity for allocation of {} bytes",
83            self.bytes_needed
84        )
85    }
86}
87
88impl<T> core::error::Error for GcHeapOutOfMemory<T> {}
89
90impl<T> GcHeapOutOfMemory<T> {
91    pub(crate) fn new(inner: T, bytes_needed: u64) -> Self {
92        Self {
93            inner,
94            bytes_needed,
95        }
96    }
97
98    #[cfg(feature = "gc")]
99    pub(crate) fn bytes_needed(&self) -> u64 {
100        self.bytes_needed
101    }
102
103    #[cfg(feature = "gc")]
104    pub(crate) fn map_inner<U>(self, f: impl FnOnce(T) -> U) -> GcHeapOutOfMemory<U> {
105        GcHeapOutOfMemory {
106            inner: f(self.inner),
107            bytes_needed: self.bytes_needed,
108        }
109    }
110
111    /// Recover this error's inner host value.
112    pub fn into_inner(self) -> T {
113        self.inner
114    }
115
116    /// Take this error's inner host value, but also retain this
117    /// `GcHeapOutOfMemory` with `T` replaced with `()`.
118    ///
119    /// This allows you to both extract the inner `T` if necessary, and also
120    /// pass the `GcHeapOutOfMemory` error to [`Store::gc`][crate::Store::gc]
121    /// calls.
122    pub fn take_inner(self) -> (T, GcHeapOutOfMemory<()>) {
123        (self.inner, GcHeapOutOfMemory::new((), self.bytes_needed))
124    }
125}