1 use 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)]
11 pub struct StoreContext<'a, T: 'static>(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)]
19 pub struct StoreContextMut<'a, T: 'static>(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.
33 pub trait AsContext {
34     /// The host information associated with the [`Store`], aka the `T` in
35     /// [`Store<T>`].
36     type Data: 'static;
37 
38     /// Returns the store context that this type provides access to.
as_context(&self) -> StoreContext<'_, Self::Data>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
98 pub trait AsContextMut: AsContext {
99     /// Returns the store context that this type provides access to.
as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data>100     fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data>;
101 }
102 
103 impl<T: 'static> AsContext for Store<T> {
104     type Data = T;
105 
106     #[inline]
as_context(&self) -> StoreContext<'_, T>107     fn as_context(&self) -> StoreContext<'_, T> {
108         StoreContext(&self.inner)
109     }
110 }
111 
112 impl<T: 'static> AsContextMut for Store<T> {
113     #[inline]
as_context_mut(&mut self) -> StoreContextMut<'_, T>114     fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
115         StoreContextMut(&mut self.inner)
116     }
117 }
118 
119 impl<T: 'static> AsContext for StoreContext<'_, T> {
120     type Data = T;
121 
122     #[inline]
as_context(&self) -> StoreContext<'_, T>123     fn as_context(&self) -> StoreContext<'_, T> {
124         StoreContext(&*self.0)
125     }
126 }
127 
128 impl<T: 'static> AsContext for StoreContextMut<'_, T> {
129     type Data = T;
130 
131     #[inline]
as_context(&self) -> StoreContext<'_, T>132     fn as_context(&self) -> StoreContext<'_, T> {
133         StoreContext(&*self.0)
134     }
135 }
136 
137 impl<T: 'static> AsContextMut for StoreContextMut<'_, T> {
138     #[inline]
as_context_mut(&mut self) -> StoreContextMut<'_, T>139     fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
140         StoreContextMut(&mut *self.0)
141     }
142 }
143 
144 impl<'a, T: 'static> From<StoreContextMut<'a, T>> for StoreContext<'a, T> {
145     #[inline]
from(store: StoreContextMut<'a, T>) -> StoreContext<'a, T>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.
153 impl<T: 'static> AsContext for &'_ StoreInner<T> {
154     type Data = T;
155 
156     #[inline]
as_context(&self) -> StoreContext<'_, T>157     fn as_context(&self) -> StoreContext<'_, T> {
158         StoreContext(self)
159     }
160 }
161 
162 impl<T: 'static> AsContext for &'_ mut StoreInner<T> {
163     type Data = T;
164 
165     #[inline]
as_context(&self) -> StoreContext<'_, T>166     fn as_context(&self) -> StoreContext<'_, T> {
167         StoreContext(self)
168     }
169 }
170 
171 impl<T: 'static> AsContextMut for &'_ mut StoreInner<T> {
172     #[inline]
as_context_mut(&mut self) -> StoreContextMut<'_, T>173     fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
174         StoreContextMut(&mut **self)
175     }
176 }
177 
178 // forward AsContext for &T
179 impl<T: AsContext> AsContext for &'_ T {
180     type Data = T::Data;
181 
182     #[inline]
as_context(&self) -> StoreContext<'_, T::Data>183     fn as_context(&self) -> StoreContext<'_, T::Data> {
184         T::as_context(*self)
185     }
186 }
187 
188 // forward AsContext for &mut T
189 impl<T: AsContext> AsContext for &'_ mut T {
190     type Data = T::Data;
191 
192     #[inline]
as_context(&self) -> StoreContext<'_, T::Data>193     fn as_context(&self) -> StoreContext<'_, T::Data> {
194         T::as_context(*self)
195     }
196 }
197 
198 // forward AsContextMut for &mut T
199 impl<T: AsContextMut> AsContextMut for &'_ mut T {
200     #[inline]
as_context_mut(&mut self) -> StoreContextMut<'_, T::Data>201     fn as_context_mut(&mut self) -> StoreContextMut<'_, T::Data> {
202         T::as_context_mut(*self)
203     }
204 }
205 
206 //
207 impl<'a, T: AsContext> From<&'a T> for StoreContext<'a, T::Data> {
from(t: &'a T) -> StoreContext<'a, T::Data>208     fn from(t: &'a T) -> StoreContext<'a, T::Data> {
209         t.as_context()
210     }
211 }
212 
213 impl<'a, T: AsContext> From<&'a mut T> for StoreContext<'a, T::Data> {
from(t: &'a mut T) -> StoreContext<'a, T::Data>214     fn from(t: &'a mut T) -> StoreContext<'a, T::Data> {
215         T::as_context(t)
216     }
217 }
218 
219 impl<'a, T: AsContextMut> From<&'a mut T> for StoreContextMut<'a, T::Data> {
from(t: &'a mut T) -> StoreContextMut<'a, T::Data>220     fn from(t: &'a mut T) -> StoreContextMut<'a, T::Data> {
221         t.as_context_mut()
222     }
223 }
224