@@ -299,6 +299,13 @@ impl Instance {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `store` does not own this instance.
|
/// Panics if `store` does not own this instance.
|
||||||
|
///
|
||||||
|
/// # Why does `get_export` take a mutable context?
|
||||||
|
///
|
||||||
|
/// This method requires a mutable context because an instance's exports are
|
||||||
|
/// lazily populated, and we cache them as they are accessed. This makes
|
||||||
|
/// instantiating a module faster, but also means this method requires a
|
||||||
|
/// mutable context.
|
||||||
pub fn get_export(&self, mut store: impl AsContextMut, name: &str) -> Option<Extern> {
|
pub fn get_export(&self, mut store: impl AsContextMut, name: &str) -> Option<Extern> {
|
||||||
self._get_export(&mut store.as_context_mut().opaque(), name)
|
self._get_export(&mut store.as_context_mut().opaque(), name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,49 @@ pub trait AsContext {
|
|||||||
/// memory or globals. Creation of a [`Func`](crate::Func) will update internal
|
/// memory or globals. Creation of a [`Func`](crate::Func) will update internal
|
||||||
/// data structures. This ends up being quite a common bound in Wasmtime, but
|
/// data structures. This ends up being quite a common bound in Wasmtime, but
|
||||||
/// typically you can simply pass `&mut store` or `&mut caller` to satisfy it.
|
/// typically you can simply pass `&mut store` or `&mut caller` to satisfy it.
|
||||||
|
///
|
||||||
|
/// # Calling multiple methods that take `&mut impl AsContextMut`
|
||||||
|
///
|
||||||
|
/// As of Rust 1.53.0, [generic methods that take a generic `&mut T` do not get
|
||||||
|
/// "automatic reborrowing"][reborrowing] and therefore you cannot call multiple
|
||||||
|
/// generic methods with the same `&mut T` without manually inserting
|
||||||
|
/// reborrows. This affects the many `wasmtime` API methods that take `&mut impl
|
||||||
|
/// AsContextMut`.
|
||||||
|
///
|
||||||
|
/// For example, this fails to compile because the context is moved into the
|
||||||
|
/// first call:
|
||||||
|
///
|
||||||
|
/// ```compile_fail
|
||||||
|
/// use wasmtime::{AsContextMut, Instance};
|
||||||
|
///
|
||||||
|
/// fn foo(cx: &mut impl AsContextMut, instance: Instance) {
|
||||||
|
/// // `cx` is not reborrowed, but moved into this call.
|
||||||
|
/// let my_export = instance.get_export(cx, "my_export");
|
||||||
|
///
|
||||||
|
/// // Therefore, this use of `cx` is a use-after-move and prohibited by the
|
||||||
|
/// // borrow checker.
|
||||||
|
/// let other_export = instance.get_export(cx, "other_export");
|
||||||
|
/// # drop((my_export, other_export));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// To fix this, manually insert reborrows like `&mut *cx` that would otherwise
|
||||||
|
/// normally be inserted automatically by the Rust compiler for non-generic
|
||||||
|
/// methods:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use wasmtime::{AsContextMut, Instance};
|
||||||
|
///
|
||||||
|
/// fn foo(cx: &mut impl AsContextMut, instance: Instance) {
|
||||||
|
/// let my_export = instance.get_export(&mut *cx, "my_export");
|
||||||
|
///
|
||||||
|
/// // This works now, since `cx` was reborrowed above, rather than moved!
|
||||||
|
/// let other_export = instance.get_export(&mut *cx, "other_export");
|
||||||
|
/// # drop((my_export, other_export));
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [reborrowing]: https://github.com/rust-lang/rust/issues/85161
|
||||||
pub trait AsContextMut: AsContext {
|
pub trait AsContextMut: AsContext {
|
||||||
/// Returns the store context that this type provides access to.
|
/// Returns the store context that this type provides access to.
|
||||||
fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data>;
|
fn as_context_mut(&mut self) -> StoreContextMut<'_, Self::Data>;
|
||||||
|
|||||||
Reference in New Issue
Block a user