Skip to content

Finish bindings generation for (implements ..)#13513

Open
alexcrichton wants to merge 1 commit into
bytecodealliance:mainfrom
alexcrichton:finish-implements
Open

Finish bindings generation for (implements ..)#13513
alexcrichton wants to merge 1 commit into
bytecodealliance:mainfrom
alexcrichton:finish-implements

Conversation

@alexcrichton
Copy link
Copy Markdown
Member

This commit is the final step in finishing up the bindings generation story for bindgen! w.r.t. the (implement ...) component model feature. Namely bindgen! now has the option named_imports: { ... } which generates a new top-level named_imports module with nested modules within it. These nested modules are similar to the default-generated ones except that they additionally take an extra "id" parameter in all trait methods. The add_to_linker function additionally takes both a &Component and a lookup function.

Putting all this together the expected flow is:

  • Host decide they want to accept any number of import a: b:c/d; from components at runtime. Bindings are generated with named_imports: { ... } in the bindgen! invocation.

  • Hosts switch from linker-per-engine to instead using a linker-per-component. After the typical population of items within the Linker next the host uses the named_imports::b::c::d::add_to_linker, for example. Here the host performs lookup from whatever string was found in the component to an ID key that the host knows about. Upon success this key will be closed over in all add_to_linker functions. Upon failure the add_to_linker closure fails.

  • This per-component linker is used to instantiate and create instances as usual. At runtime when a named import is invoked the closed-over ID is passed to the trait implementation as a parameter. Hosts can thus disambiguate through which interface the component made a call through.

Some light tests are added throughout this showcasing the various capabilities. This notably added a new ComponentExtern::is_implements method to peform semver-matching automatically so hosts can generate bindings with one version and still accept implements with other slightly different but compatible versions.

This commit is the final step in finishing up the bindings generation
story for `bindgen!` w.r.t. the `(implement ...)` component model
feature. Namely `bindgen!` now has the option `named_imports: { ... }`
which generates a new top-level `named_imports` module with nested
modules within it. These nested modules are similar to the
default-generated ones except that they additionally take an extra "id"
parameter in all trait methods. The `add_to_linker` function
additionally takes both a `&Component` and a `lookup` function.

Putting all this together the expected flow is:

* Host decide they want to accept any number of `import a: b:c/d;` from
  components at runtime. Bindings are generated with
  `named_imports: { ... }` in the `bindgen!` invocation.

* Hosts switch from linker-per-engine to instead using a
  linker-per-component. After the typical population of items within the
  `Linker` next the host uses the
  `named_imports::b::c::d::add_to_linker`, for example. Here the host
  performs lookup from whatever string was found in the component to an
  ID key that the host knows about. Upon success this key will be closed
  over in all `add_to_linker` functions. Upon failure the
  `add_to_linker` closure fails.

* This per-component linker is used to instantiate and create instances
  as usual. At runtime when a named import is invoked the closed-over ID
  is passed to the trait implementation as a parameter. Hosts can thus
  disambiguate through which interface the component made a call through.

Some light tests are added throughout this showcasing the various
capabilities. This notably added a new `ComponentExtern::is_implements`
method to peform semver-matching automatically so hosts can generate
bindings with one version and still accept `implements` with other
slightly different but compatible versions.
@alexcrichton alexcrichton requested a review from a team as a code owner May 29, 2026 22:05
@alexcrichton alexcrichton requested review from pchickey and removed request for a team May 29, 2026 22:05
@github-actions github-actions Bot added the wasmtime:api Related to the API of the `wasmtime` crate itself label May 29, 2026
@tschneidereit
Copy link
Copy Markdown
Member

  • Hosts switch from linker-per-engine to instead using a linker-per-component.

One thing I didn't think about when we discussed this yesterday: how much overhead does this introduce for hosts with large numbers of components loaded? (I'm not sure how much of a real alternative to this design there is, but I'd at least like to understand the costs a bit better.)

@alexcrichton
Copy link
Copy Markdown
Member Author

I always forget to correct that as well, but what hosts are doing right now is actually a linker-per-engine plus an instance-pre-per-component. This PR doesn't change the latter, still an instance-pre-per-component, and the main difference is that when creating an instance-pre-per-component the host will likely .clone() the per-engine linker, add more items, then create the instance pre, then discard the temporary linker. I wouldn't expect any negligible resource increase or decrease from this.

@tschneidereit
Copy link
Copy Markdown
Member

I wouldn't expect any negligible resource increase or decrease from this.

Assuming you mean s/negligible/non-negligible/: great! :)

@alexcrichton
Copy link
Copy Markdown
Member Author

Oops, yes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasmtime:api Related to the API of the `wasmtime` crate itself

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants