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