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