Repository navigation
feat(ts): translate cmp::max and min, is_sorted, and BinaryHeap - #252
Conversation
Quest-Claim: ae5726858cb8e8a0
`cmp::max`, `min`, and their `_by` and `_by_key` forms lower from std's MIR. The `is_sorted` family of slices and iterators maps to runtime ports of std's loops, and `BinaryHeap` with `PeekMut` to a runtime port of std's sifts. Integer comparisons pass `rt.lt` and its siblings instead of a test built from `cmp`, which the bench shows costs in Firefox. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…parator first `PeekMut`'s `DerefMut` hides the heap's tail behind a heap of the top alone, as std's `set_len(1)` does, so a forgotten guard leaves the heap as std's. `is_sorted_by` drops its comparator before the last item and the iterator, as std's `all` does, which also lets an iterator that drops take one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`is_sorted_by_key(&f)` over an iterator that drops disposed the map holding `f`, which dropped what `f` owns before its owner did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # ts/fixtures/lang/expected/harness.ts
# Conflicts: # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs
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 34 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. Comment |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed commit e10ad42da3d1e00ef7d58bca91f2c1f73f6756c3.
No actionable bugs found in this static review. The ordering mappings preserve custom comparison hooks rather than replacing them with a generic comparison; direct tests are limited to numeric integer/char representations. The sorted-iterator helper explicitly orders item and comparator drops, and borrowed key closures remain lent. Independent inspection of BinaryHeap/PeekMut found the saved-tail handling consistent across repeated mutable dereferences, forgotten guards, drop and pop. The differential fixture exercises comparison/drop traces as well as equal keys and whole-value replacement.
Direction: using std MIR for max/min and small runtime mappings where raw-pointer heap internals cannot translate is a reasonable split. Keep the direct integer path separate from custom PartialOrd behavior. The benchmark and census numbers in the description remain author-reported evidence, not independently verified results.
Verification limits: GitHub-only inspection of lowering, runtime code and Rust/generated fixtures, including an independent heap/ownership pass. I did not run translation, differential tests, mutation checks or benchmarks.
(Written by OpenAI)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # quest/m3/ts-unsafe.md # ts/fixtures/lang/expected/harness.ts # ts/fixtures/lang/src/harness.rs # ts/fixtures/reject/census.md # ts/fixtures/reject/expected.txt # ts/fixtures/reject/src/lib.rs # ts/fixtures/reject/ts.toml
Completes quest/m3/ts-ordering.md (removed here).
Problem
rust2-ts refused
cmp::maxandcmp::min(and their_by,_by_keyforms), theis_sortedfamily, andBinaryHeap. Consumer: moq's census, where moq-net callsis_sorted_by_key(ietf/object.rs:219) and its dependencies rangemap and uuid callcmp::max/min. The quest also asked whether #173's comparison tests cost integers anything.Approach
cmp::max,min, and their forms lower from std's MIR: each is one call intoOrd::max/minor the closure, which already translate with std's drops.std_refusednow allows&mutof a function, asFnMutcalls take, since its writes are its own body's.is_sorted: a slice's maps tort.sliceIsSorted, a port of std's chunked loop (non-short-circuit within each 33-element chunk); the rest map tort.iterIsSortedBy, std'snextthenall, dropping each item, the comparator, the last item, and the iterator in std's order.BinaryHeapandPeekMutmap to the runtime (rt.BinaryHeap,{ d: T[] }), with std'ssift_up,sift_down_range,sift_down_to_bottom, andrebuild_tailported test for test, so which of equal keys pops first,into_sorted_vec,append,extend, andretaincompare as std's do. Runtime, not std's MIR, because std'sHolemoves elements through raw pointers into theVec's storage.PeekMut'sDerefMuthides the tail as std'sset_len(1)does, so a forgotten guard leaves the heap as std's.rt.lt/le/gt/geinstead ofrt.cmpLt(rt.cmp).Proven by a new
orderscase in the lang differential harness: anItemthat logs everycmp/lt/le/gt/geand drop, over max/min,is_sorted*(slices, iterators, owned and borrowed comparators and key functions), heaps driven by op bytes (push, pop,peek_mutwrites, forgotten guards,PeekMut::pop, append, retain, extend,into_sorted_vec, drain, collect, into_iter), and heaps of bytes,Reverse, strings, and tuples. Mutations of a sift test, the comparator drop order, thePeekMuthide, and thert.lentwrap give 45,867, 58, 2, and 69 differences.#173's comparison tests on integers
New
order/*bench workloads (sort, sort_by_key, iter max/min,Ordmax/min fold, BinaryHeap), ns per item.pre173is the commit before #173, built from its own tree; its heap route is not comparable (it predatesBinaryHeap).cmpLt/ direct / pre173cmpLt/ direct / pre173The cost showed in Firefox (0.8-0.86x the time with direct tests on sort and max/min) and on the heap in Chrome (0.66x); V8 elsewhere is within noise. So the direct tests landed.
Impact
rt.le,rt.gt,rt.ge,rt.sliceIsSorted,rt.iterIsSortedBy,rt.BinaryHeap,rt.PeekMut, and theheap*/peekMut*functions.ts/MIGRATE.md's example updated to showrt.iterMax(it, rt.lt)for integers.called_closuresno longer spends anFn/FnMutclosure a mapping discards, soIterator::is_sorted_bydrops its comparator itself.Alternatives
BinaryHeapfrom std's MIR: blocked on raw-pointerHolemoves (ts-unsafe).rt.cmpLt(rt.cmp)for integers: simpler output, but measurably slower in Firefox and on the heap.mem::forgetof aPeekMut: smaller, but the O(1) array swap matches std exactly.Choices made without asking
BinaryHeap(above), and direct integer tests for everyPartialOrdtest, not only ordering's.PeekMutleaks the hidden tail as std's does.orderop and a hand-written route (bench/order.ts).Follow-ups
quest/m3/ts-unsafe.mdnow plans replacingrt.BinaryHeapandrt.PeekMutwith std's translated MIR once raw pointers translate, theorderscase proving it still matches.windows/chunks,Vec::drain, and byte arrays' order, each refused and rewritten around in this PR's fixtures and bench.Review
quest review --base origin/main, codex gpt-6.1-sol medium, 4 rounds; round 4 on head e10ad42 reported no findings.PeekMutdid not leak the tail (fixed,PeekMuthides it);is_sorted_bydropped an owning comparator after the last item (fixed, dropped byiterIsSortedBy).is_sorted_by_key(&key)over a dropping iterator droppedkey(fixed,rt.lent).Box::new(&key)(fixed, lent unless an owned function).Skipped as trivial on head 6db3efd: since the reviewed head it adds a quest-only Plan bullet to
quest/m3/ts-unsafe.md(replacert.BinaryHeap/rt.PeekMutwith std's MIR once raw pointers translate) and merges origin/main, whose fixture conflicts kept both sides' entries (harness cases, reject roots and functions) with generated snapshots regenerated.quest checkandjust cipass on that head.(written by Claude Opus 5.5)
🤖 Generated with Claude Code