Hacker News new | ask | show | jobs
Fil-C: Garbage In, Memory Safety Out [video] (youtube.com)
173 points by Bootvis 6 days ago
9 comments

There are getting to be quite a lot of these so I'll do it CPS style:

Memory Safe Context Switching - https://news.ycombinator.com/item?id=48727177 - June 2026 (30 comments)

Memory Safe Inline Assembly - https://news.ycombinator.com/item?id=48606096 - June 2026 (47 comments)

The Fil-C Optimized Calling Convention - https://news.ycombinator.com/item?id=48162876 - May 2026 (32 comments)

A simplified model of Fil-C - https://news.ycombinator.com/item?id=47810872 - April 2026 (136 comments)

Pizlix: Memory Safe Linux from Scratch - https://news.ycombinator.com/item?id=46260852 - Dec 2025 (30 comments)

Linux Sandboxes and Fil-C - https://news.ycombinator.com/item?id=46259064 - Dec 2025 (156 comments)

Ported freetype, fontconfig, harfbuzz, and graphite to Fil-C - https://news.ycombinator.com/item?id=46090009 - Nov 2025 (56 comments)

A Note on Fil-C - https://news.ycombinator.com/item?id=45842494 - Nov 2025 (210 comments)

Fil-C: A memory-safe C implementation - https://news.ycombinator.com/item?id=45842242 - Nov 2025 (1 comment)

Notes by djb on using Fil-C - https://news.ycombinator.com/item?id=45788040 - Nov 2025 (246 comments)

for more, goto https://news.ycombinator.com/item?id=45792588

He claims that all syscalls are safe because they're implemented by his custom libc, but that libc then calls out to the system libc, where the system calls are unsafe. He then claims that this is unlike rust, where making a syscall is unsafe. If you stick to the rust standard library in the same way that fil-c programs stick to the fil-c standard library, then all of your rust "system calls" are safe, too.

Someone in the audience also pointed out that a tool like this could be used to compile rust programs, not just C programs, in which case it's odd to hear Fil-C repeatedly framed as a language in opposition to rust rather than as a tool which might complement it.

Rust doesn't runtime validate that your usage of syscalls is memory safe, while Fil-C does. For example you can call mmap in Fil-C and it is still guaranteed to be memory safe, while in Rust you can easily violate memory safety by calling mmap. This seems like an unambiguous improvement to me. This is as memory safe as it is possible to be on a system with a kernel that is not memory safe.

Adding Fil-C-like runtime checks to Rust is definitely an interesting direction.

> For example you can call mmap in Fil-C and it is still guaranteed to be memory safe, while in Rust you can easily violate memory safety by calling mmap.

That's the thing, though. Your Fil-C code isn't calling mmap, it's calling the Fil-C wrapper for mmap. In neither Fil-C nor Rust('s safe subset) can you call the actual system mmap.

Fil-C has access to a memory safe API called mmap with a lot of the capabilities of the mmap system call, while Rust's safe subset does not. Rust allows you to use the mmap system call unsafely, while Fil-C does not. I feel these are both big advantages for Fil-C. You'll never have to audit a Fil-C codebase to determine whether its calls to mmap are memory safe, or indeed any other calls to any API or dependency, even those written in C.
How is Fil-C’s wrapper approach different from someone (not necessarily the Rust stdlib) implementing a safe wrapper around a particular syscall?

mmap is a bit of an outlier because it is not possible to implement a fully featured safe wrapper (MAP_SHARED) in Rust. So I would be curious to see what safety guarantees Fil-C claims to provide for mmap.

> from someone (not necessarily the Rust stdlib) implementing a safe wrapper around a particular syscall?

You might call that library "nix"[1]. Many, though not all, of the bindings are safe wrappers around the underlying unsafe syscall.

(The specific call of mmap from upthread, though, that one is not. I'm not sure how you would make such a call safe.)

[1]: https://docs.rs/nix/latest/nix/index.html

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.
Adding Fil-C-like runtime checks to Rust is definitely an interesting direction. As I mentioned upthread. It's not just the availability of the safe API that's interesting, though, but also the prohibition on using the unsafe API in the entire program and all dependencies. Which Rust could also do in theory but not yet in practice AFAIK.
mmap is a great example of Fil-C providing a unique level of safety.

You can’t use mmap in a way that corrupts memory in Fil-C

Try it. :-)

