From 4a5328732279ff3d92241e2875b9de218243fb40 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Sun, 1 Nov 2026 10:14:08 -0800 Subject: [PATCH 1/2] chore(quest): plan the fresh-write shapes #394 left refused Co-Authored-By: Claude Opus 5.5 --- quest/m3/README.md | 1 + quest/m3/ts-fresh-shapes.md | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 quest/m3/ts-fresh-shapes.md diff --git a/quest/m3/README.md b/quest/m3/README.md index e391a5e39..61ad78020 100644 --- a/quest/m3/README.md +++ b/quest/m3/README.md @@ -41,3 +41,4 @@ generic std gap is planned here even when moq never calls it. - [Type errors at the Rust that made them](/quest/m3/ts-span-precision.md) - a `tsc` error on output names the tail expression or call argument that made it - [An empty iterator of mutable references](/quest/m3/ts-empty-places.md) - `iter::empty::<&mut T>()` given to `zip` or `chain` translates - [An Option of numbers in the result slot](/quest/m3/ts-option-slot.md) - `varint_opt`'s `Option` comes back through the slot with no object per call +- [Fresh writes through a zip, a copy, and a repeat](/quest/m3/ts-fresh-shapes.md) - zipping a `Vec<[T; N]>`, reading a `T` out of `Zip::next`, and `copied` or `vec![x; n]` over a `Copy` type translate diff --git a/quest/m3/ts-fresh-shapes.md b/quest/m3/ts-fresh-shapes.md new file mode 100644 index 000000000..57b5ccc41 --- /dev/null +++ b/quest/m3/ts-fresh-shapes.md @@ -0,0 +1,27 @@ +# [M] Fresh writes through a zip, a copy, and a repeat + +## Goal + +[rust2-ts](/ts/README.md) translates three shapes it refuses for concrete types and type +parameters alike, proven by differential tests against native Rust: + +- zipping a slot with a `Vec<[T; N]>`, as `[u8; N]`; +- reading a `T` back out of `Zip::next`'s result; +- `iter().copied()` and `vec![x; n]` over a `Copy` type, a crate's own or a `T: Copy`. + +## Plan + +Found by [#394](https://github.com/moq-dev/rust2/pull/394), which made a whole write into +fresh memory count as fresh in a function generic over a type. These three stay refused for +reasons that have nothing to do with type parameters: + +- `vec::IntoIter` points at a type the slot holds in place, so zipping with it refuses. +- Reading a `T` out of `Zip::next`'s result makes it a holder. A concrete control + (`Vec>`) is refused as well. +- `Copy`'s supertrait `Clone` selects a parameter candidate, so `copied` and `vec![x; n]` + count as running the crate's `Clone`. A `Copy` type's `clone` is a copy, so these run no + code of the crate's. + +Reproduce each first and fix the one that is a single cause before the others. + +Public API: the translator's output. From 3ec2fe1cbbe9bf8670371ae1112cf27ea800bc8c Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Sun, 1 Nov 2026 10:15:10 -0800 Subject: [PATCH 2/2] chore(quest): keep vec![x; n] calling a Copy type's own clone Co-Authored-By: Claude Opus 5.5 --- quest/m3/ts-fresh-shapes.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/quest/m3/ts-fresh-shapes.md b/quest/m3/ts-fresh-shapes.md index 57b5ccc41..fad32f9f8 100644 --- a/quest/m3/ts-fresh-shapes.md +++ b/quest/m3/ts-fresh-shapes.md @@ -19,8 +19,11 @@ reasons that have nothing to do with type parameters: - Reading a `T` out of `Zip::next`'s result makes it a holder. A concrete control (`Vec>`) is refused as well. - `Copy`'s supertrait `Clone` selects a parameter candidate, so `copied` and `vec![x; n]` - count as running the crate's `Clone`. A `Copy` type's `clone` is a copy, so these run no - code of the crate's. + count as running the crate's `Clone`. The two differ: `copied` copies and calls no + `clone`, while `vec![x; n]` calls `clone` `n - 1` times, and a `Copy` type's hand-written + `Clone` may have effects or panic. Treat `copied` as running no crate code; keep + `vec![x; n]` calling the crate's `clone`, judged fresh only where that `clone` writes + nothing the slot holds. Cover both with differential tests whose `Clone` logs and panics. Reproduce each first and fix the one that is a single cause before the others.