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

Update host bindgen to match wit-bindgen's owned type generation #6124

Closed
philpax opened this issue Mar 30, 2023 · 3 comments · Fixed by #6189
Closed

Update host bindgen to match wit-bindgen's owned type generation #6124

philpax opened this issue Mar 30, 2023 · 3 comments · Fixed by #6189

Comments

@philpax
Copy link

philpax commented Mar 30, 2023

Feature

wit-bindgen recently updated its code generation to generate owned-only types by default:

bytecodealliance/wit-bindgen#547
bytecodealliance/wit-bindgen#552

I would like wasmtime to match this.

Benefit

As mentioned in bytecodealliance/wit-bindgen#535, binding generation of borrowed types can be tedious with nested types. Owned types simplify this.

Implementation

Porting over the changes from wit-bindgen should be sufficient.

@alexcrichton
Copy link
Member

I think that this is already done, but have you found differently when using the wasmtime::component::bindgen! macro?

@philpax
Copy link
Author

philpax commented Apr 5, 2023

We've actually refactored our code to make it less necessary now, but

[package]
name = "wit-bindgen-borrow-bug-repro"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
wasmtime = { git = "https://github.com/bytecodealliance/wasmtime.git", rev = "51e8eafff2b0bb2a10efb1452a23c4c9feff4261", features = ["component-model"] }
default world bindings {
    export exp: self.exp
    import imp: self.imp
}

interface common {
    type value = list<tuple<>>
    type entity = list<tuple<u32, value>>
}

interface exp {
    use self.common.{entity}
    exp: func(a: entity) -> entity
}

interface imp {
    use self.common.{entity}
    imp: func(a: entity) -> entity
}
wasmtime::component::bindgen!("main.bindings");

fn main() {
    println!("Hello, world!");
}

The bindgen generates Param and Result types:

#[allow(clippy::all)]
pub mod common {
    #[allow(unused_imports)]
    use wasmtime::component::__internal::anyhow;
    pub type ValueParam<'a> = &'a [()];
    const _: () = {
        {
            if !(8 == <ValueParam as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <ValueParam as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub type ValueResult = Vec<()>;
    const _: () = {
        {
            if !(8 == <ValueResult as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <ValueResult as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub type EntityParam<'a> = &'a [(u32, ValueParam<'a>)];
    const _: () = {
        {
            if !(8 == <EntityParam as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <EntityParam as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub type EntityResult = Vec<(u32, ValueResult)>;
    const _: () = {
        {
            if !(8 == <EntityResult as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <EntityResult as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub trait Host {}
    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,
    {
        let mut inst = linker.instance("common")?;
        Ok(())
    }
}
#[allow(clippy::all)]
pub mod imp {
    #[allow(unused_imports)]
    use wasmtime::component::__internal::anyhow;
    pub type Entity = super::common::EntityResult;
    const _: () = {
        {
            if !(8 == <Entity as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <Entity as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub trait Host {
        fn imp(&mut self, a: Entity) -> wasmtime::Result<Entity>;
    }
    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,
    {
        let mut inst = linker.instance("imp")?;
        inst.func_wrap(
            "imp",
            move |mut caller: wasmtime::StoreContextMut<'_, T>, (arg0,): (Entity,)| {
                let host = get(caller.data_mut());
                let r = host.imp(arg0);
                Ok((r?,))
            },
        )?;
        Ok(())
    }
}
#[allow(clippy::all)]
pub mod exp {
    #[allow(unused_imports)]
    use wasmtime::component::__internal::anyhow;
    pub type EntityParam<'a> = super::common::EntityParam<'a>;
    const _: () = {
        {
            if !(8 == <EntityParam as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <EntityParam as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub type EntityResult = super::common::EntityResult;
    const _: () = {
        {
            if !(8 == <EntityResult as wasmtime::component::ComponentType>::SIZE32) {
                $crate::panicking::panic("explicit panic");
            }
        };
        {
            if !(4 == <EntityResult as wasmtime::component::ComponentType>::ALIGN32) {
                $crate::panicking::panic("explicit panic");
            }
        };
    };
    pub struct Exp {
        exp: wasmtime::component::Func,
    }
    impl Exp {
        pub fn new(
            __exports: &mut wasmtime::component::ExportInstance<'_, '_>,
        ) -> wasmtime::Result<Exp> {
            let exp = *__exports
                .typed_func::<(EntityParam<'_>,), (EntityResult,)>("exp")?
                .func();
            Ok(Exp { exp })
        }
        pub fn call_exp<S: wasmtime::AsContextMut>(
            &self,
            mut store: S,
            arg0: EntityParam<'_>,
        ) -> wasmtime::Result<EntityResult> {
            let callee = unsafe {
                wasmtime::component::TypedFunc::<(EntityParam<'_>,), (EntityResult,)>::new_unchecked(
                    self.exp,
                )
            };
            let (ret0,) = callee.call(store.as_context_mut(), (arg0,))?;
            callee.post_return(store.as_context_mut())?;
            Ok(ret0)
        }
    }
}

@alexcrichton
Copy link
Member

Ah ok, thanks for the example!

alexcrichton added a commit to alexcrichton/wasmtime that referenced this issue Apr 10, 2023
This commit is a mirror of bytecodealliance/wit-bindgen#547 into the
`bindgen!` macro for Wasmtime. The new default is to generate only one
Rust type per WIT type input, regardless of if the representation can be
slightly more optimal in niche cases with more borrows. This should make
the macro easier to work with in the limit ideally.

Closes bytecodealliance#6124
brendandburns pushed a commit to brendandburns/wasmtime that referenced this issue Apr 13, 2023
…ance#6189)

This commit is a mirror of bytecodealliance/wit-bindgen#547 into the
`bindgen!` macro for Wasmtime. The new default is to generate only one
Rust type per WIT type input, regardless of if the representation can be
slightly more optimal in niche cases with more borrows. This should make
the macro easier to work with in the limit ideally.

Closes bytecodealliance#6124
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

Successfully merging a pull request may close this issue.

2 participants