Measured record · 2026-08-22
How often each rule is wrong
Rust Doctor reports on 62 rules. This page publishes how often those rules were wrong when someone read the code they flagged: 452 adjudicated sites across 18 pinned repositories, in two populations that are measured separately. It is generated from the record the test suite replays, so it states what was measured rather than what would be convenient to claim.
Download the machine-readable measurement- Pinned repositories
- 18
- Adjudicated sites
- 452
- Double judged pairs
- 219
- Rules never triggered
- 36 of 62
What a rate means here
criterionA finding is a false positive when the flagged construct is correct as written, when the surrounding code establishes its safety, or when the context makes the flagged behavior the intended one. Confirming that the rule's pattern is present is a separate, mechanical check: it proves the span is not corrupted, never that the site is a defect. That check ran over 575 findings and confirmed 575 of them, and it measures nothing about precision.
A rate is the rate of the reviewed sample, never of the unreviewed population. Sites are drawn by a fixed stride over the findings ordered by repository, path and line, so the sample follows the distribution a user actually receives. Most rules are sampled at five sites, which resolves steps of twenty points: five sites separate a rule with no observed false positive from one that has some, and cannot place a rule against the 5% threshold. Four rules were deepened past that default. The interval on each row is what says how much the number is worth.
The rate ranks, it never penalizes. What a rule costs the score is what it reported; the rate on this page only decides what the report puts at the top of the list to repair, discounted by how often repairing it would be wasted work. A rule with no measurement is ranked from the middle of a Beta(1,1) prior rather than treated as free.
Healthy code
10 repositories · 22 rules ratedMature, widely used Rust libraries and tools, pinned by tag or commit, scanned with the full catalog. This is code nobody wants disturbed, so a finding here is a demand on a maintainer who did not ask for it: 10 rules were wrong at every sampled site, and 5 were wrong at none.
- anyhow 1.0.104
- async-channel v2.5.0
- bytes v1.12.1
- fd v10.4.2
- hexyl v0.16.0
- log 0.4.33
- ripgrep 15.2.0
- serde_json v1.0.145
- smol v2.0.2
- thiserror 2.0.19
| Rule | Tier | Findings | Wrong | Rate | 95% interval | Against 5% |
|---|---|---|---|---|---|---|
clippy::exit |
P2 | 10 | 5 of 5 | 100% | 56.5% to 100% | Above |
clippy::indexing_slicing |
P3 | 246 | 40 of 40 | 100% | 91.2% to 100% | Above |
clippy::mem_forget |
P2 | 1 | 1 of 1 | 100% | 20.6% to 100% | Above |
clippy::panic |
P3 | 11 | 5 of 5 | 100% | 56.5% to 100% | Above |
clippy::panic_in_result_fn |
P2 | 46 | 5 of 5 | 100% | 56.5% to 100% | Above |
clippy::print_stderr |
P3 | 9 | 5 of 5 | 100% | 56.5% to 100% | Above |
clippy::string_slice |
P3 | 40 | 40 of 40 | 100% | 91.2% to 100% | Above |
clippy::too_many_arguments |
P3 | 1 | 1 of 1 | 100% | 20.6% to 100% | Above |
clippy::unwrap_used |
P3 | 117 | 5 of 5 | 100% | 56.5% to 100% | Above |
rust_doctor::structure::unreferenced_feature |
P3 | 7 | 5 of 5 | 100% | 56.5% to 100% | Above |
rust_doctor::structure::complex_function |
P3 | 34 | 27 of 31 | 87.1% | 71.2% to 94.9% | Above |
clippy::expect_used |
P3 | 23 | 4 of 5 | 80% | 37.5% to 96.4% | Above |
clippy::unreachable |
P2 | 23 | 4 of 5 | 80% | 37.5% to 96.4% | Above |
rust_doctor::structure::near_duplicate_function_body |
P3 | 98 | 19 of 30 | 63.3% | 45.5% to 78.1% | Above |
rust_doctor::structure::duplicate_function_body |
P3 | 134 | 8 of 20 | 40% | 21.9% to 61.3% | Above |
rust_doctor::cargo::unchecked_release_overflow |
P3 | 3 | 1 of 3 | 33.3% | 6.2% to 79.2% | Above |
rust_doctor::structure::oversized_unit |
P3 | 58 | 13 of 39 | 33.3% | 20.6% to 49.0% | Above |
clippy::missing_safety_doc |
P3 | 2 | 0 of 2 | 0% | 0% to 65.8% | Spans it |
clippy::ptr_arg |
P3 | 1 | 0 of 1 | 0% | 0% to 79.3% | Spans it |
clippy::rc_buffer |
P3 | 6 | 0 of 5 | 0% | 0% to 43.5% | Spans it |
clippy::stable_sort_primitive |
P3 | 1 | 0 of 1 | 0% | 0% to 79.3% | Spans it |
rust_doctor::cargo::duplicate_major_versions |
P2 | 1 | 0 of 1 | 0% | 0% to 79.3% | Spans it |
clippy::type_complexity |
P3 | 2 | not judged | not rated | not computed | Not measured |
rust_doctor::structure::crate_level_allow |
P2 | 33 | not judged | not rated | not computed | Not measured |
rust_doctor::structure::stacked_allow_attribute |
P3 | 1 | not judged | not rated | not computed | Not measured |
rust_doctor::structure::unreasoned_allow_attribute |
P3 | 68 | not judged | not rated | not computed | Not measured |
Rules the ten repositories never triggered are not listed: 36 of the 62 catalogued rules never fired here, which says the corpus gave them no chance rather than that they do not work.
Agent authored code
8 repositories · 7 rules ratedRepositories where at least half the commits reachable from the pinned revision carry an agent authorship trailer. The criterion reads the git history alone, never code style, README claims or popularity. This population is scanned with all 37 Clippy rules switched off, because its build scripts and procedural macros are untrusted and Clippy is the one pass that compiles anything, so only the native detectors are measured here.
- claudes-c-compiler 6f1b99a
- ostendo 0284e33
- artifexprocal 2be33f7
- mdr 26e9250
- ralph-os cd6dac9
- vibesql 4d9b33d
- syncvibe ff10443
- coda cf32fbe
| Rule | Tier | Findings | Wrong | Rate | 95% interval | Against 5% |
|---|---|---|---|---|---|---|
rust_doctor::structure::complex_function |
P3 | 1,609 | 28 of 40 | 70% | 54.6% to 81.9% | Above |
rust_doctor::structure::stacked_allow_attribute |
P3 | 2 | 1 of 2 | 50% | 9.4% to 90.5% | Above |
rust_doctor::structure::near_duplicate_function_body |
P3 | 1,120 | 19 of 43 | 44.2% | 30.4% to 58.9% | Above |
rust_doctor::structure::duplicate_function_body |
P3 | 1,476 | 11 of 46 | 23.9% | 13.9% to 37.9% | Above |
rust_doctor::structure::oversized_unit |
P3 | 948 | 5 of 37 | 13.5% | 5.9% to 28.0% | Above |
rust_doctor::structure::orphan_module_file |
P3 | 16 | 1 of 12 | 8.3% | 1.5% to 35.4% | Spans it |
rust_doctor::cargo::missing_lockfile |
P2 | 3 | 0 of 3 | 0% | 0% to 56.1% | Spans it |
rust_doctor::cargo::duplicate_major_versions |
P2 | 28 | not judged | not rated | not computed | Not measured |
rust_doctor::cargo::test_only_dependency |
P2 | 3 | not judged | not rated | not computed | Not measured |
rust_doctor::cargo::unchecked_release_overflow |
P3 | 8 | not judged | not rated | not computed | Not measured |
rust_doctor::cargo::unused_dependency |
P2 | 5 | not judged | not rated | not computed | Not measured |
rust_doctor::structure::crate_level_allow |
P2 | 43 | not judged | not rated | not computed | Not measured |
rust_doctor::structure::unreasoned_allow_attribute |
P3 | 80 | not judged | not rated | not computed | Not measured |
rust_doctor::structure::unreferenced_feature |
P3 | 2 | not judged | not rated | not computed | Not measured |
The two populations score differently
8.5 points between the mediansHealthy
- Median score
- 85
- Range
- 73 to 99
- Spread
- 26 points
- Bands
- 8 great, 2 needs work
Agent authored
- Median score
- 76.5
- Range
- 68 to 85
- Spread
- 17 points
- Bands
- 5 great, 3 needs work
Structural findings are denser on the agent population than on the healthy one: 5.36 per thousand production lines against 3.55, over 988,872 and 122,044 lines. A denser population is not by itself a noisier one, which is the question the next section asks.
Where the two rates can be compared
1 of 4 separatedFour structural rules are measured on both populations, so their rates can be differenced. The interval is a Newcombe hybrid score interval at 95%, and an interval that crosses zero means the two rates are indistinguishable at this sample size rather than equal.
| Rule | Healthy | Agent | 95% difference | Verdict |
|---|---|---|---|---|
rust_doctor::structure::complex_function |
87.1% | 70% | -34.4% to 2.8% | Indistinguishable (under coverage) |
rust_doctor::structure::duplicate_function_body |
40% | 23.9% | -39.7% to 6.8% | Indistinguishable (under coverage) |
rust_doctor::structure::near_duplicate_function_body |
63.3% | 44.2% | -39.4% to 4.0% | Indistinguishable (under coverage) |
rust_doctor::structure::oversized_unit |
33.3% | 13.5% | -37.3% to -0.6% | Separated (under coverage) |
All 4 comparisons sit under the coverage the method nominally wants, forty sites per arm, and one of them separates anyway. The limit is the corpus rather than the sampling: the healthy scope of one of these rules holds every production family the ten repositories have, so deepening it means pinning more repositories, not reviewing more of these.
Agreement between independent passes
219 pairs · 12 escalations openSites added under the current protocol were judged twice, by passes blind to each other, and a disagreement is excluded from the sample and left to a human rather than settled by the judge that produced it. Cohen's kappa is undefined when neither pass varies, which is why Gwet's AC1 is published beside it. A coefficient of 1 is total agreement, 0 is what chance alone would produce, and a negative one is worse than chance: a row that reads 0 of 3 is a rule whose two passes never once agreed, and all three of those pairs are in the escalation queue rather than in any rate above.
| Rule | Population | Agreed | Kappa | AC1 |
|---|---|---|---|---|
rust_doctor::structure::complex_function |
healthy | 0 of 3 | undefined | -1.00 |
rust_doctor::structure::duplicate_function_body |
agent | 46 of 48 | 0.89 | 0.93 |
rust_doctor::structure::near_duplicate_function_body |
agent | 43 of 43 | 1.00 | 1.00 |
rust_doctor::structure::near_duplicate_function_body |
healthy | 30 of 30 | 1.00 | 1.00 |
rust_doctor::structure::orphan_module_file |
agent | 12 of 12 | 1.00 | 1.00 |
rust_doctor::structure::oversized_unit |
agent | 37 of 37 | 1.00 | 1.00 |
rust_doctor::structure::oversized_unit |
healthy | 39 of 46 | 0.67 | 0.72 |
What this does not establish
limits- A rate at five reviewed sites cannot be placed against the 5% threshold. Read the interval, not the point.
- 36 catalogued rules never fired on this corpus and carry no rate at all.
- Verdicts recorded before 2026-08-21 carry no author on record and are published as they were measured rather than reattributed after the fact. A rate mixing provenances is worth its weakest one.
- Both populations are small, and neither is a random sample of Rust. They are ten repositories chosen for the shapes they exercise and eight chosen by a mechanical authorship criterion.
- Nothing here measures what the tool misses. Precision is not recall, and the record has no annotated ground truth to compute recall against.
Reproduce it
offlineThe measurement replays from a local clone cache and never reaches the network. Both directories must sit outside the repository, and naming one without the other fails rather than half configuring a run.
RUST_DOCTOR_CORPUS_DIR=<clone cache> \
RUST_DOCTOR_CORPUS_ARTIFACTS=<scratch> \
cargo test --test corpus_precision
Every published site is anchored to a run that located it. The position proof is a blake3 digest over the identity of every reviewed site and every adjudicated pair, recomputed offline on every cargo test: a site typed in by hand, at a line no scan ever reported, fails the suite.
- Position proof
- 2b3c827d5f910e96
- Anchored sites
- 671
- Toolchain
- 1.97.1
- Record digest
- bdc2329270dacf84
The record itself, with the verdict and the written justification behind every one of the 452 sites, is in the repository. This page publishes the rates; the record publishes the sites they were computed from.