wasmtime/runtime/store/
context.rs

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