Okay, let me know when I can call process_vm_writev or ptrace and have Fil-C verify safety properties on the result.
Don't forget reads and writes of /proc/self/mem! :-)
Better include Rowhammer too. Maybe Fil-C should run a test and refuse to start on any system with bad RAM or unpatched CPU errata. It could also monitor the voltage to protect against undervolting attacks. And you'll need some cosmic ray shielding too.

Of course I'm kidding, but it is absolutely the case that if you truly care about safety you need to consider more than the program source code and binary, but also the environment, including kernel and hardware. The user doesn't care if their web browser got hacked via stack buffer underflow or /dev/exynos-mem or Rowhammer; the result is the same.

Sure all of those are escape hatches that work against any memory safety tech.

Point is, Fil-C goes further than any other memory safety tech in terms of what it guards

It doesn't work for a significant set of syscalls and is very very unlikely to ever work because of how the syscalls themselves work unless ofc you are willing to emulate them somehow which is a insane amount of additional compute cost.
Custom libc does not call to system libc.

“Custom” and “system” aren’t the terms I use; I say user libc and you libc (because they are basically the same libc - either both are musl or both are glibc).

User libc calls to the Fil-C runtime, which filters syscalls, and those filtered syscalls are made via yolo libc.

Hence, a Fil-C program is memory safe down to the syscalls and syscalls cannot be used to escape the protections (unless you do weird stuff with /proc)

The way I see it, as far as memory safety is concerned that's just framing. Both Fil-C and Rust have a boundary below which the unsafe lives. If Fil-C is only safer than rust when you don't pass the `-F unsafe_code` argument to rustc then IMO "safer" in this case is somewhat of an empty claim.
I think you should watch the linked presentation, it will show how it is "safer" than rust. Unfortunately there are performance implications, but fil-c seems fast enough to go into production for many workloads and surprisingly needs very little code changes to existing C/C++ projects which is a huge benefit.
I think Fil-C might make a lot of sense for running legacy C or C++ codebases. But for new code, it seems like it’s trying to compete with other GC languages. Take away C’s performance advantages and I don’t know why anyone would use it.

Fil-C: Combining the ergonomics of C with the performance of Python!

I like using C. It is simple, elegant, has very fast compilation times, requires no FFI needed for many libraries, is extremely stable and extremely portable, a large ecosystem, and, most importantly, I do not think the ergonomics of C are bad.

It is inconvenient to start using it as it comes with basically nothing out of the box, but this is irrelevant after a short time using it.

Fil-C is much faster than Python

And it’s fun to write new code in.

> Someone in the audience also pointed out that a tool like this could be used to compile rust programs, not just C programs, in which case it's odd to hear Fil-C repeatedly framed as a language in opposition to rust rather than as a tool which might complement it.

You can combine both approaches for sure, but that doesn't change that they are indeed separate approaches. One (Rust) intends to characterize and prevent undefined behavior at compile time, and another (Fil-C) intends to make undefined behavior impossible at runtime, as evidenced by decisions like (for example) making unsafe usage of setjmp/longjmp safe.

You could sort of achieve "safety-in-depth" by combining both approaches, but Rust prefers to prevent all undefined behavior statically, and Fil-C prefers to focus on dynamic approaches. They have real differences, so that's probably what comes off as "oppositional"

This presentation wasn’t too bad in terms of us vs theming, but in general throughout the lifetime of the project there’s been a strong us vs them rhetoric. I think it’s working as a marketing tactic to some extent but there are better, albeit harder ways to market the thing.
Rust generally invites us vs them everywhere because it's just so ambitious and attractive (to some). Fil-C probably receives questions all the time about why they don't just do X or Y that Rust does. Maybe they end up supporting their position against that type of pressure and it looks like they're opposing Rust when all they're doing is justifying themselves.
Because by making Cyclone's ideas mainstream, which AT&T started alongside Cornell University, the C and C++ devs that so far felt safe from all those RC/GC languages, now had an actually problem as companies started paying attention and embracing the language's ideas, even extending the type system of existing RC/GC languages.

