Rust’s C FFI gives us access to decades of useful software, but the bargain is
backwards.
We use Rust to prove memory safety at compile time. Then we cross anunsafeboundary and trust the C library to respect a contract that neither language
can enforce. The legacy code remains the cheap path, while rewriting it is the
expensive one.
Fil-Coffers a more interesting bargain. It recompiles C
and C++ with capabilities, runtime checks, and a concurrent garbage collector.
Memory-safety violations panic instead of becoming exploits. Existing software
often needs few or no source changes, but it pays for safety at runtime.
I want a Rust FFI that speaks the Fil-C ABI.
This is not a new option forbindgen. Fil-C issource-compatible with C but intentionally not ABI-compatible,
and ordinary Rustextern “C”speaks the ABI Fil-C calls Yolo-C. Building the
bridge means teaching Rust, Fil-C, or a pair of generated stubs how to exchange
values without losing Fil-C’s guarantees. If it were easy, it would already
exist.
One important part of this stack is already taking shape.filnixpackages Fil-C as a Nix cross-compilation platform and has ports for more than
100 nixpkgs packages. Treating Fil-C as a platform means Nix rebuilds the
transitive dependency closure for the Fil-C ABI instead of accidentally
linking ordinary C into it. filnix is not the Rust bridge yet, but it provides
the reproducible toolchain, package universe, and test bed where one could be
built.
Zig is approaching the same problem from another direction. Andrew Kelley hasproposed an optionalfilABIinspired by Fil-C. It would be an independent implementation in the Zig
compiler and standard library, intended to compile a Zig program and its entire
C and C++ dependency tree with runtime memory safety. That is remarkably close
to the world a Rust bridge would need to enter.
But the result would give us exactly the right incentives.
We could use Rust for compile-time safety and then pay a performance penalty
for using C.
Keep the legacy library and it remains memory-safe, but every pointer operation
is checked and its memory participates in garbage collection. Rewrite the hot
path in Rust and those checks become static, so the tax disappears. C becomes
the safe compatibility path rather than the permanent fast path.
“100% safe” here means memory-safe across the whole supported boundary, not
free of logic bugs, deadlocks, or bad APIs. That boundary is the hard part.
Fil-C currently requiresthe whole program and its dependencies to use its ABI.
The project also treats interoperability with ordinary C as a non-goal. A Rust
bridge would have to preserve that whole-world guarantee rather than quietly
punching a Yolo-shaped hole through it.
I wantextern “fil-c”: Rust on the fast path, old C on the safe path, and a
performance reason to finish the migration.