Skip to content

feat(ts): translate dyn bytes::Buf as an object of Buf's methods - #447

Merged
moq-bot[bot] merged 7 commits into
mainfrom
ts-dyn-buf
Nov 2, 2026
Merged

moq-bot[bot] merged 7 commits into
mainfrom
ts-dyn-buf

Conversation

@kixelated

@kixelated kixelated commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

moq's transports read a lease through &mut dyn Buf (transport/boxed.rs), and its ErasedLease is the crate's own trait over Buf. A dyn Buf was refused as "a trait object of another crate's trait", and the crate's own object over Buf failed on chunks_vectored's IoSlice. The provided fixed-size getters (get_u16 and up, try_get_*) of any buffer the mapping doesn't name, such as a Take or the crate's own, failed in bytes' MIR on a slice-to-array pointer cast, so an object holding them could not translate either.

Approach

Decided with the maintainer: dyn bytes::Buf is an object of Buf's methods, the shape the crate's own traits get, so it works for any implementor.

  • dynamic.rs builds Buf's object as a translated crate's trait. It leaves out chunks_vectored, whose IoSlice has no JS value, so a call of it through the object fails loud as "not a method of dyn Buf".
  • The provided get_ and try_get_ of an integer of 2 to 16 bytes map to the new rt.bufGet and rt.bufTryGet over the buffer's own remaining, chunk, advance, and copy_to_slice. They read the chunk where it holds the integer and copy it out where not, as bytes' buf_get_impl! does, calling remaining as many times. try_get_ of the mapped buffers maps the same way, since its MIR hit the same cast.

Tests: buf::dyns in the stock fixture's differential test against native wasm32 reads every getter, the try_get_* errors, and copy_to_bytes through a &mut dyn Buf of a Bytes, a BytesMut, a &[u8], the crate's own buffer with and without its own copy_to_bytes, and a Take<Bytes>. It also reads each through the &mut forwarding impl over the object (moq's poll_write_buf(&mut dyn Buf) path) and through a Box<dyn Buf> that drops what it owns once. A Box<dyn Leased> covers the crate's own trait over Buf, as moq's ErasedLease is. buf::reads now runs every getter on the crate's own buffers and on a Take.

Census at the moq pin, before → after:

Refusals
moq-net 976 → 875
model 232 → 232
kio 141 → 141

moq-net loses its 5 IoSlice refusals and the getters' casts ("reads the bytes of one type as another" 77 → 29, "a raw pointer behind a reference" 64 → 16). No construct gained refusals. Its trait-object count stays 9, the dyn Iterator and dyn Error in #437 and #442.

Impact

  • The translator's output: dyn Buf translates instead of failing. New runtime exports rt.bufGet and rt.bufTryGet.
  • No breaking change.

Alternatives

  • dyn Buf as the rt.ByteSlice it reads, the quest's earlier plan: rejected by the maintainer, since it holds for no buffer in pieces, such as a Chain or moq's leases.
  • Lowering bytes' getters from MIR by supporting the slice-to-array pointer cast: that is byte reinterpretation, the unsafe quest's.

Follow-ups

New m3 quests:

quest/m3/ts-dyn.md now names Arc<dyn Iterator>, dyn FusedIterator, and &mut dyn Debug, and drops dyn Buf. It will conflict with #437, #442, and #445, whichever lands second: keep every removal.

Review

mechanical fix by codex / Codex: Merged base, reconciled trait-object documentation, and regenerated Counted import aliases; validated in ts/: cargo build --locked -p rust2-ts; cargo test --locked (11 fixture tests passed; stale stock snapshot fi·xed and rerun with cargo test --locked --test fixtures stock -- --exact); cargo test --locked --test runtime; cargo clippy --locked --all-targets -- -D warnings; cargo fmt --all --check; cargo shear; cargo sort --workspace --check --no-format; tsc -p runtime. (head af01e4c)

Codex gpt-6.1-sol at medium effort, via quest review, round 2 on head c2d5c914bc1e6707c381d4e5a505c2e8e86f5198: no findings.

Round 1 (head 7e4f92b6) reported one finding, refuted: field normalization at ts/src/lower/mod.rs:1799, a line from #424, which landed on main during the round, outside this branch's diff. It is not verified here.

🤖 Generated with Claude Code

kixelated and others added 4 commits November 2, 2026 08:33
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 31453125-c2b8-40e9-9ffa-0dc1a3073aa7
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@kixelated
kixelated enabled auto-merge (squash) November 2, 2026 19:33
@moq-bot
moq-bot Bot disabled auto-merge November 2, 2026 19:51
@moq-bot
moq-bot Bot enabled auto-merge (squash) November 2, 2026 19:51
@moq-bot

moq-bot Bot commented Nov 2, 2026

Copy link
Copy Markdown

codex / Codex land fixer note:

Merged base and resolved the three documentation conflicts, preserving the PR’s dyn Buf support and base’s Debug/Display pointer support. Regenerated the stock fixture snapshots: all eight changed generated files differ only in Counted namespace aliases after base added another Counted type. The build, Clippy, formatting, dependency checks, and runtime TypeScript checking passed on the pinned nightly. The initial cargo test --locked run passed all seven unit tests and 11 of 12 fixture tests; its only failure was the stale stock snapshot. After regeneration, cargo test --locked --test fixtures stock -- --exact passed, including its differential test, and cargo test --locked --test runtime passed all eight tests.

(written by codex / Codex)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant