Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relaxing static lifetime of Func::wrap arguments #2159

Closed
bkolobara opened this issue Aug 24, 2020 · 8 comments
Closed

Relaxing static lifetime of Func::wrap arguments #2159

bkolobara opened this issue Aug 24, 2020 · 8 comments

Comments

@bkolobara
Copy link

Hi! I'm trying to use Wasmtime inside a generator. I would like to provide a host function to suspend the execution by yielding from the generator. This is my current attempt:

let _ = Generator::new(move |yielder| {
    let suspend = Func::wrap(&store, move |param: i32| {
        yielder.suspend();
    });

    let instance = Instance::new(&store, &module, &[suspend.into()]).unwrap();
}

I had now multiple attempts of passing yielder inside the closure, but nothing worked. I always get a lifetime related error:

= note: expected `gen::Generator<'_, _>`
           found `gen::Generator<'_, _>`
= note: but, the lifetime must be valid for the static lifetime...

It's not clear to me why the passed in closure needs to be static. Can this requirement be relaxed? Or is there maybe a better way of approaching this?

Could yielder be attached to Caller and then later accessed?

@bjorn3
Copy link
Contributor

bjorn3 commented Aug 24, 2020

The 'static bound comes from

$($args: WasmTy,)*
and
F: Fn(Caller<'_>, $( $args ),*) -> R + 'static,

@bjorn3
Copy link
Contributor

bjorn3 commented Aug 24, 2020

This bound is necessary because Func has a static lifetime itself, as it doesn't have any lifetime parameters:

pub struct Func {
instance: StoreInstanceHandle,
trampoline: VMTrampoline,
export: wasmtime_runtime::ExportFunction,
}

@bjorn3
Copy link
Contributor

bjorn3 commented Aug 24, 2020

Which in turn is necessary because Instance itself doesn't have a lifetime parameter:

pub struct Instance {
pub(crate) handle: StoreInstanceHandle,
store: Store,
module: Module,
}

@alexcrichton
Copy link
Member

Due to the memory management of wasm objects right now (e.g. instances and stores) everything must live for the 'static lifetime and you can't have stack-borrowed data. Fixing this would require some sort of lifetime on a Store and everything connected to it which would be a very significant investment, and one that I'm not entirely sure is possible.

It's worth noting though that a form of stack switching like you're trying to use is something we're interested in providing first-class support for. There's a few wasm proposals in flight but we'd like to have something at least for async in the meantime as well. Basically just to say that this is likely to be supported in some fashion in the future.

@bkolobara
Copy link
Author

Thank you for the feedback! I will probably just cast it to a pointer and back to "cheat" the lifetime. The function will be only called while inside the closure, so it should be safe.

It's worth noting though that a form of stack switching like you're trying to use is something we're interested in providing first-class support for. There's a few wasm proposals in flight but we'd like to have something at least for async in the meantime as well. Basically just to say that this is likely to be supported in some fashion in the future.

I'm really interested in this. Are there maybe some issues open where I could follow the development of this or some places where the discussion was started? I could not find any active proposals regarding it.

@pchickey
Copy link
Contributor

pchickey commented Aug 25, 2020

Andreas Rossberg has presented at several CG meetings in the past year about approaches to stack switching based on delimited continuations. It does not appear that there is any formal proposal work in https://github.com/WebAssembly/proposals at this time, but the work is something the Bytecode Alliance is very interested in implementing.

Lucet already has some limited support for stack switching (it is not as general or powerful as Andreas's proposal) and this PR uses it to enable async computations which suspend the wasm stack. We will need to implement something similar in Wasmtime as part of our plans to merge the features of the two runtimes. bytecodealliance/lucet#551

@peterhuene
Copy link
Member

peterhuene commented Aug 25, 2020

I've also toyed with using a generator (from the generator crate) to "async-ify" a host function. It also needed to cast away the lifetime of the closure's argument.

I am looking forward to first-class support for this in Wasmtime.

@bkolobara
Copy link
Author

Thank you everyone for the discussion. The restrictions are much clearer to me now. I will close this issue as I don't think there is any straightforward way right now to reduce the lifetime from 'static.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants