Repository navigation
feat(ts): translate dyn Iterator and its subtraits as an rt.Iter - #437
Conversation
Quest-Claim: 63ea0c57a7775853
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou'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 4 minutes. View limit details
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. CodeRabbit Verify
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
codex / Codex land fixer note:
(written by codex / Codex) |
|
codex / Codex land fixer: Conflicts with the base: quest/m3/README.md, quest/m3/ts-dyn.md, ts/README.md, ts/fixtures/lang/expected/harness.ts, ts/fixtures/lang/src/harness.rs, ts/fixtures/reject/census.md (written by codex / Codex) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # ts/README.md # ts/fixtures/lang/expected/dyns.ts # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/dyns.rs # ts/fixtures/lang/src/harness.rs # ts/fixtures/reject/census.md
# Conflicts: # ts/fixtures/reject/census.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
std's Iterator for Box<I> forwards to I, which JS holds as itself: a boxed crate iterator reached rt.iterDyn, adaptors, and next as its raw object. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs
# Conflicts: # quest/m3/README.md # quest/m3/ts-dyn.md # ts/README.md # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs # ts/fixtures/reject/census.md
…order A shared `&Box<I>` as a `&dyn Iterator` read a place it never was, and a `Box<&mut &mut I>` borrowed kept its references, as references and boxes were peeled in two passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A box of a `TrustedLen` zip collected through the zip's own fold, though std reads a box by `next`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem
moq's model scans its live groups through a
&mut dyn DoubleEndedIterator(model/track.rs), and its transports lend a lease's chunks as aBox<dyn Iterator<Item = &[u8]>>(transport/boxed.rs). Both are refused as "a trait object of another crate's trait", the most common trait-object refusal in moq's census.Approach
A
dyn Iterator,dyn DoubleEndedIterator, ordyn ExactSizeIteratoris anrt.Iterof its items, as adyn Futureis anrt.Future. A coercion from&,&mut, orBoxmakesrt.iterDynof the iterator it points at, std's or the crate's own (throughrt.iterFrom). The runtime's newDyniterator forwards what std's vtable holds (next,size_hint,nth,advance_by, the back ends,len) and folds bynext, as std's default methods read a trait object, so alastorcountof a boxedChaindrops its items in the trait object's order and not inChain's own. A box drops the iterator it owns.Borrowed(&mut Iof a sizedI) is nowDynwith std's fold specialization and no drop. An upcast between these traits is the samert.Iter. Aforloop over aBox<dyn Iterator>reads through thert.Placethat its&mutis.Tests:
dyns::itersin the lang fixture's differential test against native wasm32 covers std iterators, a range, and the crate's own iterator, borrowed and boxed. It runs each vtable method, std's adaptors over the borrow, moq'srev().find_mapscan, anExactSizeIterator'slenwith an upcast, the drop order of a boxed iterator's items and of a boxedChain'slastandcount, and aBox<dyn Iterator>returned through the crate's own trait object, as moq's leases are. Withrt.iterDynreturning its iterator unwrapped, the differential test fails on theChaindrop order (99 differences in 709,498 cases).Census at the moq pin, before → after:
dyn Errorleft)No construct gained refusals. The reject fixture's std trait object is now a
dyn Hasher.Review fixes: references and boxes in any order around an iterator, a shared one included, are read through in one pass to the iterator; a raw pointer to one as a
dyn Iteratoris refused; and a box's specializations are the box's, not what it holds. Earlier, a box of the crate's own iterator (Box<I>, as std'sIteratorforBox<I>forwards) is now read asIininto_iter, iterator method calls, andnext, soBox<Box<I>>as adyn Iterator,&mut Box<I>and&mut Box<Box<I>>as a&mut dyn Iterator,&mut Box<dyn Iterator>reborrowed, and adaptors over aBox<I>translate. Each was reproduced as atscfailure first and is covered indyns::iters; this also fixesBox<I>of a crate iterator outside trait objects, which was broken before this PR.Impact
rt.iterDyn.Alternatives
lastthen differ from what std's defaults do through the trait object (the differential test shows it).rt.Iter, so this would need a second protocol.Follow-ups
Arc<dyn Iterator>anddyn FusedIteratorstay refused: nothing in moq builds them, and nothing callsnextthrough anArc.Iterator::by_refof a&mut &mut Iandmem::takepassed as a function value are existing refusals, met while writing the fixture.dyn Error's downcasts and the rest.Review
Codex
gpt-6.1-sol, medium effort, viaquest review --base origin/main, on the merged branch:a4b8a829): a boxed crate iterator reachedrt.iterDynas its raw object. Fixed in191305a7. A second finding (ffi lending budget) was an artifact of a base the branch had not merged yet;e3ada274merges it.191305a7):&mut Box<dyn Iterator>reborrowed passed its place. Fixed inef3bc43f.ef3bc43f): a borrowedBox<Box<I>>read its place twice. Fixed indf1213d6.84bd93ed): a shared&Box<I>as a&dyn Iteratorread a place it never was, and a borrowedBox<&mut &mut I>kept its references, both from peeling references and boxes in two passes. The maintainer chose to unify the peel:peel_iterreads through&,&mut, and boxes in any order to one&mut Iwith that&mut's JS value, anddyn_iterpasses a shared reference as it is. Fixed in1d5bee91.1d5bee91): a raw pointer to an iterator coerced to*mut dyn Iteratorwas relabeled a&mut. Now refused with a span, covered by the reject fixture'sraw_dyn_iter, in8231fa0d.8231fa0d): peeling a box letcollectsee the held zip'sTrustedLen, which a box lacks, so it folded where std reads bynext. Specializations are now picked by the receiver's own type, and onlynext,next_back,nth_back, andinto_iteruse the peeled one, in237cd7ec.2207a73a, the same code before ajust fixof the fixture): no findings.Each round's case was reproduced first (a
tscfailure, a missing refusal, or a differential mismatch) and is covered indyns::itersor the reject fixture.just cipassed on749a2e10b7b14b5a36d117b0d44c0050ad81961d, which merges main through #468.(written by Claude Opus 5.5)
🤖 Generated with Claude Code