Memory-Safe C in the Real World: Fil-C, Rust, and the Future of Legacy Code
ChatGPT & Benji Asperheim— Tue Nov 18th, 2025

Memory-Safe C in the Real World: Fil-C, Rust, and the Future of Legacy Code

For decades we’ve treated memory safety bugs in C as an uncomfortable fact of life: dangerous, expensive, but somehow unavoidable if you want performance and control. Now tools like Fil-C are forcing a more interesting question: what if we could harden existing C codebases—sudo, game engines, network daemons—without throwing everything away and starting over in Rust? Fil-C’s fat pointers, runtime checks, and garbage-collected semantics don’t magically turn C into a modern high-level language, but they do open an intriguing middle path between “ship and pray” on one side and “rewrite the world” on the other. The appeal is obvious: keep the battle-tested logic, bolt on strong runtime protections against memory corruption, and accept some overhead in exchange for fewer catastrophic bugs. It’s not a silver bullet, and it’s absolutely not free, but it hints at a future where memory safety isn’t limited only to greenfield projects and heroically ambitious rewrites.

Take a look at @ThePrimeTimeagen’s original video:

Short version: the video uses Fil-C as a case study in “memory-safe C” and ends up arguing that for big, existing C codebases (sudo, binutils, editors, etc.), tools like Fil-C are often a saner path than “rewrite it all in Rust,” but they’re not a universal solution, especially for performance-critical stuff like game engines.


What the Fil-C Video Covers

1. What Fil-C actually is

They stress that this is not “standard C with a library” — this is the default experience for Fil-C: C syntax, but every pointer access is checked and memory is GC’d.

2. Performance and overhead

Prime quotes concrete numbers from his experiments: Fil-C’s runtime impact is somewhere around 1.2x to 4x slower than plain C on the same code, depending on workload.

They also call out:

TJ (playing “Rust guy”) hammers the point that this is not a zero-cost abstraction: you pay in CPU and RAM to get these safety checks.

3. Why this came up: sudo, CVEs, and rewrites

Ed (low-level security) uses sudo as the motivating example:

The big point: changing language doesn’t preserve behavior. Rewriting a security-critical C program in Rust:

So Ed’s argument is basically:

Instead of rewriting everything in $NEW_LANG every 20 years, why not drop in a new compiler/runtime that adds strong memory checks on the existing, battle-tested C code?

That’s where Fil-C fits: same source, same logic, but instrumented memory.

4. Fil-C vs Rust vs sanitizers

They contrast Fil-C with two things:

  1. AddressSanitizer / UBSan

    • Great for testing, but not usually something you ship with; the overheads are huge and impact layout/ABI.
    • They don’t change the language; they’re debug-time tools. Fil-C is framed as something you could plausibly run in production for certain classes of software, albeit slower.
  2. Rust

    • Rust’s type system and borrow checker prevent a lot of memory errors statically, but not all: you can still have runtime panics that turn into denial-of-service conditions in privileged code.
    • There are also resource types (file handles, etc.) that neither Fil-C nor Rust make magically “safe” out of the box; Fil-C is focused on memory, not on all lifetime/resource issues.
    • Casey points out that both Fil-C and Rust can have bugs in their own memory-safety implementations; Rust doesn’t get a free pass there.

There’s even a section comparing Fil-C’s software approach to hardware memory tagging (using the high bits of pointers as tags and checking them against tagged memory regions on access), which is conceptually similar but implemented in silicon instead of the compiler/runtime.

5. Where would you actually use this?

Security-sensitive userland (sudo, editors, services)

Consensus: Fil-C is a pretty reasonable tool for stuff like:

Because:

Game engines and high-perf workloads

Prime asks Casey directly whether he’d use Fil-C in a game engine. Casey’s answer is basically “mostly no, occasionally yes”:

So Fil-C isn’t pitched as “rewrite your whole engine with this.” It’s more: maybe you wrap the dangerous choke points in a slower but safer runtime.


My take

Bluntly:

A few more concrete points.

1. For legacy C, Fil-C is one of the few realistic options

