Rust Code Health: Patterns Across 27 Open-Source Repositories

An analysis of code health patterns across 27 open-source Rust repositories, examining which antipatterns appear most frequently and which projects carry the highest structural risk.

Stephen Collins ·

Key Points

What are the most common antipatterns in Rust open-source codebases?

Long functions appear in 100% of analyzed Rust repositories (27 of 27), followed by exit-heavy functions in 96% (26 of 27), and complex branching in 93% (25 of 27).

Which open-source Rust projects have the highest code complexity risk?

DioxusLabs/dioxus leads with a risk score of 41.1, followed by nushell/nushell at 37.1 and astral-sh/ruff at 26.0. The average top risk score across all 27 repos is 19.9.

How does Rust compare to other languages in code health?

Rust codebases show a strong tendency toward long functions and multiple exit points, likely influenced by the language's Result-based error handling and match expressions. The median top risk score of 18.9 suggests moderate structural complexity overall.

Rust’s ownership model and compiler strictness are supposed to guide developers toward better code. Yet when I analyzed 27 open-source Rust repositories, I found long functions in every single one. The language’s type system catches memory bugs, but it doesn’t stop a function from growing to 500 lines or accumulating a cyclomatic complexity score that makes testing impractical.

Methodology

I computed activity risk for functions across all 27 repositories by combining structural complexity (cyclomatic complexity × nesting depth × fan-out) with recent commit frequency. Functions that are both complex and actively changing score highest—these represent the most urgent refactoring candidates. The analysis window covered recent git history to weight actively-maintained code over legacy modules.

The Most Common Antipatterns

Long functions appeared in 27 of 27 repositories—a perfect score that should concern no one familiar with real-world codebases. Rust’s pattern matching and explicit error handling often encourage developers to keep related logic together rather than split it across helper functions. This isn’t inherently wrong, but it creates maintenance problems when a single function handles multiple responsibilities.

Exit-heavy functions showed up in 26 of 27 repos. This pattern reflects Rust’s idiomatic use of early returns with the ? operator and explicit return statements for error cases. While early returns can improve readability, excessive exit points scatter control flow and make it harder to reason about a function’s invariants. The language encourages this style, so Rust teams need to be more deliberate about function boundaries.

Complex branching appeared in 25 of 27 repositories. Match expressions are powerful, but they also make it easy to accumulate high cyclomatic complexity within a single function. When a match statement handles ten variants, each with its own logic, you’ve created a function that’s difficult to test exhaustively.

The Highest-Risk Repositories

DioxusLabs/dioxus recorded the highest risk score at 41.1—more than double the median. The primary drivers were long functions, god functions, and neighbor risk, suggesting that complex functions are calling other complex functions. This creates a cascade where touching one hotspot forces you to understand its entire call neighborhood.

nushell/nushell followed at 37.1, with complex branching and deep nesting as the main contributors. Shell implementations tend toward intricate parsing and evaluation logic, but a score this high indicates functions that have grown beyond reasonable maintainability.

astral-sh/ruff came in at 26.0, driven by long functions, god functions, and complex branching. Linter implementations are inherently complex—they must handle every syntactic edge case—but the concentration of risk in specific functions suggests opportunities to extract rule-specific logic into smaller units.

juspay/hyperswitch scored 21.2, with patterns centered on complex branching, deep nesting, and exit-heavy functions. Payment processing involves significant conditional logic, but the combination of these three patterns in the same functions creates maintenance friction.

vercel-labs/agent-browser registered 21.7, showing similar patterns to hyperswitch: complex branching, deep nesting, and exit-heavy code. Browser automation logic tends to accumulate conditionals as edge cases are discovered and handled inline.

What This Means for Rust Developers

The 100% prevalence of long functions suggests this is a cultural pattern, not an accident. Rust’s emphasis on explicit control flow—combined with the ergonomic cost of creating new types and traits—pushes developers toward keeping logic in fewer, larger functions. The compiler won’t complain, and the code will run correctly, but you’re accumulating structural debt that makes future changes riskier.

The median top risk score of 18.9 is moderate, but the spread matters. DioxusLabs/dioxus at 41.1 is more than twice the median, indicating that some codebases have significant concentrations of complexity. If your repository has similar patterns, focus refactoring effort on functions that score high on activity risk—they’re complex, they’re changing, and they’re likely to cause problems during your next feature push.

Analyze Your Own Repository

You can run the same analysis on any local Rust repository. Install the CLI:

brew install Stephen-Collins-tech/tap/hotspots

Or on any platform with Cargo:

cargo install hotspots-cli

Then run:

hotspots analyze .

The output will show your highest-risk functions ranked by activity risk, along with the specific antipatterns driving each score.

Was this useful? Let me know →

Want to see analysis like this for your own codebase? Try hotspots — free & open source →