jdejaegh opened issue #11700:
Hello,
I recently updated the wasmtime dependency in one of my projects (from v32 to v36, to be on the LTS). I am mainly using the component model and resources. Since the update, I am having trouble understanding how to deal with the data in the
Store.Here is my use-case: I use components to update methods of structs at runtime. I wrote a procedural macro to generate the code needed to check if a component is available to update the method at runtime. If a component is available, I load it and call the corresponding function in the component. To have a meaningful example, I removed the procedural macro part and reduced the code to a minimum (non) working example.
In wasmtime v32, I could handle a call to a method as follows:
```rust
pub fn greet(&self) {
let plugin = get_wasm_component("person_plugin");
if let Ok((engine, component, mut linker)) = plugin {
let mut data = StatePerson::default();
let res_idx = 0_u32;
data.person_table.insert(res_idx, MaybePerson::NotMut(self));
let self_res = Resource::new_borrow(res_idx);let mut store = Store::new(&engine, data); person_bindings::example::plugin::imp::add_to_linker(&mut linker, |state| state).unwrap(); person_bindings::example::plugin::printer::add_to_linker(&mut linker, |state| state).unwrap(); let bindings = person_bindings::PersonPlugin::instantiate(&mut store, &component, &linker).unwrap(); bindings.call_greet(&mut store, self_res).unwrap() } else { self.greet_internal() } }Since I updated to wasmtime v36, I am unable to use this logic. The change was probably introduced in a version between 32 and 36 and is probably related to https://github.com/bytecodealliance/wasmtime/pull/10760. I added the type annotations on `add_to_linker` as required, but the compiler complains about this: ```text error[E0521]: borrowed data escapes outside of method --> src/main.rs:65:29 | 57 | pub fn greet(&self) { | ----- | | | `self` is a reference that is only valid in the method body | let's call the lifetime of this reference `'1` ... 65 | let mut store = Store::new(&engine, data); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | | | `self` escapes the method body here | argument requires that `'1` must outlive `'static`As I understand, the compiler wants me to have a
'staticlifetime onself(which I don't really want to have). I tried to have thestoredestroyed at the end of the function by callingstore.into_data()without success.Is there a way to use wasmtime v36 in this setup?
Here is a minimum working example of my code: https://github.com/jdejaegh/wasmtime-32-to-36-bug
Thanks for the help :)
alexcrichton commented on issue #11700:
Thanks for the report, and this is indeed an intentional consequence of https://github.com/bytecodealliance/wasmtime/pull/10760. Unfortunately there's no simple trick to get previous code relying on non-
'staticvalues working like it was before. Various refactorings you could possibly apply are:
- You could store
datain TLS via a mechanism like scoped-tls. This would mean yourTinStore<T>would be()or something trivial and data would actually be accessed through TLS.- You could refactor data in
selfto be clone-able or otherwise not connected toself. For example usingRcorArcor similar.- You could "lie" and have the store data be
*const Footo subvert the borrow checker (I wouldn't recommend this though)
jdejaegh closed issue #11700:
Hello,
I recently updated the wasmtime dependency in one of my projects (from v32 to v36, to be on the LTS). I am mainly using the component model and resources. Since the update, I am having trouble understanding how to deal with the data in the
Store.Here is my use-case: I use components to update methods of structs at runtime. I wrote a procedural macro to generate the code needed to check if a component is available to update the method at runtime. If a component is available, I load it and call the corresponding function in the component. To have a meaningful example, I removed the procedural macro part and reduced the code to a minimum (non) working example.
In wasmtime v32, I could handle a call to a method as follows:
```rust
pub fn greet(&self) {
let plugin = get_wasm_component("person_plugin");
if let Ok((engine, component, mut linker)) = plugin {
let mut data = StatePerson::default();
let res_idx = 0_u32;
data.person_table.insert(res_idx, MaybePerson::NotMut(self));
let self_res = Resource::new_borrow(res_idx);let mut store = Store::new(&engine, data); person_bindings::example::plugin::imp::add_to_linker(&mut linker, |state| state).unwrap(); person_bindings::example::plugin::printer::add_to_linker(&mut linker, |state| state).unwrap(); let bindings = person_bindings::PersonPlugin::instantiate(&mut store, &component, &linker).unwrap(); bindings.call_greet(&mut store, self_res).unwrap() } else { self.greet_internal() } }Since I updated to wasmtime v36, I am unable to use this logic. The change was probably introduced in a version between 32 and 36 and is probably related to https://github.com/bytecodealliance/wasmtime/pull/10760. I added the type annotations on `add_to_linker` as required, but the compiler complains about this: ```text error[E0521]: borrowed data escapes outside of method --> src/main.rs:65:29 | 57 | pub fn greet(&self) { | ----- | | | `self` is a reference that is only valid in the method body | let's call the lifetime of this reference `'1` ... 65 | let mut store = Store::new(&engine, data); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | | | `self` escapes the method body here | argument requires that `'1` must outlive `'static`As I understand, the compiler wants me to have a
'staticlifetime onself(which I don't really want to have). I tried to have thestoredestroyed at the end of the function by callingstore.into_data()without success.Is there a way to use wasmtime v36 in this setup?
Here is a minimum working example of my code: https://github.com/jdejaegh/wasmtime-32-to-36-bug
Thanks for the help :)
jdejaegh commented on issue #11700:
Thanks for the reply. Unfortunately, none of the options suggested worked with the example.
- Using a TLS requires that the data in there is
'staticas well. This would includeselfwhich is not possible to have'statichere.- The crate I want to produce should be "
self-agnostic": what is inselfshould not prevent the call from working. The goal is to provide a macro to users so they can apply it on any struct and have some methods replaced by WebAssembly calls. I would like to avoid restricting whatselfcan be.- I did not investigate much in the last option.
I ended up using the unsafe
std::mem::transmutesimilarly to what was done inwasmtime 32: convert the lifetime to'static.Here is how I applied it in my case:
let mut data = StatePerson::default(); let res_idx = 0_u32; - data.person_table.insert(res_idx, MaybePerson::NotMut(self)); + data.person_table.insert(res_idx, MaybePerson::NotMut(unsafe {std::mem::transmute::<&'_ Person, &'static Person>(self)})); let self_res = Resource::new_borrow(res_idx); let mut store = Store::new(&engine, data); ``` ~~~
Last updated: Dec 06 2025 at 06:05 UTC