Repository navigation
Enumerable#minmax runs its block in CRuby's pairwise order (fixes #128) - #129
Open
jiro-by-nori[bot] wants to merge 1 commit into
Open
jiro-by-nori[bot] wants to merge 1 commit into
jiro-by-nori[bot] wants to merge 1 commit into
Conversation
) `minmax` answered `[min, max]` and never called a given block, so `[1, 2, 3].minmax { |a, b| b <=> a }` was `[1, 3]` where CRuby answers `[3, 1]`: a silent wrong answer, not a gate. The block is a comparison over consecutive elements, not a key function. CRuby's `enum_minmax` compares two consecutive elements, then the smaller with the running minimum and the larger with the running maximum, and compares a trailing odd element last; a program that logs comparisons observes that order. The block form now runs that loop. Without a block the pair is the same under any total order and `Array#minmax` answers `[min, max]`, so that path is unchanged. The regression program pins the answer and the comparison sequence for even and odd lengths, empty and one-element collections, equal pairs, a hash's pairs, an `Enumerator`, and a comparison whose result depends on how often it has run. Co-authored-by: Nori <contact@tilework.tech>
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.
Summary
Enumerable#minmaxaccepted a comparison block and never called it: it answered[min, max]under the default<=>. This was a silent wrong answer for a validprogram, not a gate:
The block is CRuby's comparison over consecutive elements, not a key
function.
enum_minmaxcompares two consecutive elements once, then the smallerwith the running minimum and the larger with the running maximum, and compares a
trailing odd element last, so a program that logs its comparisons observes that
order. The block form now runs that loop; without a block the pair is the same
under any total order and
Array#minmaxanswers[min, max], so that path isunchanged.
minmax_bystill gates as unmodeled.Fixes #128.
Test plan
The new regression program
difftest/corpus/regressions/enumerable-minmax-block.rb(hand-filed,
status: fixed) is replayed bymake conformanceon every build. Itpins both the answer and the exact sequence of comparisons for:
String#size, and aHash's pairs;pairs, and a trailing unpaired element;
Enumeratorreceiver, and a comparison whose result depends on how often ithas run (only a loop with CRuby's call order answers that the same way);
Before the change the same program disagreed on the first line (the block's log
was empty); after it
bin/ruby-lean --comparereportsAGREE the model and CRuby print the same and end the same way.Validation
All run locally on CRuby 4.0.5 with the pinned toolchain:
make conformance— 1287 bootstraptest programs: 1087 agree, 194 unsupported,0 disagree, baseline held; the regressions tier and tier3 agree.
make books— 1399 jobs, success.make soundness— SOUNDNESS CHECK PASSED.make metatheory— axioms arepropext,Classical.choice,Quot.soundonly.make difftest-test— 189 passed, coverage baseline held.make lint— ruff, RuboCop, shellcheck, actionlint clean.make gen-check— all generated sources fresh.make check-not-weakened— CHECKS NOT WEAKENED.Authored by Jiro, an autonomous agent. The analysis, the code, and this
description are the agent's.