1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
use crate::store::{Store, StoreInner};
/// A temporary handle to a [`&Store<T>`][`Store`].
///
/// This type is sutable for [`AsContext`] trait bounds on methods if desired.
/// For more information, see [`Store`].
// NB the repr(transparent) here is for the C API and it's important that the
// representation of this `struct` is a pointer for now. If the representation
// changes then the C API will need to be updated
#[repr(transparent)]
pub struct StoreContext<'a, T>(pub(crate) &'a StoreInner<T>);
/// A temporary handle to a [`&mut Store<T>`][`Store`].
///
/// This type is sutable for [`AsContextMut`] or [`AsContext`] trait bounds on
/// methods if desired. For more information, see [`Store`].
// NB the repr(transparent) here is for the same reason as above.
#[repr(transparent)]
pub struct StoreContextMut<'a, T>(pub(crate) &'a mut StoreInner<T>);
impl<'a, T> StoreContextMut<'a, T> {
/// One of the unsafe lynchpins of Wasmtime.
///
/// This method is called from one location, `Caller::with`, and is where we
/// load the raw unsafe trait object pointer from a `*mut VMContext` and
/// then cast it back to a `StoreContextMut`. This is naturally unsafe due
/// to the raw pointer usage, but it's also unsafe because `T` here needs to
/// line up with the `T` used to define the trait object itself.
///
/// This should generally be achieved with various trait bounds throughout
/// Wasmtime that might give access to the `Caller<'_, T>` type.
/// Unfortunately there's not a ton of debug asserts we can add here, so we
/// rely on testing to largely help show that this is correctly used.
pub(crate) unsafe fn from_raw(
store: *mut dyn wasmtime_runtime::Store,
) -> StoreContextMut<'a, T> {
StoreContextMut(&mut *(store as *mut StoreInner<T>))
}
}
/// A trait used to get shared access to a [`Store`] in Wasmtime.
///
/// This trait is used as a bound on the first argument of many methods within
/// Wasmtime. This trait is implemented for types like [`Store`],
/// [`Caller`](crate::Caller), and [`StoreContext`] itself. Implementors of this
/// trait provide access to a [`StoreContext`] via some means, allowing the
/// method in question to get access to the store's internal information.
///
/// Note that this is only used in contexts where the store's information is
/// read, but not written. For example methods that return type information will
/// use this trait as a bound. More commonly, though, mutation is required and
/// [`AsContextMut`] is needed.
pub trait AsContext {
/// The host information associated with the [`Store`], aka the `T` in
/// [`Store<T>`].
type Data;
/// Returns the store context that this type provides access to.
fn as_context(&self) -> StoreContext<'_, Self::Data>;
}
/// A trait used to get exclusive mutable access to a [`Store`] in Wasmtime.
///
/// This trait is used as a bound on the first argument of many methods within
/// Wasmtime. This trait is implemented for types like [`Store`],
/// [`Caller`](crate::Caller), and [`StoreContextMut`] itself. Implementors of
/// this trait provide access to a [`StoreContextMut`] via some means, allowing
/// the method in question to get access to the store's internal information.
///
/// This is notably used for methods that may require some mutation of the
/// [`Store`] itself. For example calling a wasm function can mutate linear
/// memory or globals. Creation of a [`Func`](crate::Func) will update internal
/// data structures. This ends up being quite a common bound in Wasmtime, but
/// typically you can simply pass `&mut store` or `&mut caller` to satisfy it.
///
/// # Calling multiple methods that take `&mut impl AsContextMut`
///
/// As of Rust 1.53.0, [generic methods that take a generic `&mut T` do not get
/// "automatic reborrowing"][reborrowing] and therefore you cannot call multiple
/// generic methods with the same `&mut T` without manually inserting
/// reborrows. This affects the many `wasmtime` API methods that take `&mut impl
/// AsContextMut`.
///
/// For example, this fails to compile because the context is moved into the
/// first call:
///
/// ```compile_fail
/// use wasmtime::{AsContextMut, Instance};
///
/// fn foo(cx: &mut impl AsContextMut, instance: Instance) {
/// // `cx` is not reborrowed, but moved into this call.
/// let my_export = instance.get_export(cx, "my_export");
///
/// // Therefore, this use of `cx` is a use-after-move and prohibited by the
/// // borrow checker.
/// let other_export = instance.get_export(cx, "other_export");
/// # drop((my_export, other_export));
/// }
/// ```
///
/// To fix this, manually insert reborrows like `&mut *cx` that would otherwise
/// normally be inserted automatically by the Rust compiler for non-generic
/// methods:
///
/// ```
/// use wasmtime::{AsContextMut, Instance};
///
/// fn foo(cx: &mut impl AsContextMut, instance: Instance) {
/// let my_export = instance.get_export(&mut *cx, "my_export");
///
/// // This works now, since `cx` was reborrowed above, rather than moved!
/// let other_export = instance.get_export(&mut *cx, "other_export");
/// # drop((my_export, other_export));
/// }
/// ```
///
/// [reborrowing]: https://github.com/rust-lang/rust/issues/85161
pub trait AsContextMut: AsContext {
/// Returns the store context that this type provides access to.
fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data>;
}
impl<T> AsContext for Store<T> {
type Data = T;
#[inline]
fn as_context(&self) -> StoreContext<'_, T> {
StoreContext(&self.inner)
}
}
impl<T> AsContextMut for Store<T> {
#[inline]
fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
StoreContextMut(&mut self.inner)
}
}
impl<T> AsContext for StoreContext<'_, T> {
type Data = T;
#[inline]
fn as_context(&self) -> StoreContext<'_, T> {
StoreContext(&*self.0)
}
}
impl<T> AsContext for StoreContextMut<'_, T> {
type Data = T;
#[inline]
fn as_context(&self) -> StoreContext<'_, T> {
StoreContext(&*self.0)
}
}
impl<T> AsContextMut for StoreContextMut<'_, T> {
#[inline]
fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
StoreContextMut(&mut *self.0)
}
}
// Implementations for internal consumers, but these aren't public types so
// they're not publicly accessible for crate consumers.
impl<T> AsContext for &'_ StoreInner<T> {
type Data = T;
#[inline]
fn as_context(&self) -> StoreContext<'_, T> {
StoreContext(self)
}
}
impl<T> AsContext for &'_ mut StoreInner<T> {
type Data = T;
#[inline]
fn as_context(&self) -> StoreContext<'_, T> {
StoreContext(self)
}
}
impl<T> AsContextMut for &'_ mut StoreInner<T> {
#[inline]
fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
StoreContextMut(&mut **self)
}
}
// forward AsContext for &T
impl<T: AsContext> AsContext for &'_ T {
type Data = T::Data;
#[inline]
fn as_context(&self) -> StoreContext<'_, T::Data> {
T::as_context(*self)
}
}
// forward AsContext for &mut T
impl<T: AsContext> AsContext for &'_ mut T {
type Data = T::Data;
#[inline]
fn as_context(&self) -> StoreContext<'_, T::Data> {
T::as_context(*self)
}
}
// forward AsContextMut for &mut T
impl<T: AsContextMut> AsContextMut for &'_ mut T {
#[inline]
fn as_context_mut(&mut self) -> StoreContextMut<'_, T::Data> {
T::as_context_mut(*self)
}
}
//
impl<'a, T: AsContext> From<&'a T> for StoreContext<'a, T::Data> {
fn from(t: &'a T) -> StoreContext<'a, T::Data> {
t.as_context()
}
}
impl<'a, T: AsContext> From<&'a mut T> for StoreContext<'a, T::Data> {
fn from(t: &'a mut T) -> StoreContext<'a, T::Data> {
T::as_context(t)
}
}
impl<'a, T: AsContextMut> From<&'a mut T> for StoreContextMut<'a, T::Data> {
fn from(t: &'a mut T) -> StoreContextMut<'a, T::Data> {
t.as_context_mut()
}
}