Skip to content

Conversation

@alexcrichton
Copy link
Member

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

@alexcrichton
Copy link
Member Author

This is built on #1526 and #1468 currently, on the last commit is relevant.

@alexcrichton alexcrichton marked this pull request as ready for review February 10, 2026 21:13
Copy link
Contributor

@ricochet ricochet left a comment

Choose a reason for hiding this comment

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

commit ba5565b is a significant improvement, dealias begone! I double-checked the tests cover what we hit with the latest rc for WASI.

@ricochet
Copy link
Contributor

C++ codegen doesn't have async stream/futures support yet.

You could extend the list in crates/test/src/cpp.rs should_fail_verify list: issue-1432.wit, issue-1433.wit, future-same-type-different-names.wit

Looking at this with fresh eyes, I wish I had done this previously:

    fn should_fail_verify(
        &self,
        name: &str,
        config: &crate::config::WitConfig,
        _args: &[String],
    ) -> bool {
        // C++ doesn't support async yet
        config.async_
            || config.error_context
            || name == "async-resource-func.wit" // <-- missing async = true
    }

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.

Rust: P3 type aliases for futures with conflicting trait impls

2 participants