Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions quest/m3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ generic std gap is planned here even when moq never calls it.
- [A trait object in a struct's last field](/quest/m3/ts-dyn-tail.md) - `Rc<RefCell<dyn Trait>>` and the like translate, the last field as the object
- [bytes' Chain as a Buf object](/quest/m3/ts-buf-chain.md) - `Chain::copy_to_bytes` across both halves translates, and with it a `Chain` as a `dyn Buf`
- [A Buf object's size](/quest/m3/ts-dyn-buf-size.md) - a `dyn Buf` object holds only the methods some call dispatches to
- [A boxed iterator folds as std's box does](/quest/m3/ts-box-folds.md) - a `Box<I>` reads by `next` where std's `Iterator` for `Box<I>` forwards nothing else
- [by_ref of a mutable reference to an iterator](/quest/m3/ts-by-ref-place.md) - `Iterator::by_ref` of a `&mut I` in a local translates
- [mem::take as a function value](/quest/m3/ts-take-value.md) - `mem::take`, `replace`, and `swap` passed as a function value translate
- [Debug of a RefCell](/quest/m3/ts-refcell-debug.md) - `{:?}` of a `RefCell`, `Ref`, and `RefMut` translates as std's writes them
Expand Down
24 changes: 24 additions & 0 deletions quest/m3/ts-box-folds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# [S] A boxed iterator folds as std's box does

## Goal

[rust2-ts](/ts/README.md) reads a `Box<I>` of a sized iterator, owned or behind a `&mut`,
as std's `Iterator` for `Box<I>` does: by `I`'s own `next`, `size_hint`, `nth`, `last`,
`next_back`, `nth_back`, `len`, and `is_empty`, and by `next` or `next_back` for every
other consumer, proven by the lang fixture's differential tests against native Rust.

## Plan

Found on 2026-11-03 probing what [#437](https://github.com/moq-dev/rust2/pull/437) left:
the translation erases the box and folds what it holds by its own `fold`, where std's
defaults read the box by `next`. A boxed `Chain` of mapped `vec::IntoIter`s matches native
across `count`, `fold`, `for_each`, `find`, `position`, `max_by_key`, `rev().fold`, and
`skip(1).count()`, since `Chain`'s folds read and drop in `next`'s order. A box of a `skip`
of a zip std reads by index does not: `Box::new(a.map(f).zip(b.map(g)).skip(1)).count()`
makes and drops the skipped pair whole, as `Skip`'s fold does, where native skips it a
side at a time through the zip's `nth`.

`rt.iterDyn` already reads a `dyn Iterator` this way, so a box of a sized iterator can be
one too, with `last` forwarded to the iterator's own, as std's `BoxIter` specializes it.

Public API: the translator's output.