# Memory Safety Absolutists

Piotr Sarnacki wrote this in response to a shift in how memory safety gets argued about. The absolutists of the title are not Rust developers, which is the reading the title invites; they're the people now arguing that Rust doesn't count as memory-safe because it has `unsafe`.

## The setup

Until recently the terrain for non-GC systems languages was simple. Rust refuses to compile programs that may introduce memory safety issues, accepting that it will sometimes reject a program that would have been fine, and offers `unsafe` as the escape hatch for things like dereferencing raw pointers. C and its neighbors leave memory safety to the programmer, with varying amounts of help — RAII and smart pointers in C++, `defer` in [[zig]] — but nothing that stops a violation.

Fil-C changes that terrain. C and C++ compiled with Fil-C panic on invalid memory access, out-of-bounds reads and use-after-free among them, by combining a GC with InvisiCaps to track what memory a pointer is allowed to reach; [[simplified-model-of-fil-c]] walks through the mechanism. Andrew Kelley has announced a Zig compilation mode inspired by it. Sarnacki is unambiguous that he wants this to succeed and hopes popular C and C++ projects ship Fil-C-compiled releases.

## The claim he's answering

The argument he keeps encountering runs: if Rust people really cared about memory safety they would promote Fil-C and abandon Rust, since Fil-C is safer; otherwise they only care about their new language. Fil-C's author makes a version of it on Twitter, where the recurring claim is that Rust is a memory-unsafe language because `unsafe` can bypass its guarantees. Kelley's issue title carries the same charge in parentheses: "introduce an actually memory safe (unlike Rust) compilation mode inspired by Fil-C."

Sarnacki's read is that this is the same cult-like behavior Rust developers get accused of, pointed the other way.

## The rebuttal, in four moves

The first is that the premise assumes a drop-in replacement, and Fil-C is not one. It's ABI-incompatible with programs not compiled with it, it can be several times slower in some cases, and it introduces a GC. None of those is fatal for a lot of software — plenty of programs could run several times slower without anyone noticing, and plenty link nothing dynamically. But the projects where a GC and ABI incompatibility are disqualifying are real and popular, and they are frequently the same projects Rust is a good fit for. The two technologies don't overlap the way the argument needs them to.

The second is the practical record. Sarnacki is careful that there isn't much data on how secure Rust is in the field, but the Android numbers are the largest sample available: roughly 5 million lines of Rust in the Android platform, one potential memory safety vulnerability found and fixed pre-release, an estimated density of 0.2 vulnerabilities per million lines. Google's historical figure for its C and C++ is closer to 1,000 per MLOC, more than a 1000x difference. Other projects would land elsewhere, but the direction is established.

The third is the shape of the choice. Would you take a technology that prevents 99.9% of issues in 100% of programs, or 100% of issues in 90% of programs? Sarnacki tags his own numbers as invented and the point as the framing rather than the arithmetic. His answer is that the choice is false: C, C++, and Zig projects that can accept the trade-offs should ship Fil-C binaries, and the software that can't should be written in languages that remove most or all of the risk another way.

The fourth is that Fil-C's guarantee has a shape too. Those 1,000 vulnerabilities per MLOC don't vanish under Fil-C, they become crashes. Better than a security vulnerability, but still a lot of crashes to fix — and if the discussion is already about rare failure modes, it's fair to note that there have been security vulnerabilities enabled by an attacker's ability to crash a program.

He also defends using Rust where a garbage-collected language like Golang would have worked, against absolutists who say that's unacceptable. The observation underneath is that the two populations barely intersect: programs that could have been written in a GC language usually don't need `unsafe` at all, and programs that need `unsafe` usually couldn't have used a GC. And people weighing trade-offs rather than applying a rule often find that other guarantees, data-race prevention in particular, outweigh a very small residual risk. That's the [[rust-send-sync]] half of the language, which Fil-C's approach doesn't address at all.

The closing move is a consistency test. If Rust's 0.2 vulnerabilities per MLOC is genuinely intolerable to you, you should be criticizing people compiling YOLO C, C++, and non-fil Zig at least as loudly. He notes that some absolutists apply the standard only to Rust.

## Where this connects

The "Rust has `unsafe`, therefore Rust is unsafe" step is the one doing all the work, and [[safety-in-an-unsafe-world]] is the direct counter-argument to it. Joshua Liebow-Feeser's position is that memory safety is not something Rust gives you but something a library gives you, and Rust ships exactly one instance of that in the box; `unsafe` is the tool for encapsulating a proof, not a hole in the type system. The Netstack3 evidence there points the same way as the Android numbers Sarnacki cites: 192,000 lines of Rust networking code, eleven months of dogfooding, three bugs found. Neither Sarnacki nor Liebow-Feeser argues Rust is unbreakable; both argue that the interesting quantity is how often it breaks, not whether the language admits the possibility.

[[cobaltc]], a speculative C-successor specification, takes Rust's side: `unsafe` is an explicit, local boundary, and unsafe code may implement a safe abstraction but must not export an invariant the safe interface cannot guarantee. [[ability-guarantee-tradeoff]] gives the general shape of Rust's bargain, a compiler that accepts fewer programs in exchange for guarantees, with `unsafe` as the way back into the larger set.
