Skip to content

Conversation

@alexcrichton
Copy link
Member

This commit adds a new method to Resolve which is intended to resolve a longstanding issue for bindings generators based on wit-parser: #1497. Specifically this adds functionality to Resolve to duplicate exported interfaces and their contents, if necessary. This is a boon to bindings generators because it means that a TypeId, for example, uniquely identifies a single generated type. Previously it might refer to one of two types, either the imported version or the exported version. After this method, however, there will be two TypeIds if necessary.

This is currently modeled as a mutation to Resolve which is opt-in. This is done to avoid tampering with the AST-like structure of Resolve today where other AST-like operations don't want to necessarily have to keep everything in sync. Once a Resolve is nominalized, however, it's effectively incompatible with other operations such as merging, printing, etc. My thinking is that for now this is a reasonable tradeoff as bindings generators can pretty easily invoke this method before actually running bindings generation.

Closes #1497

This commit adds a new method to `Resolve` which is intended to resolve
a longstanding issue for bindings generators based on `wit-parser`: bytecodealliance#1497.
Specifically this adds functionality to `Resolve` to duplicate exported
interfaces and their contents, if necessary. This is a boon to bindings
generators because it means that a `TypeId`, for example, uniquely
identifies a single generated type. Previously it might refer to one of
two types, either the imported version or the exported version. After
this method, however, there will be two `TypeId`s if necessary.

This is currently modeled as a mutation to `Resolve` which is opt-in.
This is done to avoid tampering with the AST-like structure of `Resolve`
today where other AST-like operations don't want to necessarily have to
keep everything in sync. Once a `Resolve` is nominalized, however, it's
effectively incompatible with other operations such as merging,
printing, etc. My thinking is that for now this is a reasonable tradeoff
as bindings generators can pretty easily invoke this method before
actually running bindings generation.

Closes bytecodealliance#1497
@alexcrichton alexcrichton requested a review from a team as a code owner February 10, 2026 00:29
@alexcrichton alexcrichton requested review from dicej and pchickey and removed request for a team and pchickey February 10, 2026 00:29
# add version detection to build scripts but in other cases this may not be
# reasonable to expect.
rust-version = "1.81.0"
rust-version = "1.82.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed for indexmap 2.13's replace_index 👍

@ricochet
Copy link
Contributor

This LGTM. I like how it's opt-in and won't impact existing workflows

@alexcrichton alexcrichton added this pull request to the merge queue Feb 10, 2026
Merged via the queue into bytecodealliance:main with commit 9501a05 Feb 10, 2026
36 checks passed
@alexcrichton alexcrichton deleted the nominal-type-ids branch February 10, 2026 18:24
alexcrichton added a commit to alexcrichton/wit-bindgen that referenced this pull request Feb 10, 2026
This commit leverages bytecodealliance/wasm-tools#2447 to make many
existing and future problems much easier in `wit-bindgen`. Namely a
`TypeId` now uniquely identifies a type to be generated rather than
simultaneously representing both an import and an export in some
situations. This isn't immediately leveraged in bindings generators just
yet but it's intended to open up the doors to benefitting from this in
the future.
alexcrichton added a commit to alexcrichton/wit-bindgen that referenced this pull request Feb 10, 2026
Previously stream/future payload were generated by collecting the set of
types used in `future` and `stream` types in a WIT, rendering them to a
string, deduplicating based on this string representation, and then
generating various impls-with-vtables. This stringification strategy
unfortunately falls down in a few situations such as:

* Type aliases in WIT render as two names in Rust, but they're using the
  same Rust type.
* Types with the same definition, but in multiple modules, will have two
  different paths in Rust but alias the same type.
* Primitives may be used directly in streams/futures but then
  additionally used as a WIT type alias.

In all of these situations it's effectively exposing how Rust requires
at most one-impl-per-type-definition but the stringification/deduping
was just a proxy for implementing this restriction and not a precise
calculation. Using the work from bytecodealliance/wasm-tools#2447 as
well as bytecodealliance#1468 it's possible to do all of this without stringifying.
Specifically bytecodealliance#1468, transitively enabled by
bytecodealliance/wasm-tools#2447, enables building a set of equal types
that the Rust generator knows will all alias the same type definition.
Using this it's possible to translate a payload to its "canonical
payload" representation ID-wise and perform hashing/deduplication based
on that. This in turn solves all of the issues above as well as previous
issues such as bytecodealliance#1432 and bytecodealliance#1433 without requiring the workaround in bytecodealliance#1482.

The end result is that all of these various bugs should be fixed and the
Rust generator should be much more reliable about when exactly a trait
impl is emitted vs not.

Closes bytecodealliance#1523
Closes bytecodealliance#1524
github-merge-queue bot pushed a commit to bytecodealliance/wit-bindgen that referenced this pull request Feb 10, 2026
* Generate nominal IDs for all bindings generation

This commit leverages bytecodealliance/wasm-tools#2447 to make many
existing and future problems much easier in `wit-bindgen`. Namely a
`TypeId` now uniquely identifies a type to be generated rather than
simultaneously representing both an import and an export in some
situations. This isn't immediately leveraged in bindings generators just
yet but it's intended to open up the doors to benefitting from this in
the future.

* Rely on nominal type ids in the rust generator

No major changes just yet, but this shows some examples of removing
non-obvious logic in bindings generation enabled by nominal type ids.

* Fix Go CI
alexcrichton added a commit to alexcrichton/wit-bindgen that referenced this pull request Feb 10, 2026
Previously stream/future payload were generated by collecting the set of
types used in `future` and `stream` types in a WIT, rendering them to a
string, deduplicating based on this string representation, and then
generating various impls-with-vtables. This stringification strategy
unfortunately falls down in a few situations such as:

* Type aliases in WIT render as two names in Rust, but they're using the
  same Rust type.
* Types with the same definition, but in multiple modules, will have two
  different paths in Rust but alias the same type.
* Primitives may be used directly in streams/futures but then
  additionally used as a WIT type alias.

In all of these situations it's effectively exposing how Rust requires
at most one-impl-per-type-definition but the stringification/deduping
was just a proxy for implementing this restriction and not a precise
calculation. Using the work from bytecodealliance/wasm-tools#2447 as
well as bytecodealliance#1468 it's possible to do all of this without stringifying.
Specifically bytecodealliance#1468, transitively enabled by
bytecodealliance/wasm-tools#2447, enables building a set of equal types
that the Rust generator knows will all alias the same type definition.
Using this it's possible to translate a payload to its "canonical
payload" representation ID-wise and perform hashing/deduplication based
on that. This in turn solves all of the issues above as well as previous
issues such as bytecodealliance#1432 and bytecodealliance#1433 without requiring the workaround in bytecodealliance#1482.

The end result is that all of these various bugs should be fixed and the
Rust generator should be much more reliable about when exactly a trait
impl is emitted vs not.

Closes bytecodealliance#1523
Closes bytecodealliance#1524
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 this pull request may close these issues.

proposal: wit-parser: create distinct imported and exported TypeDefs, Functions, and Interfaces in a Resolve

3 participants