-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Changing the return type of add_to_linker
closures
#8382
Comments
|
One other point I'd add is that I wouldn't take strict backwards compatibility as a constraint here. Everything that works today should continue to work, but beyond that it's fine if callers need a slightly different function call or annotations or such. |
It turns out the closure lifetime problems were due to a type inference limitation: rust-lang/rust#58052 This seems to work as a rough approach to improve on: use std::borrow::BorrowMut;
trait BorrowHost<T, U>: Send + Sync + 'static {
fn borrow_host<'a>(&self, data: &'a mut T) -> impl BorrowMut<U>
where
U: 'a;
}
impl<T, U, F> BorrowHost<T, U> for F
where
F: Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
{
fn borrow_host<'a>(&self, data: &'a mut T) -> impl BorrowMut<U> + 'a
where
U: 'a,
{
self(data)
}
}
pub fn add_to_linker<T, U>(
linker: &mut wasmtime::component::Linker<T>,
get: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> wasmtime::Result<()>
where
U: Host,
{
add_to_linker_borrow_host(linker, get)
}
fn add_to_linker_borrow_host<T, U: Host>(
linker: &mut wasmtime::component::Linker<T>,
getter: impl BorrowHost<T, U>,
) -> wasmtime::Result<()> {
let mut inst = linker.instance("foo")?;
inst.func_wrap(
"bar",
move |mut caller: wasmtime::StoreContextMut<'_, T>, (): ()| {
let mut host = getter.borrow_host(caller.data_mut());
host.borrow_mut().host_func();
Ok(())
},
)
}
// add_to_linker(linker, |data| &mut data.host)?; |
Nice that looks reasonable to me 👍 |
After some more iteration here I've come up with something that solves my problems. I'm not really happy with it but its the best compromise I've been able to make with the borrow checker: https://gist.github.com/lann/8d85f69ef334051206ee1c7c0897f0f4 If this looks acceptable I can PR it, though I'd also be happy if someone was able to refine the design further. |
Some minor cleanups on that:
One point I think is pretty important is that we'll need One other minor possibility might be to have: pub trait GetHost: Send + Sync + 'static {
type T;
type Host<'a>: Host;
fn get_host<'a>(&self, data: &'a mut Self::T) -> Self::Host<'a>;
} As I write that out though I don't think I like that, so probably scratch that. |
Oh also I'd generalize |
I added |
Heh yeah when I've tried to golf this stuff historically I've found that it's a very fine line to walk between rustc and usability here... |
I'll start on the PR. I also updated the gist with your suggestions in case someone is looking here before the PR is ready. |
I tried many variations with GATs but ended up playing whack-a-mole with various lifetime constraints. It may be possible to express this with a single generic |
This is what I was (vaguely) worried about: https://github.com/bytecodealliance/wasmtime/actions/runs/8805989303/job/24169783936?pr=8448#step:17:392 e.g.
|
From an out-of-band discussion, we're going to try:
|
From this Zulip discussion:
I've been experimenting with ways to provide reusable bits of host functionality and have run into a stumbling block with wasmtime's generated
add_to_linker
functions, which takeget
closures with types (roughly) like:These closures are usually trivial field accesses like
|data| &mut data.some_host_impl
, but this is somewhat limiting because you can only return&mut
s borrowing fromT
. As a specific example, the wasmtime-wasiWasiView::table
needs to be shared with wasmtime-wasi-http'sWasiHttpView::table
, but this currently requires both*View
implementations to use the same concrete type withinT
, making the two host implementations uncomposable.There are some
unsafe
approaches to deal with this but I'm wondering if it would be possible to change theadd_to_linker
closure signature to permit returning non-ref types, e.g. something thatimpl
sAsMut<U>
. I've been trying to find a way to do this backward-compatibility but I'm running into the limits of my understanding of closure lifetimeThe text was updated successfully, but these errors were encountered: