The conventional wisdom about learning Rust goes something like this: it’s hard at first, but once ownership clicks, the path ahead is smooth. The Rust team’s recent research complicates that picture. Their survey found that challenges don’t disappear with experience; they get replaced by different ones. Beginners fight the borrow checker. Experienced network developers fight async complexity. Embedded teams run into ecosystem gaps. Safety-critical teams face certification problems that no amount of language fluency solves.
That finding reframes what improving Rust means. Fixing the learning curve is one problem. Fixing production-scale friction is another. The two require different investments.
The Problem Nobody Outgrows
Compilation speed shows up across every cohort the Rust team interviewed: novices, experts, embedded developers, web developers. The 2023 annual survey bears this out, with roughly 40 percent of respondents naming compilation times as their top complaint, a position it has held for four consecutive years.
The reasons are structural. Rust compiles to no stable ABI, so generic types get monomorphized at every crate boundary rather than shared. Duplication compounds across a large dependency tree. The LLVM backend, which handles final optimization and machine code generation, accounts for 50 to 70 percent of release build time on its own. Linking is expensive because Rust produces many small object files, one per code generation unit. A clean release build of a modest project takes seconds where Go would take a fraction of a second. Large production codebases like TiKV and Substrate have reported full clean builds exceeding 20 to 40 minutes.
The ecosystem has responded with a practical toolkit. sccache caches crate compilation artifacts and can cut CI build times by 60 to 80 percent on cache hits. The mold linker is 8 to 10 times faster than GNU ld; for a large Rust binary, the link phase can drop from 40 seconds to under 2 seconds. The Cranelift codegen backend, which replaces LLVM for debug builds, speeds compilation by 2 to 3 times; the Bevy game engine reported debug builds dropping from 30 seconds to 10 after switching. Cranelift is nightly-only for now, but it is progressing toward stable.
These mitigations are meaningful, but they do not make Rust compilation fast in an absolute sense; they reduce a recurring tax rather than eliminate it.
The Shifting Shape of Rust Friction
New Rust developers spend time fighting ownership and the borrow checker. This is well-documented and is probably the first thing anyone mentions about Rust’s learning curve. Less discussed is the fact that the borrow checker also occasionally rejects valid programs.
The canonical example is what the borrow checker team calls Problem Case 3: a function that borrows from a hash map to check if a key exists, then inserts into the map in the else branch. The current borrow checker, NLL (Non-Lexical Lifetimes), rejects this even though it is provably safe. Developers work around it with redundant lookups or unnecessary clones. Polonius, the next-generation borrow checker, uses a Datalog-based formalism that handles these cases correctly. Its original implementation had quadratic worst-case complexity on some programs; the Polonius 2.0 redesign addresses that. It is available under a nightly flag but was not ready for the Rust 2024 edition. Work continues.
The async story is more complicated. Rust’s async/await syntax stabilized in version 1.39 in November 2019. For the next four years, async functions inside trait definitions were not stable. Any trait with an async method required either a boxed future with heap allocation or the async-trait procedural macro, which boxes return types automatically. That crate recorded roughly 50 million downloads per month before async fn in traits finally stabilized in Rust 1.75 in December 2023, a five-year gap.
The 1.75 stabilization was real progress, but it left gaps. Dynamic dispatch with async trait methods still requires boxing. The Pin<Box<dyn Future<Output = T> + Send>> signatures that many async libraries expose remain genuinely difficult to read and write. The async ecosystem is also split between runtimes, primarily Tokio and async-std, that do not interoperate. Traits like AsyncRead and AsyncWrite have competing definitions across the futures crate, Tokio, and other libraries.
Bob Nystrom described this structural issue in 2015 as the “colored function” problem: once any function in a call chain is async, all of them must be. Rust inherited this property by design. The lack of a built-in async runtime in the standard library is a deliberate choice, not an oversight. It preserves flexibility across embedded, server, and other use cases. The cost is that every async project starts with a runtime selection that has downstream consequences.
The Certification Wall
For teams writing software where correctness has legal or safety consequences, the language being well-engineered is not sufficient. You need toolchain qualification. Aerospace software must meet DO-178C. Automotive software must meet ISO 26262. Medical devices, industrial control systems, and railway signaling all have their own standards, and all require that the compiler used to produce the software be qualified under those standards.
Until November 2023, no qualified Rust toolchain existed. Ferrocene, developed by Ferrous Systems and AdaCore and qualified by TÜV SÜD, changed that. It is now qualified for ISO 26262 ASIL D and IEC 61508 SIL 4, the highest safety integrity levels in those standards. DO-178C qualification for avionics, pursued in partnership with AdaCore, is in progress.
Ferrocene tracks upstream rustc but adds qualification artifacts: a Safety Manual documenting which language features are permissible in safety-critical code, a Tool Qualification Kit, and a Qualification Report from the notified body. The qualification covers the compiler as a software development tool under Part 8 of ISO 26262, not the generated code itself. Teams still need to validate their own code and processes against their applicable standard.
This is a genuine milestone. It opens doors that were previously closed to Rust in regulated industries. The AUTOSAR consortium published Rust safety coding guidelines in 2023. The wg-safety-critical working group tracks language-level requirements for the Rust language itself. The infrastructure is being assembled, but the pace is deliberate and the coverage is still narrow compared to what Ada and C toolchains have accumulated over decades.
Embedded’s Specific Problems
Embedded Rust has its own maturity timeline. The embedded-hal crate, which defines the standard hardware abstraction layer traits, spent years in 0.x versions with frequent breaking changes. Version 1.0 arrived in January 2024, giving the ecosystem a stable foundation. Embassy, the primary async embedded framework, still does not offer semver stability guarantees; its API changes between releases, which matters when firmware ships inside products.
DMA (Direct Memory Access) remains an architecturally unsolved problem. DMA transfers bypass the CPU entirely, which means Rust’s ownership system cannot directly enforce that a buffer remains unmodified during a transfer. Embassy’s approach is to require 'static lifetimes on DMA buffers, which is correct but forces static memory allocation. It works; it is not the ergonomic solution the community is still working toward.
probe-rs, the Rust-native debug probe interface, has improved substantially and is now the recommended tool in the official embedded Rust book. It programs flash 2 to 5 times faster than OpenOCD. Its chip description database has gaps for newer and more obscure MCUs, and its JTAG support lags its SWD support. These are solvable problems and they are being solved, but teams who hit them face real friction.
What the Research Confirms
The engineering manager quoted in the Rust team’s research said: “If all the things laid out were done, I’d be a happy Rust programmer. If not, I’d still be a Rust programmer.” That sounds like damning with faint praise, but it captures something accurate. The language solves problems important enough that developers tolerate the friction rather than walk away from it.
The Rust team’s research is useful less for naming Rust’s problems, which most developers already know, than for mapping them to experience levels and domains. That mapping clarifies where investment belongs. Compilation improvements help everyone. Async work helps the large and growing server and network developer cohort. Certification infrastructure helps safety-critical teams who currently have no viable alternative to C or Ada. Embedded ecosystem investment helps a productive community that is still working around gaps.
Most of these efforts are already underway. The gradient is clearly positive. That is why people keep using Rust despite the friction, and why understanding the friction precisely matters for making it better.