Rust, part 15: the state of Rust today — 1.98, the supply chain, and the borrow checker's next act
Part 15from the Rust series · 15 parts in all
The stable compiler is at 1.98 as this is written, with the 2024 edition a year and a half behind us. The interesting questions in 2026 are no longer "is Rust viable" — that was settled — but which of the remaining rough edges are actually being worked on, and which have turned out to be permanent.
What is genuinely settled now
- The async story composes.
async fnin traits (1.75, part 8), async closures (1.85, part 13), and a stable set ofAsyncFntraits mean the macro-and-box workarounds are now legacy rather than required. New async code does not needasync_trait, and the crates that still carry it do so for compatibility. serde, tokio and clap are the de facto standard library extension. Not because the language chose them, but because the ecosystem converged and nobody benefits from a fourth JSON crate.- Rust is in the kernel, in Windows, in Android and in the browser engines. The incremental-adoption-through-a-C-ABI pattern from part 4 is now the normal way a large C or C++ codebase takes Rust on, and it works.
The supply chain, which is the real 2026 conversation
Almost every production Rust question I get asked now is about dependencies, not about borrows:
# The baseline hygiene commands, all worth wiring into CI.
cargo deny check advisories bans licenses sources
cargo audit
cargo tree -d # duplicated majors - the upgrade you have been avoiding
cargo semver-checks # does this release actually break your public API?
# And the lockfile rule that matters more than any tool:
# a binary commits Cargo.lock. A library does not.
The surface area is the point: a typical service has hundreds of transitive crates, and
that is a fact to manage rather than a reason to avoid Rust. The tools above are mature, and
cargo-vet — recording that a specific human reviewed a specific version — is what
the high-assurance end of the ecosystem uses instead of pretending review happened.
Polonius, and why the borrow checker is still being rewritten
The borrow checker the compiler ships is not the one its designers want. The current
implementation uses a "mid-point" dataflow analysis whose limitations are the reason for the
error messages that make no sense: the pattern that makes you clone a Vec
unnecessarily, or refuse a conditional return of a reference obtained before a mutation. The
replacement, Polonius, has been in development for years, and is now available
as an opt-in on the newer compilers rather than a default.
What it fixes is narrow and real:
fn get_or_insert(map: &mut HashMap<String, String>, key: &str) -> &str {
if let Some(v) = map.get(key) {
return v; // borrowed map immutably, returned it
}
map.insert(key.to_string(), String::new()); // needs a mutable borrow
map.get(key).unwrap() // today: may need restructuring
}
Under the current analysis this can be rejected because it considers the first borrow live
across the insert; Polonius reasons about which paths reach which borrows
and accepts it. That is a genuine improvement to code people actually write, and it is the
change most likely to make Rust feel different in the next few years. Treat the timing as
in-progress: it is opt-in now, and I would not schedule a redesign around it.
What I would tell someone starting today
- Learn ownership properly, once (part 1). Everything else is downstream of it, and the people who fight Rust are usually fighting this.
- Use
thiserrorin libraries andanyhowin binaries (part 2), and resist reaching forRc<RefCell>to make the compiler stop complaining. - Write the straightforward safe code, and keep
unsafein one module behind a safe API with documented invariants (part 11). - Pick the runtime deliberately, and remember that in async Rust nothing is concurrent unless a combinator or a spawn says so (part 7).
Fifteen parts ago this series started with three rules about ownership. The through-line is that Rust's difficulty is front-loaded and its benefits are structural: the borrow checker, the type system and the error model all move work from production to the compiler. Fifteen years of industry experience says that is the right direction to move work in.