If you’ve got 500k—5M lines of C that’s been shipping for 20+ years, the panel is right: a wholesale Rust rewrite is usually fantasy. You don’t have the time, and you will absolutely ship new logic bugs along the way.

For that situation, a tool like Fil-C (or any compiler+runtime that:

is genuinely attractive. You get incremental hardening instead of a moonshot rewrite. That’s the strongest, most defensible argument in the video, and I think they’re right to lean on it.

2. GC-C is fine for some domains and wrong for others

Fil-C’s GC is both its selling point and a huge foot-gun:

So as a general systems language story, I wouldn’t sell “GC-C” as the future. As a hardening tool for the huge pile of non-real-time C out there, it’s a lot more reasonable.

3. Rust vs Fil-C isn’t a moral question; it’s a cost model

The video has some light Rust-baiting for entertainment, but strip that away and the trade-off is:

If I were starting a new privileged daemon from scratch in 2025, I’d still probably pick Rust or another modern memory-safe language, not Fil-C, because developer time and maintainability matter as much as raw safety. But if I owned sudo itself? I’d absolutely consider something like Fil-C (or future CHERI-like hardware) as a first step before signing up for a multi-year rewrite.

4. For games, I’d mostly stick with the current pattern

For your world (engines, tools, scripting, plugins), I think:

So Casey’s “maybe in tightly scoped, user-input-heavy parts, but not the whole engine” reads as the right answer.


Memory Safe Programming Languages

What are some memory safe programming languages? Short answer: anything that doesn’t let you casually scribble over raw memory tends to count. In practice there are a bunch of mainstream “memory-safe by default” languages.

Here are the big buckets:

  1. Managed, GC’d languages (memory safe unless you use native FFI):

    • Java, Kotlin
    • C# / F#
    • Go
    • Python
    • JavaScript / TypeScript
    • Ruby, PHP
    • Clojure, Scala, Elixir, etc.

These all use automatic memory management and only give you objects, arrays, and references—not raw pointers. Out-of-bounds and use-after-free are prevented by the runtime (you may get exceptions or panics, but not silent memory corruption).

  1. Statically typed, functional-ish, safe by design:

    • Haskell
    • OCaml / Reason / ReScript
    • Elm
    • Futhark, etc.

Same story: no raw pointer arithmetic in normal code, GC or region-based memory, strong type systems. Memory bugs are extremely rare outside of FFI.

  1. Systems languages with explicit safety models:

    • Rust — the poster child. The borrow checker + ownership rules prevent use-after-free, double free, and data races in “safe” Rust. There is unsafe as an escape hatch, but normal Rust code is designed to be memory safe.
    • Swift — ARC, bounds-checked arrays, strong typing. It has unsafe APIs you can opt into, but ordinary Swift code is memory safe.
    • Zig — not memory-safe by default like Rust, but it has safety features (bounds checks, use-after-free detection in debug modes) you can keep turned on; worth mentioning as “safer C”, not truly memory-safe.
  2. Specialized / research or niche languages focused on safety:

    • Ada/SPARK
    • Cyclone (historical, C-like safe language)
    • Pony, Rust-inspired research languages, various ML-family offshoots

Important nuance:

If you tell me what domain you care about (systems, web backend, games, embedded), I can narrow this down to the few languages that make the most sense for you to actually invest in.

Conclusion

Fil-C won’t replace Rust, and it won’t redeem every gnarly C codebase that should probably be retired, but it does prove something important: memory safety for legacy systems is not a lost cause. The trade-offs are real—higher CPU and RAM overhead, a garbage collector that changes timing characteristics, and safety that’s enforced at runtime rather than in the type system—but for the right targets, especially security-sensitive userland like sudo and network services, that price looks increasingly reasonable. In that sense, Fil-C feels less like a quirky experiment and more like a bridge technology: a way to carry critical C software into a safer era while the ecosystem slowly shifts toward languages with stronger guarantees. If we take it seriously, we don’t have to choose between “unsafe but fast” C and “rewrite everything” Rust evangelism. We can mix approaches, harden what we have, and reserve rewrites for when they actually pay off. That’s not the most glamorous vision of the future—but it might be the one that lets our software, and our users, survive long enough to see it.