1 #[cfg(feature = "gc")]
2 mod enabled;
3 #[cfg(feature = "gc")]
4 pub use enabled::*;
5 
6 #[cfg(not(feature = "gc"))]
7 mod disabled;
8 #[cfg(not(feature = "gc"))]
9 pub use disabled::*;
10 
11 mod noextern;
12 pub use noextern::NoExtern;
13 
14 mod none_ref;
15 pub use none_ref::NoneRef;
16 
17 use core::fmt;
18 use 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.
24 pub trait GcRef: GcRefImpl {}
25 
26 impl<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 /// * [`OwnedRooted<T>`][crate::OwnedRooted]
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.
40 pub trait RootedGcRef<T>: RootedGcRefImpl<T> + Deref<Target = T>
41 where
42     T: GcRef,
43 {
44 }
45 
46 impl<T, U> RootedGcRef<T> for U
47 where
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 `()`.
67 pub struct GcHeapOutOfMemory<T> {
68     inner: T,
69     bytes_needed: u64,
70 }
71 
72 impl<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 
78 impl<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 
88 impl<T> core::error::Error for GcHeapOutOfMemory<T> {}
89 
90 impl<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 }
126