Catalog the standard library, and recognize a sortedness check - #43
Merged
Conversation
zmaril
force-pushed
the
pr3-std-catalog-is-sorted
branch
from
August 25, 2026 18:50
afb4600 to
2d2174e
Compare
The catalog builder read trait declarations and free functions. A method written on a type belongs to neither, so `Vec::push` and `<[T]>::is_sorted` fell between the two passes and no catalog ever held them. For core that is 5,621 methods — most of what a caller of the standard library actually calls, and the reason `slice::is_sorted` could not be recommended at all. Inherent implementations are now a third pass, named by the type they are written on: a nominal type by the path its crate publishes, a built-in one the way the language names it, and anything with no name a caller could write left out rather than invented. `Coverage::Adjacent` is the walk the `Pairwise` doc said would arrive when something needed it. A single loop, not a nested one, and the only coverage where the two are neighbours — which makes it the one that says anything about ORDER. The bound must stop one short, because that is what keeps `v[i + 1]` inside the sequence, and the extent is therefore one past the bound. `Idiom` now holds two, and the second cost three answers rather than a second recognizer: which pairs the walk must reach, what it asks of a pair, and what has to hold before the API may stand in. Sortedness admits only the adjacent coverage, because `a > b` over EVERY pair decides something far stronger. The conditions come out right without being told to. `slice::is_sorted` needs `T: PartialOrd` and so does the loop, so the element bound is dropped rather than restated; it allocates nothing, so a `const fn` may still have it; it makes the same comparisons, so nothing is hidden. What is left is the one real gap, and it is a subtle one: the loop refuses on a strict `a > b` and the API accepts only on `a <= b`, which agree under a total order and not under a partial one. Two NaNs are sorted to the loop and not to the API. Measured: 30 findings across 127,210 CodeNet files, all 30 read and confirmed; zero across 3,650 files of production Rust. One file has two neighbour loops and the recognizer took the right one — the other writes through the index. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ghYbUJFcVfkKYacbTVJsR
zmaril
force-pushed
the
pr3-std-catalog-is-sorted
branch
from
August 25, 2026 20:28
2d2174e to
28f1943
Compare
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.
Stacked on #42.
The catalog builder was missing most of the standard library
It read trait declarations and free functions. A method written on a type
belongs to neither, so
Vec::pushand<[T]>::is_sortedfell between the twopasses and no catalog ever held them. In core alone that is 5,621 methods —
most of what a caller of std actually calls, and the reason
slice::is_sortedcould not be recommended at all.
Inherent implementations are now a third pass, named by the type they are
written on: a nominal type by the path its crate publishes, a built-in one the
way the language names it (
slice,str,u32), and anything with no name acaller could write left out rather than invented.
A sortedness check
Coverage::Adjacentis the walk thePairwisedoc said would arrive whensomething needed it — a single loop, not a nested one, and the only coverage
where the two are neighbours, which makes it the one that says anything about
order. The bound must stop one short, because that is what keeps
v[i + 1]inside the sequence.
The second idiom cost three answers rather than a second recognizer: which pairs
the walk must reach, what it asks of a pair, and what must hold before the API
may stand in. Sortedness admits only the adjacent coverage, because
a > boverevery pair decides something far stronger.
The conditions come out right without being told to.
slice::is_sortedneedsT: PartialOrdand so does the loop, so the element bound is dropped ratherthan restated; it allocates nothing, so a
const fnmay still have it; it makesthe same comparisons, so nothing is hidden. What is left is one real gap: the
loop refuses on a strict
a > band the API accepts only ona <= b, whichagree under a total order and not under a partial one. Two NaNs are sorted to
the loop and not to the API.
Measured
30 findings across 127,210 CodeNet files, all 30 read and confirmed. Zero
across 3,650 files of production Rust. One file has two neighbour loops and
the recognizer took the right one — the other writes through the index.
Review notes — the catalog is not committed
core.jsonis 26 MB of generated JSON against itertools' 312 KB, and isreproducible in two seconds from a rustup component. It follows the existing
.gitignoreconvention for generated packs rather than entering history;infact-packs/rust-std/README.mdis the command, andinfact.tomlalreadypoints at where it lands.
Consequence: a fresh clone produces no
is_sortedfindings until that commandis run once. The tests do not depend on it — a test that needs a real
signature reads a single-callable excerpt under
crates/infact-rust-behaviors/tests/fixtures/catalog/.Only a nightly toolchain emits rustdoc JSON, so the version recorded is a
nightly version. That is what a finding is bound to, and it is honest: the
signature it was checked against came from that compiler and no other.
332 tests, clippy clean.