Stream: wasmtime

Topic: Can components be generic over exported interfaces ?


view this post on Zulip Antoine Lavandier (Oct 21 2025 at 08:52):

It's possible to generic of the imported interfaces of a components (in fact this is how add_to_linker works). Is it possible to also do this with exported interfaces ?
So for example this is possible

wastime::component::bindgen({
    inline: r#"
        package example:interface-imports;

        interface logging {
            enum level {
                debug,
                info,
                warn,
                error,
            }

            log: func(level: level, msg: string);
        }

        world with-imports {
            import logging;
        }
    "#
});

use example::interface_imports::logging::Host

fn<T: Host>(host: T){
  // Do stuff like
  // Create a store owning a T
  // and use it to instantiate a component
}

Is there a way to something like this

wastime::component::bindgen({
    inline: r#"
        package example:interface-imports;

        interface logging {
            enum level {
                debug,
                info,
                warn,
                error,
            }

            log: func(level: level, msg: string);
        }

        world with-imports {
            export logging;
        }
    "#
});

use example::interface_imports::logging::Guest

fn<T: Guest>(guest: T){
  // Do things like calling guest.call_log():
}

The use case is that I'd like to have a library that ingests any component that implements (i.e. export) interfaces. As far as I know it's not possible to do without me creating that guest trait and users implementing it for the specific struct created when they call bindgen!

view this post on Zulip Alex Crichton (Oct 21 2025 at 14:35):

Yeah I would agree the guest side would be pretty difficult here due to the fact that it needs to get hooked up to no_mangle functions. It's sort of "almost there" but not quite given the current generated bindings

view this post on Zulip Antoine Lavandier (Oct 21 2025 at 15:08):

I took more time to look at the generated code and I think that I have potential solution that would essentially mirror what happens for imported interfaces. If I'm not mistaken declaring with: { "interface": path::to::mod} removes the mod interface { ... } part of the generated code and instead adds use path::to::mod::{Host, add_to_linker, ...}.
Applied to exported interfaces this could look like this
So by default everything is generated at the bindgen call site and otherwise, it's replace by use statements when the bindgen caller provides a path to a module that already generates the approriate code.
Then the trait could be defined only once and implemented directly on the struct exports::interface::Guest and/or the MyWorld struct.


Last updated: Dec 06 2025 at 06:05 UTC