In a language like C (or Zig), you need to manually manage memory. This makes programming a lot more complex, and it's really easy to accidentally mess up. Especially in large projects which have a lot of separate modules.
The biggest advantage of using a garbage collector is that you don't have to think about freeing memory. The GC automatically frees objects when they're no longer referenced. This makes programming much much easier. The downside of using a garbage collector is that it hurts performance at runtime. GC languages are slower and use more RAM.
Fil-C is the worst of all worlds here. Like C, it forces you to manually manage your own memory. But you still pay the performance cost of having a runtime garbage collector. And that cost is (apparently) really high. The only performance numbers I've seen showed ~2x worse CPU performance and ~4x worse memory performance. There's no way Fil-C can compete with C, Zig and Rust for performance.
So with Fil-C, you have a language that's much slower than C, and much more difficult to program in than C#, Java, Go or Typescript.
Fil-C still has some wonderful uses. Fil-C could be a fabulous debugging tool for C programs. It could be a wonderful teaching tool if it had nice visualisations on top of the GC's view of the world. And it could be a great way to run legacy C code.
But it's not a "rust killer". Fil-C programs run too slowly to be able to compete head to head with rust. And Fil-C doesn't offer the language benefits of a GC that you get in C#, Go, and friends. It seems like a really bad deal.
This is not necessarily true. It depends on a language, e.g. Go is slow, Nim[0] is extremely fast with conventional GC and slightly faster with ARC/ORC[1].
GC programs can be faster than manually managed ones in some cases. It's just manual memory management gives you more control of where and when free is called. And a good type system is a privelege that gives Nim more control with destructors.
Another scarecrow of safe languages is GC pauses, which is also not a thing in Nim, see table in [2].
[0] - https://nim-lang.org/
[1] - https://nim-lang.org/blog/2020/10/15/introduction-to-arc-orc...
[0] - https://programming-language-benchmarks.vercel.app/nim-vs-go
> GC programs can be faster than manually managed ones in some cases.
I've seen poorly written programs in C/C++/Rust which are slow because they allocate millions of tiny objects. Its true that generational GCs can be faster in this case. But you usually get much better performance again by using arenas and such. The reality is that I know more about the lifecycle of my data than my compiler. If you know what you're doing, you can take advantage of this information to write better programs.
If you don't want to think about memory management, then I agree - you're usually better off using a language with a GC. Personally I do a lot of my prototyping in typescript because I can iterate faster when I don't have to think about lifetimes.
Maybe some day Fil-C will run general purpose C code at native speeds, without a high memory overhead. But we're not there yet. I'm not holding my breath.
Can you expand on this?
Do you have any actual benchmarks?
What I do not like, primarily comes down to how the project is talked about and marketed. First, because it promotes an "us vs them" mindset, instead of a "we're all trying to improve memory safety" mindset, and second, because in doing so, it also overstates its case.
These things are sort of intertwined. Let's talk about the overstatement first. Fil-c has its own definition of memory safety that is slightly different than others. For example, I saw this recently:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct User {
char name[8];
int is_root;
};
int main(int argc, char*argv[]) {
struct User* user = malloc(sizeof(struct User));
strcpy(user->name, argv[1]);
if (user->is_root) {
printf("I am root!\n");
} else {
printf("I am not root :(\n");
}
return 0;
}
This, when invoked with "012345678" passed in, will print "I am root!". In my understanding, this is deliberately allowed.But beyond corners like this, fil-c's author will go on about "Rust has unsafe as a hatch, fil-c does not" while if you control-f for "zunsafe_" on https://fil-c.org/stdfil you get ... escape hatches.
The author regularly erases the difference between "traps at runtime" and "is prevented at compile time", which are legitimate tradeoffs where one or the other may be better depending on what you're doing. But they're presented as either equivalent, or one is superior, and I find this muddles the discourse. The performance issues also tie into this, "add a GC" is absolutely a valid way to handle these sorts of issues, but it is not the same thing as what Rust does. And that's okay! But presenting it as purely superior means that it's just hard to talk about.
Speaking of muddling the discourse, the author regularly trolls on X, providing tons of bad faith arguments and generally trying to rile up a "fil-c vs Rust" war that I think reduces our ability to talk about these differences in a calm, engineering focused context.
Finally, due to its design, fil-c is effectively Linux only. That's great for Linux, but many people also use other systems, and so it is not a meaningful option for them.
Anyway, after saying all that: I still think that it is a good project, and that it should exist and continue to be worked on. I just wish that the heat was turned down, and people could talk about the various approaches and their tradeoffs without turning it into a culture war.
On the muddling the discourse, I'm not on twitter and don't engage there, so I don't have an opinion on that, but I did come across https://news.ycombinator.com/item?id=49044561 recently, and I just don't see how the author can make such bold claims while examples like the one Steve provided above are still in the language. Corrupting memory in Fil-C is still easy, type confusion is still easy, intra-object overflows are still easy. Fil-C prevents a range of classes of bugs from being exploitable, but it doesn't stop the bugs from happening.
> Those languages rely on a much larger pile of YOLO C/C++ code for their runtimes and standard libraries than Fil-C does. So Fil-C is safer than those
Given the relative immaturity of Fil-C, this seems wildly wrong to me. I’m not sure how to take his claims about his runtime seriously.
Sure, this is a simple fact.
> So Fil-C is safer than those
This is not a simple fact that follows, and a good example of why you seem to be catching so much criticism for overly bold claims. One could state that a smaller runtime is easier to audit, and so the investment needed to reach similar levels of safety is lower. One might even argue that after similar levels of investment, that the probability that it's safer is higher. But jumping all the way from lower number of lines => safer is a simple fact is a huge leap.
By contrast Fil-C has a small number of rules and largely obviates the need for “native” code.
I make bold claims because they hold water.
- You can at worst corrupt only the capability you’re pointing to.
- intra object overflows are almost never useful for memory corruption exploits unless they let you corrupt a pointer, and Fil-C prevents that from being useful because you cannot corrupt the capability.
- the zunsafe api is basically unused. One library uses it (OpenSSL) for good reasons. This is in contrast to widespread use of the unsafe keyword in Rust, beyond just one library for a narrow purpose.
Thanks for reporting bugs. Worth noting that they require doing things that extant C code never does. It’s good to fix those, but the true threat model of any memory safe language is not to sandbox a malicious programmer, but to protect the program of a normal programmer against a malicious user
Wait, so there are escape hatches? But… you’ve repeatedly said, many times, that there are zero escape hatches?
And now here you’re saying not only that there only are escape hatches, but there’s a good reason to use them?
Damn. Misrepresenting `unsafe{}` whilst saying your language is better because there are no escape hatches and no need for escape hatches is like… 80% of your online personality.
When can we expect the website to be updated to remove the misleading claims?
"Fil-C has no unsafe statement and only limited FFI to unsafe code."
`zunsafe_call` is a weird thing to get hung up on as an "escape hatch", considering it's just a super limited form of FFI, intentionally designed so that it's only usable for OpenSSL's use case.
> Misrepresenting `unsafe{}`
`unsafe` lets you write Rust code that violates any reasonable definition of memory safety (including Rust's definition or my definition), and it's widely used.
Except there is an escape hatch, by your own admission above?
> `zunsafe_call` is a weird thing to get hung up on as an "escape hatch"
from the docs:
> unsigned long zunsafe_call(const char* symbol_name, ...);
> Performs an unsafe call to Yolo-land.
That’s just a `unsafe{ func(…) }` escape hatch
> intentionally designed so that it's only usable for OpenSSL's use case.
Cool motive, still an escape-hatch =)
Do you have the backbone to update the fil-c website to correct the record, and let the person you retweeted here[1] know that the escape hatch row is incorrect?
Or… is what everyone says about you here true?
I was always intrigued by the maturity about how the Rust team approached this sort of thing. IIRC years ago you and I had a back and forth on me thinking it would be helpful to have a "Why Rust is better than C++" type page.
Seeing an alternative approach from Andrew Kelley in recent weeks has really hammered home the value of the approach the Rust team took in terms of community building.
But you did the same thing when, on the spectrum that ranges from C to ATS, with Zig, Rust, and Java somewhere in the middle (though all closer to C than to ATS), you declared the exact compromise that Rust makes "table stakes"! [1]
Zig improves on C's memory safety when it comes to spatial safety, possibly the more impactful kind, so it, too, could be part of the "we're all trying to improve memory safety", yet you exclude it.
You're trying to draw some hard line that passes exactly between Rust and Zig on the C to ATS spectrum, and I'm trying to say that that line isn't there (your attempt at a definition of delineating safe and unsafe code also applies to C). Obviously, C, Zig, Rust, Java, and ATS all make very different tradeoffs, all of which may be more or less attractive to different people and in different circumstances, but there is no sharp line, at least not one that is meaningful enough to be "table stakes". Your personal inclinations place a premium on the things Rust offers and Zig doesn't while mine are the opposite, but I make no claim to universality.
I'm happy to accept that not everyone shares my aesthetics and can understand why some people prefer Rust, but those claims to or hints at universality annoy me (as they did when they were made by Haskellers, and I actually find Haskell's aesthetics quite pleasing), as they are simply unsupported. I've spent a lot of time studying formal methods and software correctness in general (https://pron.github.io) and if there's one thing we know in that field is that things are never that simple (and, bringing this back to this posts topic, even something like incremental compilation can contribute to program correctness).
(Now, you may argue that you're only talking about "memory safety" and not correctness in general, but what gives memory safety value is that violations are causes of many dangerous vulnerabilities; but once, say, Java eliminates all of them, 100% of bugs/vulnerability - which are still numerous - will be caused by other problems, all potentially avoidable with ATS, so why isn't ATS table stakes? Of course, the answer is cost, but all the languages on the spectrum differ in their costs.)
[1]: I assume that you meant Rust's compromise, because you implied that Zig doesn't pass that bar but Rust does.
I do not go around posting "omg Rust is SO MUCH BETTER than zig or fil-c, which are TRASH." I talk about engineering tradeoffs, and what matters to me personally. I do not say "if you use Zig, you are a bad person." I am not saying that any comparison is bad. I am saying that the way that the comparison is presented is bad. That is different.
> you declared the exact compromise that Rust makes "table stakes"
Table stakes for me.
> Zig improves on C's memory safety when it comes to spatial safety,
I agree that it's an improvement on C!
> yet you excluded it.
I said that it is not pursuing a design that I personally find compelling enough to use to write software. That doesn't mean that I think it's worthless. This whole thing started off with me talking about how much I respect the Zig project! Yet you're trying to turn this into something where I'm talking shit. I presented a specific technical tradeoff that is important to me. That is very different.
> You're trying to draw some hard line on a spectrum that passes exactly between Rust and Zig, and I'm trying to say that that line isn't there (your attempt at a definition of delineating safe and unsafe code also applies to C)
I don't believe you've shown that. And my "attempt" does apply to C: it fails the bar, because it does not delineate between a safe subset and an unsafe superset.
> you may argue that you're only talking about "memory safety" and not correctness in general,
I am in fact talking about "memory safety" and have been this whole time, yes.
> what gives memory safety value is that violations are causes of many dangerous vulnerabilities; but once, say, Java eliminates all of them, 100% of bugs/vulnerability - which are still numerous - will be caused by other problems, all potentially avoidable with ATS, so why isn't ATS table stakes?
This is just an entirely different question. Yes, there are other forms of safety that are important too. That's just not what we're talking about here.
> While I still don't plan to write software in it, given that I believe memory safety is table stakes
What exactly am I missing? You know you don't have to hijack Zig threads (repeatedly) with your thoughts on memory safety, right?
My point in bringing this up is to strengthen my compliment. Even though I disagree with aspects of Zig's design, the stuff talked about in this post is excellent.
Ok, so if you meant "table stakes" as an expression of a personal preference and suitability to the programs you write without making an unsupported universal claim such as "this leads to better correctness" or "the price is almost always worth it" then we're good :)
> Yes, there are other forms of safety that are important too.
The thing is that they can be at least equally important, and some affordances for memory safety could potentially _harm_ them. To me, Rust offers little safety in the programs I want to write in a low-level language, but the price it charges in language complexity and implicitness ends up in a negative balance (I can't prove it, of course; as I said, software correctness is very complicated, and some of the greatest researchers in the field were proven wrong on how to best achieve it).
Oh, who is saying things like that? Do you mean to imply that this kind of vitriol is characteristic of the Fil-C project?
>introduce an actually memory safe (unlike borrow checking) compilation mode inspired by Fil-C
I never said Fil-C is “so much better” (let alone with all caps) than anything.
I never called Rust “trash”.
I think you’re taking this all too personally
You think this is reasonable? I have also seen strange people on twitter support Fil-C while claiming that Rust is a language for [slur]s. I suppose by your "reasoning" that these people directly represent you and your project?
It is absolutely possible that one language might actually have an objectively better approach to memory safety than another, and in such cases it is usually possible to argue for this using sound technical or empirical arguments. But the way the author of Fil-C presents their arguments it often comes across in a kind of antagonistic manner, like he has a chip on his shoulder.
You may well be right. I've yet to learn about it, but I'm planning to.
As a long time PL researcher, I can, should, and will point out interesting corner cases of languages. Including in Fil-C or Rust
Here is you claiming "Facts" on a troll post claiming to "criticize" Rust: https://x.com/filpizlo/status/2081765923757903940
So your defense is a tu quoque fallacy? Note that "the same thing" is an admission.
Fil-C now has support for inline assembly, so it's not needed anymore, and I believe indeed the intention is to remove it, since Fil-C is not supposed to have any unsafe hatches.
Fil-C is not Linux only by design, that's completely false.
By the way, if you don't want a culture war, you gotta stop warring.
I find it hard to understand how could steveklabnik's comment be seen as warring.
See, this is nuance! Nuance is good! But you can't go around saying "fil-c has no escape hatches" when it has one, even if that one is planned on being removed.
> Fil-C is not Linux only by design, that's completely false.
Can you explain to me how it would work on other platforms? It currently does not, and I don't see how it can. Or at least, not without more "escape hatches."
This is one reason why Rust has unsafe: you have to interact with inherently unsafe APIs in order to do anything meaningful with the operating system. fil-c needs an equivalent of some kind, and so isn't better or worse here, it's just the reality of how these systems work.
Just to add to this, on Windows for example you're really only supposed to invoke syscalls via ntdll as the syscall table is not stable so their numbering changes over time. You cannot guarantee forward or backward compat if you do not use the library.
If you look at some of the syscalls in https://github.com/j00ru/windows-syscalls, you can see they clearly do change over time too.
I don't even work on Rust anymore, and in fact started this thread with a criticism of Rust. There are lots of good criticisms of Rust. There is a difference between "this criticism isn't good" and "every criticism is an offense."
Rust folks, this whole thing is a thread about Zig’s new feature - not even a memory safety-related feature! - and we cannot spend the whole damn time talking about Rust.
Steve, even you - I don’t believe I have ever seen you say an unkind word. But have you considered that it may be unkind to have written more than half of the words on a thread about a Zig performance feature?
This comment spawned two subthreads. One of them was focused on the differences between Rust and Zig's compilation model, which is directly relevant to the article and illuminating regarding the engineering tradeoffs.
In the other subthread, pron posted paragraphs and paragraphs arguing about what memory safety really means and whether or not Steve is right to have his opinion that Rust is "safe". This tangent had essentially nothing to do with the content of Steve's comment; it (and not Steve's initial comment) was the point where the thread was derailed from the topic of Zig's incremental compilation model. Steve responded politely in this thread to comments and questions directed at him, but did not fan the flames or take the thread further into off-topicness. If the moderators collapsed pron's comment or detached it and pinned it to the bottom of the page, this comment thread would be much better and much more respectful to the Zig project.
I think the RESF trope is just about dead now; it's given way to the Rust Detractor Strike Force showing up to turn unrelated threads into tangential arguments about why Rust is bad.
Inherently? No! I commented specifically because I was really glad to see this post. This work that Zig is doing is very good, and I wanted to call that out, in part specifically because I am on "the other side" in whatever sense that is. Why would it be unkind for kind words to be coming from me?
What I mean is a bit different though, it’s that these arguments you get drawn into end up drowning out any real discussion of Zig’s progress. I don’t think that’s your intent but it is frustrating. I should be clear, I don’t think it’s wrong for you to defend yourself from accusations etc., I just wish it didn’t look like this.
I wonder how much better HN would be if they took a page from other forum systems that said “you know what, this whole branch of stuff should be moved over here and renamed so the original topic can move on”.
Sorry, all this may be unhelpful, I don’t know where the line should be, I’m just thinking out loud about the problem.
You're accusing steve of what pron is doing... I mean look at how much text pron wrote, it is much more than steve wrote, and how pron is constantly skirting the edges of the HN guidelines.
The fact is that every thread about Zig is filled with this kind of battle, and I’m tired of it, and it doesn’t represent any community, it’s so much worse on HN than anywhere else, and it’s all just defensiveness and crap.
I think this is a case of people who can dish it out but can't take it. As far as I'm concerned if you troll someone you should expect to get trolled back.
It’s funny, I’ve heard people claim this about rust developers for years. But I’ve seen very little evidence of it. Where are all these toxic comments? Look at Klabnik’s comments in this thread. He’s lovely.
—-
A son comes home to his poverty stricken family with a spring in his step. “Mum! Dad! All that time at community college paid off! I got a job!”. Dad immediately snaps - “so what, now you have a job, you think you’re better than us?”
What happened? Dad is unconsciously projecting a belief onto his son. Something like “unemployed people are shameful”. Then dad feels judged by the projected belief and he attacks the son for it. But it wasn’t the son’s belief in the first place. He just wanted his parents to be proud.
How does the son respond? It’s a tricky one. If the son defends himself by talking up how great it is to have a job, he reinforces the projection and dad will get more angry. If he says “there’s nothing to be proud of for having a job” then he’s lying about his values. It’s a trap.
When I’m feeling uncharitable, I project this same dynamic onto rust and C/C++ devs. “Mom! Dad! I figured out a way to get memory safety without sacrificing native execution and performance!” C: “So you think your language is better than ours? Why are you so toxic about it?”
I’m not really sure how to respond to comments like yours. I think you’re mad at ghosts.
The OP is about Zig and now there are 40+ mentions of Fil-C initiated mostly by Rust folks and those comments are largely criticizing me personally.
That’s toxic AF!
But hey, nerd holy wars have existed since the internet began. I use vim btw...oh you use emacs? You're an idiot. Etc etc.
When he brought up the universality claim, he came up with a niche counter example that he kept inside his head and he makes it out to be the general rule by being extremely vague about literally everything.
Kinda rich of you to knock another language for its "marketing" when here you are once again on a Zig thread marketing Rust as a memory safe language. And speaking of "us vs them" mindsets, guess which language that reminds me of?