Rust’s compiler is famous for catching bugs at compile time. Memory safety, thread safety, null pointer dereferences — the borrow checker handles them all. But static analysis of 11 open-source Rust repositories reveals a different story: every single one contains exit-heavy functions and long functions. The ownership model prevents certain bug classes; it doesn’t prevent functions from growing into unmaintainable sprawl.
Methodology
I measured activity risk across these 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 — they represent the most urgent refactoring targets. The analysis window covers recent git history to weight actively-developed code over dormant modules. Repositories were selected from popular, actively-maintained Rust projects spanning CLI tools, GUI frameworks, SDKs, and editor infrastructure.
The Most Common Antipatterns
Exit-heavy functions appeared in all 11 repositories. In Rust, this often manifests as chains of early returns handling Result and Option types — the ? operator makes it easy to sprinkle exit points throughout a function. While individual early returns are idiomatic, accumulating many of them fragments control flow and makes reasoning about function behavior harder.
Long functions also appeared universally. Rust’s explicit error handling, pattern matching, and lifetime annotations add verbosity that can push functions past reasonable lengths even when the underlying logic isn’t complex. The median function flagged for this pattern contained over 100 lines of implementation code.
Complex branching showed up in 9 of 11 repos. Rust’s powerful match expressions encourage exhaustive handling of variants, but complex enums with many cases can produce functions with cyclomatic complexity exceeding 15. Combined with nested if let chains, this creates functions that are difficult to test thoroughly.
God functions — combining high complexity, high fan-out, and excessive length — appeared in 9 of 11 repos as well. These represent the highest structural priority for refactoring.
The Highest-Risk Repositories
casey/just leads with a risk score of 19.1. The command runner’s parser and executor contain complex branching, deep nesting, and scattered exits. Parsing DSLs tends to produce this signature — handling many grammar rules in a single pass accumulates conditional paths quickly.
iced-rs/iced and jdx/mise both score 18.6. Iced shows long functions and god functions driven by layout and rendering logic that resists decomposition — a common property of GUI frameworks. Mise shows the same branching and nesting patterns; CLI tools handling many subcommands and configuration options share these characteristics.
FuelLabs/fuels-rs scored 18.5 with a distinct profile: exit-heavy functions, god functions, and stale complexity. The SDK contains complex functions that haven’t been modified recently, representing latent risk that will surface when those areas need changes.
lapce/lapce rounds out the top five at 18.1. The Rust-native code editor carries complex branching and deep nesting in its core editing and rendering paths — structural patterns common in editor infrastructure regardless of language.
What This Means for Rust Developers
Rust’s safety guarantees are real, but they operate at a different layer than structural code health. The borrow checker ensures memory safety; it says nothing about whether your function has grown to 200 lines with 12 return points. In fact, Rust’s explicitness can mask complexity growth — handling every Result and matching every enum variant produces code that looks thorough while becoming harder to modify.
The prevalence of exit-heavy functions across all 11 repositories suggests this is a Rust-specific pattern worth monitoring. Consider extracting helper functions or using combinators like and_then and map to consolidate exit points. For complex branching in match expressions, breaking out match arms into separate functions can reduce cyclomatic complexity without losing the exhaustiveness guarantees.
Analyze Your Own Repository
Run the same analysis on your codebase:
brew install Stephen-Collins-tech/tap/hotspots
Or on any platform:
cargo install hotspots-cli
Then in your repository:
hotspots analyze .
The output identifies your highest-risk functions ranked by the same activity risk metric used in this analysis.