Skip to content

feat(ts): translate bytes' BufMut for a &mut [u8] and a &mut [MaybeUninit<u8>] - #642

Open
kixelated wants to merge 3 commits into
mainfrom
quest/m3/ts-bufmut-slices
Open

kixelated wants to merge 3 commits into
mainfrom
quest/m3/ts-bufmut-slices

Conversation

@kixelated

@kixelated kixelated commented Nov 7, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

bytes' impl BufMut for &mut [u8] refused at every call: mapped_self (ts/src/lower/stock.rs) counted any &[u8] or &mut [u8] as a mapped buffer, but no Buffer mapping writes a mutable slice. Reproduced first with a new differential case: 45 refusals, all <&mut [u8] as bytes::BufMut>::*. The &mut [MaybeUninit<u8>] impl already translated from its MIR but for ptr::write_bytes, which the provided put_bytes reaches through the forwarding &mut T and Box<T> impls (they don't forward put_bytes) and the MaybeUninit impl's own put_bytes calls.

Approach

  • mapped_self counts only a shared &[u8], so the &mut [u8] impl translates from MIR like the deque's in moq-dev/rust2#611: chunk_mut is the slice's rs.ByteSlice, advance_mut its mem::take(self).split_at_mut(cnt).
  • ptr::write_bytes and the *mut T / NonNull write_bytes methods map to a new rs.ptrWriteBytes for byte pointees (u8, MaybeUninit<u8>). Any other pointee is refused with a span, as JS keeps it as a value, not bytes. The origin check refuses a write the body shows reaching past an array JS keeps apart, as it does ptr::copy.
  • Differential case buf::slices: writes a 255-byte array through a &mut [u8] and a &mut [MaybeUninit<u8>] of the room its input picks, by write_all and chunk_all (every provided and overridden method, chunk_mut writes, advance_mut past the room), directly, through a &mut, and through a Box, ending with the room left and both arrays whole. Of 320 inputs per kind, each of the 8 kinds reaches both completed writes (21 to 127) and panics.
  • Reject cases for write_bytes::<u32> and a write_bytes past a lone byte.

Impact

  • Translator output: BufMut for &mut [u8] and &mut [MaybeUninit<u8>], and ptr::write_bytes of bytes, now translate instead of refusing.
  • Runtime: new rs.ptrWriteBytes.
  • No wire impact. Not breaking.

Caused by

No single PR: mapped_self has counted every byte-slice reference since bytes' Buf/BufMut mapping began, before any &mut [u8] consumer.

Choices made without asking

  • write_bytes covers byte pointees only and refuses others (u32, i8, structs). Integers of every byte set alike (such as zeroing) could be supported, but no consumer reaches them; see Follow-ups.
  • rs.ptrWriteBytes sets byte by byte through the same elemSet path as ptrCopy's fallback rather than a Uint8Array.fill fast path: simpler, and nothing here is hot.

Alternatives

  • Map &mut [u8] as a new Buffer variant in the bytes mapping. Rejected: the impl's MIR translates exactly with what exists, and a mapping would duplicate bytes' panics by hand.

Follow-ups

  • ptr::write_bytes of non-byte pointees (integers and floats from a repeated byte, e.g. zeroing a [u32]): plan as an m3 quest, since rust2 aims for all of std and this refusal is a std gap with no consumer yet.

Validation

  • just ci: lint passes; tests pass but for the two known TypeId-hash snapshots (ts/fixtures/lang/dyns/expected/ids.ts, ts/fixtures/lang/panics/hook/expected/lib.ts), which differ only in hash strings, reproduce on bare origin/main per the coordinator, and moq-dev/rust2#633 fixes.
  • stock differential: 0 differences.

Models

Size: S
Implementer: Claude Code, claude-opus-5-5, high effort

(Written by Claude Opus 5.5 with high effort)

🤖 Generated with Claude Code

Review

Rewritten by quest review after each round.

  • Reviewer: Codex, gpt-6.1-sol, medium effort
  • Session: 01a1b538-0a34-7080-ac34-8e28ac2dc77c, round 1
  • Head: 0de9208
  • Base: origin/main at efa6300
  • Score: 10/10, No actionable defects were found in the specified diff; 400 focused differential cases passed using existing build artifacts, although the full suite was blocked by the read-only environment.
  • Findings: none

@pullfrog

pullfrog Bot commented Nov 7, 2026

Copy link
Copy Markdown

Pullfrog  | Review this ➔

kixelated and others added 2 commits November 7, 2026 00:25
…init<u8>]

A `&mut [u8]` counted as a mapped buffer, though no mapping writes one, so
every call into its impl refused. It now translates from the MIR, as the
`MaybeUninit` impl already did, and `ptr::write_bytes` of bytes maps, which
the provided `put_bytes` reaches through the forwarding impls. Its other
pointees are refused, and a write the body shows past an array JS keeps
apart is too. A differential case writes an array through each slice,
directly, through a `&mut`, and through a `Box`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title BufMut on a byte slice feat(ts): translate bytes' BufMut for a &mut [u8] and a &mut [MaybeUninit<u8>] Nov 7, 2026
@kixelated
kixelated marked this pull request as ready for review November 7, 2026 08:58
@coderabbitai

coderabbitai Bot commented Nov 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 26 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

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: 488969bf-3410-4b8b-9dad-3cbb3ea86a85
Commits

Reviewing files that changed from the base of the PR and between efa6300 and 0de9208.

Files selected for processing: 17

  • quest/m3/README.md
  • quest/m3/ts-bufmut-slices.md
  • ts/README.md
  • ts/fixtures/reject/census.txt
  • ts/fixtures/reject/expected.txt
  • ts/fixtures/reject/src/pointers.rs
  • ts/fixtures/reject/ts.toml
  • ts/fixtures/stock/expected/buf.ts
  • ts/fixtures/stock/expected/bytes/buf/buf_mut.ts
  • ts/fixtures/stock/expected/harness.ts
  • ts/fixtures/stock/src/buf.rs
  • ts/fixtures/stock/src/harness.rs
  • ts/runtime/rs.ts
  • ts/src/census.rs
  • ts/src/lower/mir/origin.rs
  • ts/src/lower/pointer.rs
  • ts/src/lower/stock.rs
  • 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 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Automated review by review (OpenAI)

Reviewed head 0de9208600994217a125a9ca574882d7624a8b49 against base efa6300cc2a9be621b52d683179bcd8e49f9a672.

No actionable introduced findings identified.

The mutable-slice implementations now reach MIR without changing shared-slice mappings. I checked the generated slice cursor/backing-storage behavior against bytes' implementations, the byte-only pointer fill and origin checks, and the registered differential and rejection cases.

Direction: no changes requested from this review; retain the normal validation gates.

Verification limits: GitHub-only static review. I did not execute the translator, differential tests, or CI, and did not independently reproduce the reported results or pre-existing snapshot failures. This COMMENT is not an approval.

(Written by review (OpenAI))

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.

1 participant