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