Repository navigation
feat(ts): translate Debug of std's iterators - #317
Merged
Merged
Conversation
Quest-Claim: 46472d86c834193c
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs
# Conflicts: # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs
# Conflicts: # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
format!("{it:?}")of std's iterators refused withunsupported call to <... as Debug>::fmtand a span (found by #312), while their collections'Debugtranslated. Each iterator writes its own text:Iter([1, 2]),Chars(['a']),Bytes(Copied { it: Iter([97]) }), a bare list of entries, orRange { iter: [(2, SetValZST)] }.Reproduced on
lang: 34 refusals ofDebugacross the iterators below.Approach
remaining(): the items each has left, by value, without taking them (a place-lending iterator's values).rt.fmtIterwrites them as a list inside the wrappers std writes,rt.fmtCharswritesChars(...), andrt.fmtSetValwrites aBTreeSetentry as std's internal map entry,(key, SetValZST).fmt.rsmaps each iterator'sDebugby its std path to its wrapper and item type, as read from the pinned std source and confirmed natively:Iter([..]):slice::Iter,binary_heap::Iter,btree_set::Iter;IterMut([..]):slice::IterMut;IntoIter([..]):vec,binary_heap, andvec_deque's;Drain([..]):vec::Drain;Drain { iter: Drain([..]) }:binary_heap::Drain.Chars([..])andBytes(Copied { it: Iter([..]) }).btree_map'sIter,IterMut,Keys,Values,ValuesMut,Range,RangeMut,IntoIter,IntoKeys,IntoValues;hash_map'sIter,IterMut,Keys,Values,ValuesMut,IntoIter,IntoKeys,IntoValues,Drain;hash_set'sIter,IntoIter,Drain.Range { iter: [(k, SetValZST), ..] }andIntoIter { iter: [..] }:btree_set::RangeandIntoIter.&[u8; N]asrt.ByteSlices was aniterMap; it is nowrt.iterLend, whoseremaining()reads through to the items as the collection holds them, so a slice's or collection's iterator of byte arrays prints too.values_mutof copied values is now its own pick ofHashIterandBTreeIterrather than aniterMapoveriter_mut, so it hasremaining()too.remaining()walks a fresh iterator of the same map past what it took; the map cannot change while the iterator borrows or owns it.fmt::iterscase inlangruns differentially against native wasm32: every iterator above consumed from the front bynthand from the back bynext_back(B-tree ones included), empty,{:#?},{:x?}, width,CharsandBytesover one- to four-byte chars and escaped chars, byte-array elements and keys, and elements with customDebug. Hash iterators hold at most one entry, consumed or not, since std leaves their order unspecified. BreakingChars::remainingand theSetValZSTtext made the differential fail with 186 differences.Kept refused, with their span:
vec_deque::IterandIterMut, andVecDeque::as_slices: they write the ring buffer's two halves,Iter([3], [1, 2]), and the runtime's deque splits elsewhere than std's (power-of-two growth that moves the head to 0,with_capacityignored, item-by-item shifts ininsertandremove). Recorded as A deque's two slices, afterVecDequecapacity in std-rest.vec_deque::Drain, which writes its internal counts,Drain(drain_len, idx, tail_len, remaining): same quest.CharIndices:char_indicesitself has no mapping, so nothing makes one.Impact
{:?}of the iterators above translates instead of being refused. Iterators lending byte arrays are made byrt.iterLendinstead ofrt.iterMap.rt.fmtIter,rt.IterWrap,rt.fmtChars,rt.fmtSetVal,rt.iterLend, andIter.remaining()on std's iterators that have it.Alternatives
Debugimpls do: the runtime's iterators have noclone, and a JSMapiterator can't be copied, so each kind reads its own state instead.iterMapinfmtIterfor byte arrays:iterLendkeeps that read-through to the one wrapper it is right for.Follow-ups
as_slices, andDebugof a deque'sIter,IterMut, andDrain.remaining()reads what std'sDebugreads through a clone, so clones may replace it.Choices made without asking: the quest named the listed iterators; I also covered each sibling the same mapping refused (
IterMut,IntoIter,Drain,Range,Into*,*Mut). The quest's plan saidbtree_set::Iterwrites a bare list; std writesIter([..]), which this follows.Review
Codex (
quest review), gpt-6.1-sol, medium effort, againstorigin/maind1a076ef:ac3946de: one finding, "Preserve bounded zip folds for borrowed iterators" (ts/src/lower/iter.rs:877). Refuted: it was #314's zip fold, onorigin/mainbut not yet merged into that head, so the review saw it as reversed; this PR's only change toiter.rsisby_ref'siterMaptoiterLend. Fixed by mergingorigin/main.517d782da7479f7ef6001de254ef6712bfd7df3f: no findings.just cipassed locally on517d782d.🤖 Generated with Claude Code
(written by Claude Opus 5.5)