wit-bindgen: generate only one StreamPayload or FuturePayload implementation per type alias set by danielvallance · Pull Request #1482 · bytecodealliance/wit-bindgen

alexcrichton

@danielvallance

…tations

WIT 'use' statements are represented as Type::Id(_) Types in this codebase, and get
translated to Rust type aliases in the generated Rust bindings.

Since these aliases may be located at different module paths, creating a StreamPayload
or FuturePayload implementation for more than one of these paths will cause the Rust compiler
to complain about conflicting trait implementations for the same type.

This commit solves this issue by dealiasing payload types of the form Type::Id(_) when generating
a key for the future_payloads and stream_payloads maps. This means each alias set will have at
most one implementation of these traits.

Fixes issue 1432

alexcrichton

Merged via the queue into bytecodealliance:main with commit 105bf6c

Feb 9, 2026

27 checks passed

ricochet added a commit to ricochet/wit-bindgen that referenced this pull request

Feb 10, 2026
This change dealiases inside print_ty during recursion, so it catches
aliases at every nesting depth.

PR bytecodealliance#1482 only dealiases the top-level payload type.
That works when the payload itself is an alias
(e.g., future<error-code>), but not when the payload is an anonymous
type that contains aliases (e.g., future<result<_, error-code>>).

Fixes bytecodealliance#1523
Resolves bytecodealliance#1432

This was referenced

Feb 10, 2026

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

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 that referenced this pull request

Feb 12, 2026
* rust: Reimplement how stream/future payloads work

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 #1468 it's possible to do all of this without stringifying.
Specifically #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 #1432 and #1433 without requiring the workaround in #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 #1523
Closes #1524

* Try fixing CI

* Fix typo

* Fix rust CI