At work the other day, I was reminded of the recent (at least, resurgent) discourse around memory safety and Rust (it's always Rust). I've made a lot of random comments on this topic around various friends and coworkers, but I figure I need to write things down more.
Just so we're clear, this post is about Fil-C. I'll probably be talking a little bit about memory safety in general, but this is really a [current hot topic] post more than anything else.
The Tech
Fil-C is a "fanatically compatible memory-safe implementation of C and C++". By my understanding, it is a clang pass that adds runtime integrity checks to memory accesses, along with an optional garbage-collecting runtime. If a memory violation is detected, the program aborts, rather than allowing memory to be corrupted.
From a technical perspective, this is really cool. Eliminating an entire class of vulnerabilities with nothing but a compiler change is awesome! Buffer overruns get taught in every undergraduate systems course as the most basic memory vulnerability, and simply eliminating it as a possibility is a really good idea!
It is also not the value proposition of Rust. Rust attempts to eliminate classes of bugs - data races and use-after-free, to name a few - at compile time, which means no incurred runtime overhead. If your deepest desire is a programming language that aborts at the language level on a bad memory operation, we've had that since 1995 -- write your app in Java! Or Python, or Ruby or Go or Scala or Haskell or Racket or any other high-level GC language!
If you're writing new code, it's not clear to me why you'd want to choose Fil-C over Rust, or any member of the high-level GC language zoo.
The real advantage to Fil-C is that it can be applied post-hoc to existing C/C++ code. This is great! Personally, I've always been skeptical of the whole rewrite-in-Rust movement, for the obvious reasons (loss of institutional knowledge, long ramp to MVP, generally questionable return on time invested). There's a lot of existing C in the world, and if the vast majority of it can be made "memory-safe" (more on that in a sec) simply by Clicking The Button, that should be celebrated!
There are, of course, other reasons to use a Systems Language instead of Java -- speed! I wasn't able to find hard numbers on how much overhead Fil-C really introduces, but social media suggests that the slowdown is on the order of 4x. That isn't an automatic deal-breaker, but it is enough to make me think twice in a performance-constrained environment.
"But Rust is slower than C, too!"
Maybe? Even setting aside that cross-language benchmarks are misleading, according to most versions of the benchmark game I could find1, Rust is generally within a factor of 2x of Clang-C. Even the non-unsafe/FFI/hand-vectorized versions generally sit very comfortably within the 4x margin of the fastest (= hand-vectorized/naked FFI) C benchmarks.
So what does this buy you? Proponents say Fil-C is "more safe"
than Rust due to not having an unsafe escape hatch.
To which I say, "sure"? Fil-C's guarantees absolutely aren't a
catchall for C memory issues. For example, it doesn't perform
checks within a structure, meaning something like
struct Foo {
char buf[N];
bool is_admin;
}
is still vulnerable. This is particularly problematic for programs that allocate one big chunk of memory that gets cut up into smaller objects (e.g. arena allocators).
Fil-C also requires that you recompile your entire dependency chain. This is allegedly a feature - Fil-C's creator is adamant that a single dependency using unsafe invalidates your entire memory safety claim - but I'm skeptical whether this approach scales. Does this mean you have to give up dynamic linking (or at least, dynamic linking against system objects)? Does it mean you can't use Fil-C at all if you don't have access to some dependency's source code?
The Discourse
Something I do not understand is why Rust lives so rent-free in so many of these people's minds.
For example, Zig's issue proposing a Fil-C mode includes a comment that is "actually memory safe (unlike Rust)" (at the time of writing, it has since been changed to "unlike borrow checking", but the conversation history includes the original title). What does this potshot accomplish? The issue was closed until "only serious people remain" (which, sure, most of the people coming in from social media probably didn't care one way or another what modes Zig had), but you cannot tell me with a straight face that you could not have seen this coming with such an inflammatory title.
I can even somewhat understand why Zig specifically has such a chip on its shoulder; Zig and Rust really are aimed at more-or-less the same niche, and Rust is, for better or worse, currently head-and-shoulders ahead in the race towards mainstream adoption. There's also been a lot of attention aimed at Zig vs Rust specifically due to the recent Bun rewrite in Rust. I have no particular opinions on the rewrite itself (and the Zig maintainer's response did not especially endear him to me), but I do think it is reasonable to be a bit spiteful after such a high-profile repudiation of your language.
But what about everyone else? The Fil-C creator spends a non-trivial amount of their social media presence highlighting anti-Rust comparisons. There are high-profile forks of projects with the sole purpose of deleting the Rust bits.
And why? There are a lot of stated concerns about cross-platform viability and not trusting rustc, but I personally think that's all talk. Why is perl any more trustworthy? Why are the only meaningful commits to WD-40 git forcibly restoring the "master" terminology and deleting the code of conduct? is this about technology, or is this about Rust being the "woke" language being DESTROYED by ONE CHAD?
On the subject of Fil-C in particular, at the time of writing, I see no direct evidence that Filip Pizlo is an alt-right sympathizer, even if there sure are a lot of blue check retweets.
But, like, why is Rust such a boogeyman? Why are people so gleeful about highlighting shortcomings in Rust's approach? I used to think there was an element of personal pride here ("I simply do not make memory mistakes"), but if that's the case, why is a garbage collected, crash-on-violation strategy currently the leading champion? Does anyone serious actually claim that Rust is so perfect that its flaws need to be blasted from the heavens?
Well, I suspect I know the answer. But that's depressing.
I make no claim that the particular aggregator I linked is authoritative; if you have a better one, feel free to direct me towards it!↩︎