Thus anyone that identifies themselves with the programming language they work with, gets dragged into a us vs them discussion.

Arguably the most important memory safety property, i.e. bounds checking for dynamic arrays, is also not statically checked in Rust.
It's possible to do this (WUFFS does it) but it's so invasive that, well, you basically end up with WUFFS. You end up having to track every set of possible and impossible values at every location, etc. (during each program location too.) WUFFS certainly has its place and I've kind of been itching to try it out myself, but I think getting to the point where dynamic arrays can be statically bounds-checked would have highly disabled Rust.
How would Rust perform static checks on dynamic bounds? That seems like an impossible order, i.e. not a reasonable evaluation criteria for any (general-purpose) language.

(I'm separately skeptical that it's the most important memory safety property; I suspect that a review of Chrome and Firefox 0days would show that UAFs and type confusion are, at least to attackers, equally if not more important.)

Presumably, they're talking about the possibility of explicitly replacing dynamic bounds checks in cases where it's statically provable that the access will not overrun. That doesn't necessarily mean you lose cases where you genuinely can't prove such a thing, but rather that it would be possible to opt into compiler assistance with proving it, rather than hoping LLVM will have your back. At least, that's how I'd envision such a thing for Rust. This would be similar to how you can already choose whether to invite more of the borrow checker by using references directly, or to do the checks at runtime with Rc/RefCell, etc.
Yeah, that seems like a nice thing that Rust could offer. It strikes me as a weird thing to get hung up on, though, given that the norm in compiled languages - including C - is to express your bounds such that an optimizing compiler can (but won't necessarily) eliminate them.

(You mentioned WUFFS below, which is why I qualified with general-purpose! One thing that WUFFS does that I think Rust could add pretty easily is provable indexing, e.g. allow me to use a `u8` to index a `[u8; 256]` without having to widen to a `usize` first and hope that LLVM optimizes it back out.)

> rather than hoping LLVM will have your back

My thought here is to proactively verify that LLVM elided the automatic bounds checks in places where you believe that your explicit checks should be sufficient.

That was a key part of my article on "No-Panic Rust": https://blog.reverberate.org/2025/02/03/no-panic-rust.html ("A Dance With The Optimizer")

I merely pointed out that the statement "Rust prefers to prevent all undefined behavior statically" is misleading in the sense that Rust does not do this for all undefined behavior.
ATS could probably do some of this by constructing proofs about the bounds and indices - not in the completely general case of course, but for at least some fraction of what a language without dependent types would have to defer to runtime
those are not dynamic bounds.
Rust can not do this. But the original claim is that it is all statically checked in Rust, and this is an obvious counter example. Some dependently types languages can prove this statically, also model checking can do this, etc. So it can be done statically as well, but not in Rust.
> But the original claim is that it is all statically checked in Rust

Where? The GP's comment says "prefers," which I didn't read to mean a blanket statement. I don't think anybody with more than passing experience in Rust (or C) would make such a claim.

> Some dependently types languages can prove this statically, also model checking can do this, etc. So it can be done statically as well, but not in Rust.

You're couching the part where it can't be done with full generality or can be done with full generality, but with punishing semantics. The appropriate comparison here is with other normal general purpose compiled languages.

This isn't entirely true. Rust's indexing operator performs a dynamic check but the language and stdlib have a number of ways to access array elements without indexing, which is effectively a form of static checking. For example, the following loop is statically guaranteed to not go OOB, and will not emit any unnecessary bounds checks:

  for i in some_arr {
    println!("{i}");
  }
I suspect most techniques you could think of to statically avoid bounds checks are possible in rust's type system.
These are not terribly interesting cases though, as it would also be impossible to get an oob access in other languages either.
Yes, rust didn't invent the concept of an iterator, and is thus not the only language which offers a solution to statically avoid bounds checks. Feel free to give a more "interesting" case you believe rust wouldn't be able to handle.
But that's also arguably pretty boring because it's very easy to dynamically check and the cost for doing so is relatively small compared to what needs to be done for other properties.

On the other hand statically checking bounds for (dynamic and non) arrays is very very hard in the general case.

The combination of static safety gracefully degrading to runtime safety where not provable is interesting to me
This is sort of already possible in Rust when you use safe primitives (e.g., RefCell), but it doesn't cover unsafe code invoking Undefined Behavior. Placing something like Fil-C around unsafe code could prove to be interesting, especially since current approaches rely on interpretation (Miri, Soteria Rust) rather than translation.
In Rust, there are safe syscall wrappers, and then there's the unsafe general `syscall` function: https://docs.rs/libc/latest/libc/fn.syscall.html.

If I'm understanding correctly, it's this general syscall function that's safe in Fil-C.

indeed, the ideas could be used more widely.

fil-c runs on linux.

what if linux ran on fil-c?

Do you want your kernel to be 2x slower and use 4x as much memory?
A computer spends the vast majority of its time and memory in userspace, so this tradeoff isn't as bad as it sounds.
The benefit also isn’t as big as you might expect. Most of Linux’s recently found security vulnerabilities were due to ToC/ToU bugs. Fil-C would not magically fix these problems.

It would sometimes be a good trade off, for some users. But I don’t think many regular users would choose to pay this cost.

a fun exercise is to ask an LLM how it might be applied.
You can run your Fil–C userland on provably–secure seL4.

(Left as an exercise for the reader)

If you’re using SeL4, userland processes are already strictly sandboxed. There’s still some benefit to Fil-C, since the added memory safety would make it much more difficult to take over a process. But the blast radius of a compromised program in SeL4 is much smaller because of the capability model.
I was under the impression that fil-c's memory management (gc?) wouldn't work on a kernel? Be sweet if you could, ofc
This is a myth that seems to never die. OS kernels can and have been written in GC languages. Watch the video maybe? The whole presentation was running on a distro fully compiled with FillC.
The video has a slide which says,

> I'm running on an OS where the entire userland is compiled with Fil-C/C++

(emphasis mine)

Looking up https://fil-c.org/pizlix , that says,

> The kernel is compiled with Yolo-C. So that you can compile the kernel, a copy of GCC is installed in /yolo/bin/gcc.

Where do you see anything saying the Linux (the kernel) can be built with Fil-C?

Ok, I stand corrected: only the kernel userland was compiled with Fil-C.

However, I don't see why the full Linux kernel could not be compiled with Fil-C. It would be nice if Fil himself could explain what limitations there are, but the documentation does not list missing C/C++ features as far as I know, it only says it's "fanatically compatible" which I take to mean mostly everything should work?!

But to my point in general, here's a osdev.org wiki explaining how high level languages can and have been used for OS development (with the caveat that some Assembly code is required, which I believe is also true of kernels written in C): https://wiki.osdev.org/Languages

what if fil-c could draw pelicans?
also: why not use fil-c to improve cython, and the ffi.
the only reason to use cython (in my experience) is to write quick numpy extensions without a tonne of extra baggage from having a complete compiled extension in C/C++/Rust. Often, you explicitly want to avoid the compiler offering you any kinds of additional checking because you want to get maximum throughput. Most of the functions I’ve written in cython explicitly opt out of bounds checking etc since the memory access is sequential and bounded by construction and very obvious when you mess things up by writing simple unit tests. Given that, it doesn’t seem useful to me to add any kind of memory safety as additional overhead. YMMV I mostly do scientific computing and signal processing.
If you want a slow, garbage collected language in the Python ecosystem, why not just write Python?
you would. python and ffi would have runtime sanity checks a la fil-c. better error messages too. ask your favorite LLM how it would look.
Both Rust and Fil-C have unsafe blocks, but in Fil-C latter system, only Pizlo gets to write them. Why am I not filled with confidence?
Fil-C has no unsafe blocks
Is the runtime compiled by the Fil-C compiler, or is it a single huge unsafe block? I honestly don't know the answer.
But it still defers compile-time errors to run-time. Not safe enough for me. I rarely have 100% coverage
I was amazed by the presentation all the way up until 33:47, where the buggy program compiles and only errors out when the invalid access is executed. So apparently Fil-C enforces memory safety dynamically at run-time, rather than detecting these bugs at compile-time.

A new language designed around memory safety, such as Rust, can reject large and important classes of memory-safety bugs at compile-time. Rust does not catch everything at compile-time, like bounds checks and RefCell, which are checked at run-time(, and the problems due to unsafe and C interop like explained in the presentation.)

Still, IMO the comparison becomes a bit apples vs pears when bragging about how much more memory-safe Fil-C is than Rust. It would have been helpful to explain this important difference about run-time vs compile-time.

Very cool and useful anyway.

I thought it was very obvious throughout the video what was happening...

Rust has compile time checks to enforce some safety. In comparison Fil-C is a lot more memory safe, it's more comparable to being a software implementation of CHERI.

Unfortunately it comes with downsides: runtime performance, runtime enforcement, granular safety (the safety is around allocations).

It also comes with huge upsides: you can run C/C++ with little to no code changes. Imagine compiling nginx and the associated system libraries with Fil-C, the performance hit is probably acceptable and now the web server is memory safe.

Rust probably provides enough memory safety (even if it is not complete safety) in most circumstances though.

I'm not a native English speaker, I know "memory safe" has a precise technical meaning, but the word "safe" still feels a bit strange to me given that a memory-safety bug can make the program crash at run-time.

Sure, Fil-C prevents the bug from possibly being exploited, which is a huge improvement. But crashing can be a DoS attack, and if running a mission-critical system, it might not be an acceptable outcome.

I just feel the already very good presentation could have been made much better if it had put more weight on explaining these trade-offs.

Even in memory safe Rust, out-of-bounds array access also results in crashes.

The whole point of memory safety is that bugs can not be exploited. A memory safe program does not mean a crash safe program.

The main advantage of Rust is that you can rewrite GPL software and replace the license with MIT.
The author's whole schtick is purposefully rage-baiting Rust devs, so really not that shocking that he downplays the compile-time trade-off
Ha, looking through the links dang added, I came upon something I wrote back in December

I gave (somewhat arbitrarily) the example that safe Rust is OK with a 64-bit pointer (on a modern PC for example) having the value made by the UTF-8 text "LAUGHING". That's 8 bytes, 8 bytes is 64 bits, it fits perfectly. Of course I point out, unsafe Rust, which is allowed to dereference pointers, must never dereference this LAUGHING pointer, it's not actually pointing at anything, but it is allowed to exist in safe Rust.

Coincidentally, in like February or so this year, a new third-party Rust type "ColdString" was introduced to their reddit by somebody I've never met - I read about it and encouraged its author. ColdString is 64 bits (on modern hardware) because inside it's a pointer, and indeed if the text you wanted to store in a ColdString was "LAUGHING" you do that exactly as I described in the December post - it's just the UTF-8 encoded text, no problem. The clever trick inside ColdString is how it can know when that 64-bit pointer really is actually a pointer for longer strings - yet also allows any 0 to 8 byte UTF-8 text string to just be encoded in the ColdString itself directly.

How does it do that? When the 64-bit pointer is actually a pointer, does it mangle it into something that is certainly not UTF-8 (e.g. changing its top byte to 0xC0, and assuming that bits 56-63 are the same as bits 48-55, or something like that)?
UTF-8 is a self-synchronizing encoding, so each UTF-8 byte tells you whether there were any previous bytes you'd need in order to understand it. Since we're storing a whole string our first byte logically cannot be such a "continuation byte", if it seems to be, we can say these eight bytes aren't UTF-8 encoded text but instead a pointer. The UTF-8 "continuation" marker is that the top bit is set and the next bit is not. So, we need to smash two bits of our pointer.

Now, by pointing only at memory aligned to 4 bytes, the way a 32-bit integer would be on a typical machine, the bottom two bits of the pointer are always zero. So, we ask for such 4-byte aligned pointers when allocating memory to point at, most allocators actually never give out smaller alignments anyway because they cause problems in C but we've told the allocator our requirement so even if it could it won't give out unaligned pointers.

Finally we need to re-arrange our pointer so that those two zero bits are in the right place to put a UTF-8 continuation marker. In Rust this is legal safe code, the map_addr method on a pointer is allowed to twiddle with a pointer's address bits (on typical platforms, all of them) and so long as your transform is reversible (which this one is) it will work correctly when you twiddle the pointer back and dereference that pointer in unsafe Rust.

Ah, so it is basically a single rotr(x|2, 2), nice
I like the inline asm sanitizer; probably could be extracted out of Fil-C.
I was just thinking that we were overdue for a Fil-C post on HN.
Every one of these posts is the same. There's this weird blindness to the problems and imperfections in Fil-C --- just shouting down. It reduces my confidence in Fil-C as a whole.

Rust, for all its faults, at least engages with its critics. I've long faulted Rust's use of Result over exceptions, for example, but the maintainers at least acknowledge that other options exist and each has trade-offs. Not Pizlo and his fans.

To be clear, I like Fil-C. It's a practical implementation of something that should have existed a long time ago. And Pizlo is, in fact, a great programmer. It just rubs me the wrong way that he can't be content with having done excellent work --- he has to claim things that his system doesn't provide (like memory safety under data races --- minor fault, but still) and claim that other systems are worse in ways they are not (e.g. with respect to Rust having unsafe blocks).

Is genuine excellence not enough? Why must he persist in claiming a false perfection?

> claim that other systems are worse in ways they are not (e.g. with respect to Rust having unsafe blocks)

If considering only "safety", then Fil-C is more safe than any Rust containing unsafe blocks, no? With the usual caveats about whether an abort() is safe.

Machine code is unsafe, so any memory-safe language must necessarily be built on some unsafe code somewhere. Safety is always conditional on the underlying unsafe implementation having no bugs.

With Fil-C, the "unsafe blocks" live entirely within the compiler and runtime. With Rust, the unsafe foundation is the Rust compiler and standard library, as well as any unsafe code within your application or dependencies.

So either way you're in the same situation of relying on the correctness of the unsafe code you depend on. But there are two major differences:

- Unsafe code can be written in Rust, instead of inside the compiler. This is much easier to write and to review for correctness.

- People other than Fil are allowed to write unsafe Rust. This is what Fil's point is about, and yes, it allows you to opt-in to increasing your attack surface by trusting unsafe code written by yourself or your dependents. Rust allows the user to choose where they draw the trust boundary, and Fil-C does not.

It's true that Fil is probably better than I am at writing unsafe code. So "Fil-C is safer than Rust" is true in that sense. But Fil-C is certainly not safer than safe Rust. And sure, you can't run all the Rust code in the world if you compile with '--deny unsafe_code'; but Fil-C can't run all the C code in the world either. Unsafe Rust is rarely needed, mostly only if you want to do pointer crimes or FFI, and Fil-C doesn't support a lot of (perfectly legal) pointer crimes and FFI either.

Machine code could be made safe actually, however most research topics regarding strong typed Assembly, or verified Assembly, failed to gain mindshare among commercial vendors.

One such example,

https://www.microsoft.com/en-us/research/publication/safe-to...

Reasonable people can disagree with you on the point that Rust is more safe because you can write unsafe code in Rust, whereas in Fil-C you write unsafe code in the compiler.

Why might I write unsafe Rust? To do something not particularly fancy. A use case covered by normal safe Fil-C. Why might I write unsafe Fil-C (compiler) code? To improve compiler or runtime performance or add new platforms, etc. Analogous to wanting to work on Rust's IR or borrow checker.

Very different use-cases.

There are no 'unsafe' blocks in Fil-C. I think you trying to conflate 'unsafe blocks' with the fact that there might be compiler errors which might break 'safety'? Which is equally true in any system including Rust.
Exactly, my point is that the compiler and runtime are the "unsafe" portions of Fil-C, and that Fil-C and (safe) Rust are equivalent in this regard.
Any safe system has unsafe parts. Quibbling about whether these parts are called "blocks" isn't useful. The term changes nothing.
He's been especially arrogant and dismissive on X. I'm very glad Fil-C exists, but his behavior makes me doubt the whole project.
To be concrete and hopefully more constructive with my criticism, he's prone to saying things like "Fil-C is safer than Rust":

https://x.com/filpizlo/status/2053351119095791995

And "Rust let’s you corrupt memory / Fil-C doesn’t.":

https://x.com/filpizlo/status/2079253367587737841

These are false claims. The following compiles and runs fine with Fil-C, happily corrupting memory in a way that a safer language like Rust would not allow:

    #include <stdint.h>
    #include <stdio.h>
    
    struct Account {
            unsigned char name[8];
            uint32_t privileged;
    };
    
    void write_name(struct Account *account, size_t index, char value)
    {
            account->name[index] = value;
    }
    
    int main(int argc, char* argv[])
    {
            struct Account acct = {
                    .name = "foobar",
                    .privileged = 42,
            };
    
            write_name(&acct, 8, 1);
    
            printf("privileged = %d\n", acct.privileged);
            return 0;
    }
His claims about Fil-C being safer than Rust seem to hinge on Fil-C's ability to make safe-er an entire application stack, compared to a hypothetical Rust application that links to C dependencies which (currently) can't be compiled with Fil-C. This is true as far as it goes, but it's a far cry from justifying a blanket statement like "Fil-C is safer than Rust".
Mark? AwareDigital 2013?
Hey drop me an email
If you think you like Fil-C but aren’t able to see the specific way in which it’s better than Rust (more comprehensive safety), then what is it that you’re liking?
Not the parent, but: I strongly dislike this framing of "Fil-C is better than Rust" or "Rust is better than Fil-C". This is apples-to-oranges; users will almost never be comparison-shopping between the two because they address almost entirely different problems.

There are roughly two categories of Rust user:

1. People who are using Rust for application development. Most of these users write zero unsafe blocks in their careers. For these users, "memory safety" was probably not a strong reason to pick Rust, because there are a wealth of other memory-safe application development languages out there.

2. People who are using Rust for systems programming (i.e. programming under resource or environment constraints). These users may write unsafe for performance reasons, or to do things like hardware MMIO; and they're using Rust over C/C++ either for security or just because the tooling is nicer.

The first category of user is unlikely to consider C for application development in this decade; they're going to be comparing Rust against Go or Java or Node.js. Fil-C solves the security problem of memory safety, but it does not free the developer from the difficulty of having to manually write memory-safe C code; their program will just crash if they get it wrong.

The second category of user cannot use Fil-C because of its performance overhead, runtime requirements and/or lack of escape hatches for MMIO/FFI.

Where Fil-C does shine is for legacy application software written in C. Here, it's a free lunch: a way to harden the massive amount of existing software without an expensive rewrite. I would love to see distros shipping pizlonated coreutils, ffmpeg, systemd, curl, sudo, postgres, etc., anything that has a big attack surface, but does not need to be memory-unsafe.

This is a problem I care about a lot, and your work here is truly a monumental advancement in the field. Comparisons to Rust sell it short by inviting endless debate on problems largely tangential to Fil-C.

I’ve never said that Fil-C is better than Rust full stop.

I have articulated the specific ways that Fil-C is better.

And I’ve articulated the specific ways that Rust is better. You’ve enumerated some of those reasons from your perspective, though I disagree on the details.

I like those kinds of conversations. We shouldn’t shy away from them as a community. They help us grow a shared understanding of the tech

Let's not shy away then. What details do you disagree on?

P.S. Also fan of your work. Competition is always good.

I'm able to see how it's safer than Rust but what I like is that it works with existing C++ code; I don't think the extra safety relative to Rust is worth the performance penalty (not to mention needing to recompile every dependency) and I doubt you think that, either
It provides a way to improve the safety of existing code without rewriting it. It would be nice if it could solve the memory safety issues around data races too.
>I've long faulted Rust's use of Result over exceptions

Why?

Not the person you're asking, but result types pessimize code more, add register pressure, use more icache for largely dead code, etc. They're arguably noisier at the source level too.

That said, I've spent too much of my life chasing implicit control flow to accept exceptions. Heck, C++'s "noexcept" is a strong argument against exceptions all by itself.

> That said, I've spent too much of my life chasing implicit control flow to accept exceptions.

Yes. This is why unchecked exceptions are annoying. Checked exceptions are a „failed experiment“ anyway.

A result type (or even Go‘s err) with forced error handling meaningfully increases the robustness of a program in my experience.

My view is that Java's checked exceptions failed in big part because Java didn't have type variables back then; after all, polymorphic Result types are not that much different from checked exceptions.

I haven't written any Java since it has gained those, so I suspect there might be other aspects making it awkward. And it still would lack exhaustiveness checking that e.g. Rust has.

Checked exceptions were actually the "right way" to do exceptions (if there is such a thing), the problem was just that developers hated them, but I think that draws the wrong conclusion. That tells me their syntax/usage was seen as too much forced boiler plate making code unwieldy, not that they didn't have benefits for correctness (something often not appreciated until years later).

Unchecked exceptions lead to unhandled exceptions at runtime. We've all seen screens with Java programs running with tons of exceptions in the log, or worse, that crash with unhandled exceptions. This is the result of the unchecked exceptions mess, which is why I won't use languages that use them for routine error handling for anything more than trivial programs.

    > result types pessimize code more
What does it mean?

    > They're arguably noisier at the source level too.
But they are more explicit, which means there will be fewer bugs in your code.
C++ noexcept exists because the way C++ evolved, it is no argument against exceptions.

Exceptions came to be during the 1990's, as the C++ARM to C++98 standardisation process was taking place.

Naturally during the early days C++ compilers lacked exceptions, as CFront was introduced without them.

Then we had the C folks that were migrating to C++.

When C++ compilers finally supported exception, compilers vendors introduced the non standard switch to disable them, so that existing code could still compile with the expected behaviour.

The standard itself does not acknowledge this as allowed.

This feature was naturally misused by the anti-exception folks, same applies to how RTTI came to be.

So noexcept is a way to be able to write code to appease both camps, while surfacing what variant was chosen by the programmer.

From my point of view allowing disabling exceptions in first place was a mistake, those folks should have moved back to C, or fixed their code.

I don't understand why Result type is necessarily slower. Result that simply bubbles up is basically an exception, no?
You need instructions to check the result type, and a bit somewhere to store whether it's valid. Most exceptions only add extra instructions during throws/unwinding. There may or may not be an overall reduction in code size, depending on how many checks you have vs table entries.
The worst part about rust not having exceptions is that it actually does have exceptions, you just shouldn't use them. All the downsides and none of the benefits:

https://smallcultfollowing.com/babysteps/blog/2024/05/02/unw...

Just like on Go's case, panic/recover are exceptions with bad ergonomics.
This is a vacuous statement on par with characterizing setjmp/longjmp in C as "exceptions with bad ergonomics".
No, Rust does not have exceptions. Rust has unwinding, if you choose to compile your program with support for it, which you are free not to, and is trivially achieved by a single flag.
It's hard for me to think of a definition of "exception" which doesn't include Rust's panics:

  use std::panic::catch_unwind;
  fn throws_exception(){
      panic!("hello");
  }
  fn main(){
      match catch_unwind(|| {
          throws_exception();
          println!("Never reached");
      }) {
          Ok(_) => (),
          Err(e) => println!(
              "threw an exception: {:?}",
              e.downcast_ref::<&'static str>().unwrap())
      }
  }
I can disable exceptions in rustc, but I can't disable the influence they have on language and library design (as detailed in the link I posted). Exceptions are the main reason you can't temporarily move something out from behind an exclusive reference, or return an error code from a Drop impl. Heck, Rust wouldn't even need destructors if it weren't for exceptions: the compiler could just tell you when you forgot to free something.
He claims the system provides memory safety under data races. Does it not?
Question for the author from someone with no expertise in the field: how does Fil-C different from https://security.apple.com/blog/memory-integrity-enforcement...? I'm guessing the hardware of the latter is something that Fil-C doesn't necessarily rely on.
Who is the author of this project? Is it a single person? A small team? A single person with LLMs?
Filip Pizło (https://www.filpizlo.com/), according to his website: Director of Programmability and Data Model at Roblox. Previously, I worked at Epic Games (Senior Director of Language Engineering) and Apple (Manager of the JavaScriptCore Team).

He seems to be the main developer of Fil-C: https://github.com/pizlonator/fil-c although there are other contributors.

Filip mentioned in the talk that Fil-C is his personal project.
I am asking, because I doubt a single person can achieve this. It requires at least a team of several people.
Yet another prove of the idea that worse is better.

First people use unsafe poorly-designed languages for writing critical software (already worse). Then someone invents a hack making code 4x slower and consuming 2x more memory to "fix" safety issues (much worse).