Cargo is the Rust build tool and package manager. This analysis covers 9,162 functions across the repository at commit 07b8049, with 427 landing in the critical band. The top finding is publish in src/ops/registry/cargo_publish.rs, sitting in the fire quadrant with a cyclomatic complexity of 25, a nesting depth of 5, and a fan-out of 23, last changed just 6 days ago. That combination is the headline: this isn’t a stale function nobody looks at, it’s a wide, deeply branched function someone touched less than a week ago — exactly the profile I’d want on a review queue before the next release cycle.
The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).
Top 5 Hotspots
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
publish | src/ops/registry/cargo_publish.rs | 26.6 | 25 | 5 | 23 |
run | src/ops/cargo_run.rs | 23.2 | 17 | 3 | 16 |
replace | src/workspace/parser/mod.rs | 21.5 | 10 | 3 | 10 |
get | src/ops/cargo_config.rs | 20.1 | 20 | 3 | 8 |
push_md | crates/mdman/src/format/text.rs | 19.4 | 124 | 10 | 24 |
9,162 functions analyzed
The quadrant split tells its own story before I get to individual functions: 993 functions sit in structural debt (complex but dormant), versus 138 in active fire. Debt outnumbers fire by roughly 7 to 1, which is a normal shape for a mature codebase — most complexity accumulates quietly and gets revisited in bursts. The five functions below are the exceptions worth naming individually, because they sit at the intersection of hard-to-reason-about and either currently changing or carrying a large blast radius for whoever touches them next.
Function body is too long to review in a single pass; likely contains multiple distinct responsibilities.Exit Heavy×6Exit Heavy
Multiple return or throw paths dispersed through the body — each exit needs separate test coverage.God Function×6God Function
Calls an unusually large number of distinct functions (high fan-out), making it the structural centre of gravity for a subsystem.Cyclic Hub×6Cyclic Hub
Participates in a call cycle with other high-traffic functions, creating circular dependency risk.Complex Branching×5Complex Branching
High cyclomatic complexity — many independent execution paths, each a potential bug surface and required test case.Hub Function×4Hub Function
Many other functions call this one — a change here ripples widely through callers.Deeply Nested×2Deeply Nested
Control structures nested 4+ levels deep, making it hard to reason about the full execution state at inner branches.
Across the top hotspots, long-function and exit-heavy show up most often — 8 and 6 occurrences respectively — followed closely by god-function and cyclic-hub patterns at 6 each. That combination is consistent with what I’d expect from a CLI-driven tool like cargo: top-level command handlers (publish, run, get) tend to accumulate validation branches, early returns, and calls out to a dozen-plus collaborators, because they’re the place where user input meets the rest of the system.
publish — src/ops/registry/cargo_publish.rs
This is the top-ranked function in the dataset, and the source excerpt shows why. It walks through package spec matching, filters unpublishable packages against workspace visibility rules, branches on whether --workspace was passed, and only then acquires a cache lock and starts verifying dependencies against the registry. That’s a lot of sequential decision points before the actual publish logic even begins — consistent with the cyclomatic complexity of 25 and a nesting depth of 5. The fan-out of 23 means this function is a hub: it calls into spec resolution, feature resolution, registry source lookup, and verification routines, so a change to any of those call signatures likely means a change here too. It was touched once in the last 30 days and modified as recently as 6 days ago, with 2 distinct authors working on the surrounding file in the last 90 days and a bug-fix rate of 14% recorded historically. None of that proves the current logic is broken, but the shape — high fan-out, high nesting, recent edits — is exactly the profile where a small change to one branch can silently break another. I’d extract the unpublishable-package filtering and the registry-resolution steps into named helper functions before the next edit lands here; that alone would cut the visible branching in the top-level function significantly.
run — src/ops/cargo_run.rs
This one is structural debt, not live churn — it hasn’t been changed in 141 days and had zero touches in the last 30. The source excerpt shows a cascade of validation checks: glob pattern rejection, binary target filtering, and then three separate branches handling zero, one, or multiple matching binaries, each with its own error message construction. A cyclomatic complexity of 17 and fan-out of 16 in a function this shape means whoever next modifies cargo run target-selection behavior is going to be reading through all three of those branches to understand where their change fits. Because it’s dormant, the real risk isn’t right now — it’s the day someone needs to add a new target-selection flag and has to untangle this logic cold. Given the zero recorded bug-fix history and a single commit author in the historical record, this reads as legitimate accumulated complexity rather than a source of past incidents. Worth a scoping pass — decompose the binary-count branching (0 / 1 / many) into a match returning a result type — the next time this file is opened for any reason.
replace — src/workspace/parser/mod.rs
This function parses the [replace] section of a workspace manifest, and it sits in the fire quadrant: a cyclomatic complexity of 10 is moderate, but it was touched once in the last 30 days, last changed only 2 days ago, and the surrounding file shows 10 distinct authors in the last 90 days — the widest ownership spread of anything in this top five. The historical bug-fix rate on this file sits at 71%, the highest of any function analyzed here, and the review-comment density (2.5) is also the highest recorded — both are file-level signals, not proof this exact function is defective, but they mean this parsing logic has drawn sustained reviewer attention and correction over time. Combined with active edits happening right now, I’d treat this as a live regression-risk candidate rather than a backlog item: get a second reviewer on any pending change here, and consider adding explicit test cases for the semver-exact-match branch that the source shows building the replacement dependency.
get — src/ops/cargo_config.rs
Another debt-quadrant function — zero touches in 30 days, 141 days since its last change. The source shows a nested dispatch: first branching on output format compatibility with --show-origin, then branching again on merged versus unmerged config resolution, with each branch fanning out into format-specific print functions (print_toml, print_json, print_toml_env, print_json_env). A cyclomatic complexity of 20 for what reads as primarily format-selection logic suggests the branching could collapse into a lookup table or a smaller set of format-handling trait implementations rather than repeated match arms. This is textbook high-blast-radius-when-next-touched: nobody is working on it now, but the next person who adds a new output format will be threading a new branch through code that already has 20 paths to keep straight.
push_md — crates/mdman/src/format/text.rs
This is the outlier of the set, and it’s worth calling out on its own. A cyclomatic complexity of 124 and a nesting depth of 10 are both far beyond anything else in this analysis, with a fan-out of 24 — the source excerpt confirms why: it’s a markdown-event dispatcher with a nested match over event types, and inside that, a further match over tag types (paragraph, heading levels, blockquote, code block, list, item, footnote, table), each with its own indentation and formatting side effects.
That’s four times the complexity of the next-highest function in this list, in a function with zero touches in 30 days and 141 days since last change, and zero authors recorded in the last 90 days on this file. This is pure structural debt sitting in a documentation-generation tool bundled with cargo — nobody is actively editing it, but if a new markdown tag type needs handling, whoever picks up that work is stepping into a 124-path function with 10 levels of nesting. My first move here would be extracting each Tag:: arm into its own named function — the list-item and heading-level handling alone look like natural extraction points — before adding any new event type support.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
long_function | 8 |
exit_heavy | 6 |
god_function | 6 |
cyclic_hub | 6 |
complex_branching | 5 |
hub_function | 4 |
deeply_nested | 2 |
These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.
See more analyses with these patterns: complex_branching, cyclic_hub, deeply_nested, exit_heavy, god_function, hub_function, long_function.
Reproduce This Analysis
git clone https://github.com/rust-lang/cargo
cd cargo
git checkout 07b80494920f3824e2515e536b76ff282e23993e
hotspots analyze . --mode snapshot --explain-patterns --force
To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.
I use Hotspots to highlight structural and activity risk — not “bad code.” I treat these findings as a prioritization aid, not a bug predictor. Editorial policy →