diff --git a/quest/m3/ts-unsafe/README.md b/quest/m3/ts-unsafe/README.md index 8ec3e33af..d239abee4 100644 --- a/quest/m3/ts-unsafe/README.md +++ b/quest/m3/ts-unsafe/README.md @@ -80,3 +80,7 @@ Public API: the translator's output. - [NonZero's unchecked arithmetic](/quest/m3/ts-unsafe/nonzero-unchecked-ops.md) - `NonZero::unchecked_add` and `unchecked_mul` translate, aborting at std's site - [UnsafeCell's raw accessors](/quest/m3/ts-unsafe/unsafecell.md) - `UnsafeCell::raw_get`, `from_mut`, and `replace` translate - [A byte local whose address is taken, in a buffer of its own](/quest/m3/ts-unsafe/lone-byte-buffers.md) - raw and mutable slices of a `u8` local, and casts of them to byte arrays, translate instead of being refused +- [Zeroed values beyond one Box](/quest/m3/ts-unsafe/zeroed-values.md) - `MaybeUninit::zeroed`, `mem::zeroed`, and `Box::new_zeroed_slice` translate through the zero-value code +- [Rc and Arc of an uninitialized value](/quest/m3/ts-unsafe/rc-arc-uninit.md) - `Rc` and `Arc`'s `new_uninit`, `new_zeroed`, slice forms, and `assume_init` translate +- [A raw pointer into a nested array](/quest/m3/ts-unsafe/nested-array-pointers.md) - `&raw mut (*p)[1][0]` points into its inner array +- [ptr::write_bytes beyond bytes](/quest/m3/ts-unsafe/write-bytes-any.md) - `write_bytes` of integers, floats, and arrays and tuples of them translates diff --git a/quest/m3/ts-unsafe/nested-array-pointers.md b/quest/m3/ts-unsafe/nested-array-pointers.md new file mode 100644 index 000000000..bed550b46 --- /dev/null +++ b/quest/m3/ts-unsafe/nested-array-pointers.md @@ -0,0 +1,22 @@ +# [M] A raw pointer into a nested array + +## Goal + +[rust2-ts](/ts/README.md) translates a raw pointer to an element of a nested array, such as +`&raw mut (*p)[1][0]`, today refused as not supported yet. It points at that element in +its inner array, so reads, writes, and arithmetic within the inner array match native Rust, +proven by differential tests. + +## Plan + +Suggested on [#639](https://github.com/moq-dev/rust2/pull/639). An element pointer is +`rs.AtIndex`, `{ array, index }`, into the array JS holds it in; for a nested array that is +the inner array. Arithmetic that crosses from one inner array into the next, which Rust +allows within the outer allocation, stays refused with a span unless the plan finds a +cheap exact way; say which in the PR. + +Decided with the maintainer on 2026-11-07: ✅ m3, in this epic (from #639's follow-ups), ✅ +arithmetic within the inner array (rejected: crossing inner arrays as a requirement). No +consumer at the moq pin. + +Public API: the translator's output. diff --git a/quest/m3/ts-unsafe/rc-arc-uninit.md b/quest/m3/ts-unsafe/rc-arc-uninit.md new file mode 100644 index 000000000..4aa45f64e --- /dev/null +++ b/quest/m3/ts-unsafe/rc-arc-uninit.md @@ -0,0 +1,22 @@ +# [S] Rc and Arc of an uninitialized value + +## Goal + +[rust2-ts](/ts/README.md) translates `Rc` and `Arc`'s `new_uninit`, `new_zeroed`, their +slice forms (`new_uninit_slice`, `new_zeroed_slice`), and `assume_init`, the way `Box`'s +forms translate, proven by differential tests against native Rust, with strong and weak +counts and drops matching. + +## Plan + +Suggested on [#639](https://github.com/moq-dev/rust2/pull/639) (`Box::new_uninit`, +`new_zeroed`, `write`, and `assume_init` for one value) and +[#606](https://github.com/moq-dev/rust2/pull/606) (`Box::new_uninit_slice`). These are +stable std APIs, and std gaps are deferred, not dropped. Cover both ways a program writes +the value before `assume_init`: `Rc::get_mut(&mut rc).unwrap().write(v)`, and a write +through `as_ptr`. + +Decided with the maintainer on 2026-11-07: ✅ m3, in this epic (from #639's follow-ups). No +consumer at the moq pin. + +Public API: the translator's output. diff --git a/quest/m3/ts-unsafe/write-bytes-any.md b/quest/m3/ts-unsafe/write-bytes-any.md new file mode 100644 index 000000000..5e94da4f9 --- /dev/null +++ b/quest/m3/ts-unsafe/write-bytes-any.md @@ -0,0 +1,22 @@ +# [S] ptr::write_bytes beyond bytes + +## Goal + +[rust2-ts](/ts/README.md) translates `ptr::write_bytes` for pointees other than bytes whose +every byte pattern the runtime can build, such as integers, floats, and arrays and tuples of +them (zeroing a `[u32]` is the common case), proven by differential tests against native +Rust. Any other pointee stays refused with a span. + +## Plan + +Suggested on [#642](https://github.com/moq-dev/rust2/pull/642), which translated +`write_bytes` for `u8` and `MaybeUninit` pointers through `rs.ptrWriteBytes`. A value +of `n` repeated bytes is the integer or float those bytes spell in little-endian wasm32 +order; the zero case can reuse [#639](https://github.com/moq-dev/rust2/pull/639)'s +zero-value code. A pattern that is invalid for the pointee (a `bool` of 2) is UB in Rust and +need not be reproduced. + +Decided with the maintainer on 2026-11-07: ✅ m3, in this epic (from #642's follow-ups), ✅ +any byte pattern (rejected: zero only). No consumer at the moq pin. + +Public API: the translator's output. diff --git a/quest/m3/ts-unsafe/zeroed-values.md b/quest/m3/ts-unsafe/zeroed-values.md new file mode 100644 index 000000000..ca87e5810 --- /dev/null +++ b/quest/m3/ts-unsafe/zeroed-values.md @@ -0,0 +1,21 @@ +# [S] Zeroed values beyond one Box + +## Goal + +[rust2-ts](/ts/README.md) translates `MaybeUninit::zeroed`, `mem::zeroed`, and +`Box::new_zeroed_slice`, proven by differential tests against native Rust. Each builds the +value all-zero bytes give, as `Box::new_zeroed` does. + +## Plan + +Suggested on [#639](https://github.com/moq-dev/rust2/pull/639), which translated +`Box::new_zeroed` for one value: it builds the zero value part by part through tuples, +arrays, the crate's structs, enums by their zero tag or niche, and std's wrappers (`Wrapping`, +`Cell`, `Mutex`, ...), and leaves a part that can't be zero, such as a reference or a +`String`, unwritten. Reuse that code rather than a second walk. `mem::zeroed` of a type with +a part that can't be zero is UB in Rust; translate it as the same partly unwritten value. + +Decided with the maintainer on 2026-11-07: ✅ m3, in this epic (from #639's follow-ups). No +consumer at the moq pin. + +Public API: the translator's output.