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}