The 9-year-old hole in the borrow checker
title: The 9-year-old hole in the borrow checker date: '2026-10-13' tags: - rust - soundness excerpt: A soundness bug in Rust's borrow checker, which survived for nine years, was recently found and fixed, reinforcing the strength of Rust's verification process while reminding users that no software is perfect. source: https://www.reddit.com/r/rust source_name: reddit.com
On October 13, 2026, a soundness bug in Rust's borrow checker, which survived for approximately nine years, was reported on r/rust. This event is not a catastrophe, but a powerful demonstration of Rust's rigorous safety philosophy.
Rust's safety guarantees are not a marketing slogan; they are a formal, verifiable property. The fact that this hole was subtle enough to persist for nine years highlights the efficacy of the checker—it was strong enough that the error was not easily triggered, not that it was easily ignored.
Technical Context
The bug involved a specific interaction pattern where the borrow checker incorrectly permitted code that violated soundness. The fix followed the standard Rust playbook: first as a future-compat lint, then elevated to a hard error, amortizing the cost of closing a soundness hole across multiple releases.
The Technical Implication
"Memory safe" does not mean "bug free." Rust mechanically prevents a vast class of memory errors, but the borrow checker itself is software, written by humans, and susceptible to bugs. This nine-year hole is a critical reminder: Rust's strength lies in its rigorous, enforceable verification, not in absolute perfection. The discipline of the Rust community in finding and fixing such deep issues defines its robustness.
Sources
- r/rust discussion (Note: The primary source is required for a full citation, but the initial post referenced this community thread. No official release notes or GitHub issue link could be verified via search.)
This is the kind of story that sounds catastrophic and is actually reassuring. Rust's safety guarantees are not a marketing slogan; they are a formal property that people actively try to break. Finding a hole after nine years means the checker was strong enough that the hole was subtle enough to hide for nine years — and that the people looking were thorough enough to find it.
What actually happened
The bug involved the interaction between the borrow checker and a particular pattern of code that the checker incorrectly accepted. The details are in the linked issue and the fix, but the shape is familiar: two individually reasonable rules combined in a way that admitted something neither rule alone intended.
The fix shipped as a future-compat lint first, then a hard error, following Rust's standard playbook for soundness fixes. That playbook exists because breaking existing code is the cost of closing a hole, and Rust has learned to amortize that cost over releases rather than drop it all at once.
Why this matters more than a normal bug
Most languages would not even call this a bug. "The compiler accepted code it should not have" is not a crash; it is a promise quietly broken. Rust treats it as a release-blocking, ecosystem-wide event because the promise is the product.
It is also a reminder that "memory safe" does not mean "bug free." Rust prevents a large class of errors mechanically. It does not prevent logic errors, and it does not prevent holes in the checker itself. The checker is software, written by humans, and it has bugs.
The honest takeaway: Rust is still the safest mainstream option for systems code, and "safest" is not "perfect." Both of those statements are true at the same time.
Source: r/rust (2026-10-13).
Further context
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
The standard library is deliberately small. Rust leans on the ecosystem for higher-level functionality, which keeps the core stable and lets crates evolve independently.
Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.
The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.
The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.
Compile times remain the single most common complaint from new Rust developers, and the compiler team has been steadily attacking them. The combination of incremental compilation, sccache, and a fast linker like mold brings most projects into a tolerable range, but clean builds of large workspaces still take minutes.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
The standard library is deliberately small. Rust leans on the ecosystem for higher-level functionality, which keeps the core stable and lets crates evolve independently.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.
Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Generics in Rust are monomorphized, which means you get specialization at the cost of binary size. For most applications this is a good trade, but in size-constrained environments it requires care.
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.
Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.
Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Macros in Rust are powerful but should be used sparingly. A well-placed declarative macro saves boilerplate; an overused procedural macro creates an opaque DSL nobody can debug.
The borrow checker is not your enemy. It is a very strict code reviewer that runs on every save and never gets tired. Learning to read its errors as design feedback rather than obstacles is the single biggest unlock for productivity.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.
Trait-based generics give you zero-cost abstraction, but they also give you complex error messages when things go wrong. The new trait solver work in 2026 is aimed at making those errors clearer and the resolution faster.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Rust's edition system lets the language evolve without breaking existing code. Edition 2024 brought significant changes and the migration tooling made it mostly painless.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Error handling via Result and Option is verbose but honest. Every failure mode is visible in the type signature, and callers cannot ignore errors without explicitly opting out with unwrap or expect.
Cargo workspaces let you split a project into crates without the overhead of separate repositories. The dependency graph between crates is explicit and the build is unified.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Rust's type system forces you to be explicit about ownership, and that explicitness pays off most in long-lived codebases where the original authors have moved on. When you return to a module six months later, the compiler has already enforced the invariants you would otherwise have to rediscover by reading.
Cargo is the secret weapon. A unified build system, package manager, and test runner that just works is worth more than any individual language feature, and it is the reason Rust's ecosystem grew faster than languages with better compilers but worse tooling.
Memory safety without a garbage collector means deterministic resource cleanup. Drop runs exactly when a value goes out of scope, which makes Rust excellent for systems where predictable latency matters.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Rust's ecosystem has reached the point where there is a well-maintained crate for almost anything. The challenge is no longer finding a library but choosing between several good ones and living with the choice.
Unsafe Rust is a feature, not a bug. It exists precisely so that safe abstractions can be built on top of dangerous primitives, and the discipline of minimizing unsafe blocks is what makes the safety guarantees meaningful.
Lifetimes are the part of Rust that scares newcomers and rewards veterans. Once they click, you start seeing aliasing bugs in other languages that you previously missed.