Hacker News new | ask | show | jobs
by jitl 8 days ago
Rust is less safe because it has a feature for turning off safety, called `unsafe`. Fil-C does not have a way to turn off safety, and it enforces safety checks at runtime. That's the reasoning anyways. If you define another language Rust-Without-Any-Unsafe, then maybe that one is safer than Fil-C.
2 comments

> If you define another language Rust-Without-Any-Unsafe, then maybe that one is safer than Fil-C.

Just write `#![forbid(unsafe_code)]` at the top of your src/lib.rs, and track crates not using it with `cargo geiger`. You don't need a whole new language, it already provides the tools to wield that hatch shut.

> Rust is less safe because it has a feature for turning off safety

Can I write Fil-C's mmap wrapper in Fil-C?

If no, fair enough, but it's worth noting I can write a safe Rust mmap wrapper in Rust, and I absolutely and frequently need to do that kind of "syscall wrapping" in arenas Fil-C explicitly hasn't handled, by virtue of being explicitly a Linux project.

If yes, that sounds like an escape hatch to Fil-C's memory safety, undermining the claim that Fil-C is fundamentally safer, and you're now at best arguing it's safer as tends to be used.

It should be mentioned that rust's type system has a long-standing known bug compromising memory safety, as made famous by cve-rs. It's perhaps not a big issue for most people but if you are someone that wants the assurances of #![forbid(unsafe_code)] that should probably be on your radar.
Certainly, we should build into our threat model the idea that the implementation of Rust will have bugs that compromise safety until proven otherwise (merely fixing that one aforementioned bug won't alter that calculus). And the same applies to Fil-C: we should assume it has bugs that compromise safety until proven otherwise. Until then, in practice, Rust has much more real-world use that convincingly demonstrates its ability to realistically eliminate memory safety risks.
A known bug with easily accessible proof-of-concept is quite different from a theoretical bug.
No, that's not how this works. The bug being utilized by cve-rs has such roundabout requirements that it's unlikely that anyone has ever triggered it without trying (to be clear, the Rust devs plan to fix it regardless). Meanwhile, here's a memory safety bug that Fil-C fails to catch, not because of a compiler bug, but by design: https://www.reddit.com/r/cpp/comments/1v4nw0k/filc_garbage_i...
I've encountered a few soundness holes in rust-lang in practice, but they've all been fixed before I managed to shoot myself in the foot with any of them:

• `std::mem::uninitialized()`. It's now deprecated in favor of `MaybeUninit`.

• `std::env::set_var(...)`. It's now marked `unsafe`. While I dodged the bullet, these fellows didn't: https://www.geldata.com/blog/c-stdlib-isn-t-threadsafe-and-e...

• `#[no_mangle]`. It's now `#[unsafe(no_mangle)]`.

I don't believe I've constructed cvs-rs's hole by accident. cve-rs's code links to https://github.com/rust-lang/rust/issues/25860 , which is admittedly still open after a decade. Progress appears to still be ongoing though! Related:

https://github.com/orgs/rust-lang/projects/44/views/1

https://rust-lang.github.io/rust-project-goals/2025h2/next-s...

> Meanwhile, here's a memory safety bug that Fil-C fails to catch, not because of a compiler bug, but by design: [...]

Thanks for sharing a concrete example of Fil-C's limitations! Disappointing - but not unexpected - to see it underperforming existing sanitizers. I was hoping for better.

But the runtime cost of Fil-C means that - in most cases - your actual production application will be compiled with a standard C compiler. This applies not just to your code, but to all dependencies (due to ABI).

So I don’t see how Rust is at a huge disadvantage here when Fil-C is typically not going to be enforcing safety in production. I suppose the testing/fuzzing story becomes all the more important because you need to exercise runtime behavior for Fil-C to detect unsafe faults.

Don’t get me wrong: I think Fil-C is a smart idea and an excellent way to introduce memory safety to existing C codebases. But I don’t get this whole (usually implied) idea that Fil-C somehow makes Rust look bad or renders it obsolete.

The whole point of Fil-C is that it is fast enough to consider using in production for some applications while still guaranteeing memory safety. We already have ASAN and Valgrind and other tools for development purposes, that's not what Fil-C is targeting.
So Fil-C is competing with Go, C#, typescript and Python. If I’m writing a greenfield project where “bare metal” performance isn’t needed, why would anyone choose Fil-C over a more mature GC language?

C is more verbose and more error prone than Go and C#. It has worse tooling. It’s missing decades of language features. C isn’t properly cross platform. There’s no package manager. The “standard library” isn’t fully standard. It’s full of sharp edges and bad decisions.

I can imagine using Fil-C to run legacy code. But for new projects, it just seems worse in every way compared to Go, C#, typescript and friends. It’s worse, slow, and inconvenient.

Of the group of languages presented, your argument has more merit for Go. With C# and others, there is an additional OOP argument in there, that splits into different factions.

But what is being overlooked, is the massive numerical dominance of C programmers and projects, along with legacy and embedded code. There is going to be a preference for writing and using C, that could arguably fuel Fil-C for a very long time.

> But what is being overlooked, is the massive numerical dominance of C programmers

I roll to doubt. I haven’t seen C topping programming language popularity charts for a long, long time.

I used to interview software engineering candidates professionally. Candidates could pick any language they wanted for the interview. Python was chosen by about 70% of our interviewees. C was under 5%. (N=400 or so)

> I haven’t seen C topping programming language popularity charts

C is still highly ranked on many charts. C (as of July 2026) is ranked #2 on the TIOBE index. PYPL has C and C++ weirdly merged, the annoying C/C++, and that comes in as #3. The IEEE and Redmonk have C firmly in the top 10, using different methodologies. We also have to consider how many years back that C's run in the top 10 goes.

We have to also use context, as popularity can be a measure beyond simply job demand, relative to usage by students, hobbyists, open-source, and legacy. Furthermore, demand can be relative to location and country. Because it is less in your specific area or company, doesn't mean that's so in other areas or countries.

Speaking for myself, I am never hired because I know C or C++, rather specific managed languages, however if there is the need to look under the runtime hood, or have bindings, like most Python libraries actually are, then suddenly it is welcome that I know C and C++ versus most folks on the team.
to be fair, most programmers are at least a little bit polyglot, and if you know python and C and you're trying to solve an interview problem, python is gonna be the easier option 99% of the time, even if you're not that great at python compared to C.
You could use raw C in environments with effective sandboxes, Fil-C in environments without a sandbox.

Or you could write a library that works for Fil-C and C without writing the library twice.

I am assuming that Fil-C introduces orders of magnitude less overhead than ASAN or Valgrind.

Also, it’s probably fast enough for apps to be deployed in something like a staging environment for integration tests to run against them. Production deploy/release can then happen using a tagged version that gets compiled using vanilla GCC/Clang.

I'm not sure about the speed of ASAN, it may be comparable but doesn't guarantee memory safety. It's only for catching mistakes and not secure against an adversary. Valgrind is dramatically slower.
I think it's not so much that Fil-C renders Rust completely useless, but rather it reduces the supposed validity and wild arguments to frivolously rewrite anything and everything in Rust.