Darpa Project for Automated Translation From C to Rust (2024)
Posted3 months agoActive3 months ago
darpa.milTechstoryHigh profile
calmmixed
Debate
70/100
RustCMemory SafetyDarpa
Key topics
Rust
C
Memory Safety
Darpa
DARPA has funded a project to develop an automated translator from C to Rust, sparking discussion about the benefits and challenges of adopting Rust, as well as the effectiveness of automated translation.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
60m
Peak period
71
0-3h
Avg / period
13.3
Comment distribution160 data points
Loading chart...
Based on 160 loaded comments
Key moments
- 01Story posted
Oct 1, 2025 at 4:53 PM EDT
3 months ago
Step 01 - 02First comment
Oct 1, 2025 at 5:52 PM EDT
60m after posting
Step 02 - 03Peak activity
71 comments in 0-3h
Hottest window of the conversation
Step 03 - 04Latest activity
Oct 3, 2025 at 7:51 PM EDT
3 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
ID: 45443368Type: storyLast synced: 11/20/2025, 9:01:20 PM
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
To a lesser extent, I have a problem with the protections it doesn't provide and leads developers to think they're writing safe software that in specific cases, actually just promotes silent failure through invalid data, not crashing.
I'm impressed that the language is even uglier than bad C++, which is an accomplishment in violating the beauty of reading.
Edit:
No, I think complicated C++ is also distasteful, but equally, sometimes both are just simply necessary.
Annotating specific attributes of data flow is just a requirement for types of guarantees, but I wish they weren't always done inline. It incentivizes programming language authors to squeeze more out of columns, and as a result creates quirky reading that while is more featureful or does things that aren't even possible in other languages, makes for a less than aesthetic reading experience.
I think my opinions can be handwaved away here, but I just wish we as programmers found nicer ways to give these attributes to functions, variables, and parameters.
My account is throttled by Hacker News moderators. So, I can't participate any more here for the time being. Thank you for replying to my comments.
Just expressing some petty opinions, I don't mean to start a syntax flame bait war, sorry all.
Edit (for Ygg2): What you think is superficial is an entire portion of the art of software development. And your usage of FUD is incorrect. Disliking a painting, a song, or a book isn't FUD. It's just plain as day disinterest.
In my limited rust experience, I’ve found that it does a pretty good job of using the ugliness of something like an explicit lifetime to signal to the developer and reader that the code is doing something complicated and non-obvious. Like “here’s a part where the types logic required more help than what the compiler could figure out on its own; here be dragons.”
In that way the “ugliness” is really just a manifestation of “hard things possible” and the language not hiding the underlying realities from you.
I agree that most of the awkwardness of reading comes from explicit declarations, but really, even if it's more verbose, I would prefer that that explicit nature is defined elsewhere rather than reading like a compact run-on sentence. (I'm hypocritically writing here, since I do this too often myself.)
Can you back up this claim that the language is intentionally cryptic?
Ignoring that: other languages have sigils (Perl's @, $, %, etc.; PHP has always used $; Java uses @ annotations, and so on) or their own quirky syntax (C#'s custom attributes before a class, Python's @ decorators, etc.). What is it about Rust that is particularly confusing?
Java and C++ aren't just verbose, there's a lot of redundancy there, at least classically. Stuff that is needlessly repeated between headers and implementation, cases where you're having to hold the compiler's hand and continually repeat information that it should be able to infer itself from the code. And then the moment you find auto or template inference and feel like you can finally trust the compiler to do the right thing, it barfs up half a page of inscrutable errors and you're back to babying it.
Rust—in my limited exposure—is hitting kind of a sweet spot where it's the expressiveness and build/package ecosystem of Python, the performance and precision of C++, and the density of Perl. Or at least that's what's being aimed for; but obviously these goals open it up to charges that it's actually just as unreadable as Perl or as verbose as C++.
I have no experience with Rust so it makes sense i dont understand, but i also have no experience with Python or JS.
Normally these union types would be handled with a match, or an if let, eg:
The unwrap functions are basically just shortcuts for this, with the most extreme being unwrap() itself, which simply returns the Ok/Some value if present, and otherwise triggers a panic state resulting in the program exiting.But all of this is rust forcing the developer to either address the null case, or explicitly put in an "unwrap" to acknowledge that they're not addressing it. This is in contrast to C or C++ where you just myPtr->lol wherever you want, and if myPtr is null then it's a segfault.
So that's the worst of it. The rest is the function chain, which is a bit obscured by lack of indentation, and that the functions are being passed lambdas.
Also this code isn't a thing you'd actually do, it's maybe an illustration or part of an example I suppose
You see that vec![1, 2, 3] ? That's what we're getting at the end, a growable array with three integers in it. All the other stuff is machinery to handle errors which in fact have not happened.
Is the same effect, although probably for style you'd write:I mostly expose myself to it, at the moment, through benchmark work which highlights how competitive of a good language it is.
But there's seemingly nowhere else to go, but maybe small Discord servers where you can meet people and share honest opinions that are real and agree to disagree without penalty.
Everyone should feel free to express harmless opinions.
Edit: Whoever downvoted me for this comment is proving my point.
Edit (for adastra22): I'm not sure that me providing a list of specific modifications to Rust syntax is meaningful to anyone anyway. I'm just a nobody. And it should be OK for people to express personal opinions that hint towards something being wrong without also being required to solve the problem. That's just life.
I expected him to explain some core deficiencies: problems regarding the module system or multi-threading limitations, or some pathological case where latency spikes... and he said "I don't like the whitespace."
I never took him seriously again and left that company shortly after.
Converting all C++ code to Rust while actually getting a safety improvement is not possible because Rust does not safely support all of the things folks do in C++ (complex cyclic object graphs with inscrutable logic deciding lifetimes, intentional races, etc).
It’s easy to think that all of those “bad” things that C++ programmers do should somehow not have been done. It’s more likely that it’s either not possible to do it any other way or that you get a worse outcome if you do it another way. The cyclic nature of compiler IRs comes to mind. As do the wacky relationships between objects in games. Complex uses of syscall ABI are another. Oh and dynamic linking. Likely there are many other examples.
The idea that an LLM would convert C to Rust without introducing a slew of problems along the way is especially juvenile. Most likely the LLM with either use the unsafe subset of Rust, or produce Rust code that doesn’t actually match the functionality of the C code (but declare premature victory thinking that it did).
Seems most accounts are throttled 2posts per hour. Mine included.
> Edit (for Ygg2): What you think is superficial is an entire portion of the art of software development. And your usage of FUD is incorrect.
There is no art in programming language design. Art can be defined as something meant to exist solely for its own sake. That's not what PL is. It's just the thing that makes up a program.
There is a lot of creativity and application involved in programming language design. You can design works of art with a language. But on its own I would have trouble seeing it as art.
But what you mean by art is probably aesthetic i.e. how beautiful is something to look at. When it down comes to userbase it's just a popularity contest. Braces, Parens, keyword or indent? It makes very little difference.
Yet people are vocal about their pet syntax being "The one true" syntax to rule them all. It's like quarreling over whether to stir cement clockwise or counterclockwise.
I'm of the Douglas Crockford school of language design. Languages are meant to facilitate transfer of programming ideas while minimizing errors. If your syntax isn't minimizing errors I frankly don't give a damn. Give me a cement that lasts a thousand years, not one with that I need to worry which way I mix.
As for FUD, I stand by that statement. Saying Rust is uglier than C++ a language known for its near-universally disliked syntax definitely strikes me sowing fear aimed at newcommers.
1. Memory / thread safety
2. They didn't like C/C++
And often times it feels like there is more focus on problem two than problem one.
Quite a bit of idiomatic and safe (yes that does exist) C++ doesn't "translate" well to Rust without large amounts of rearchitecting. I'd focus more on converting C/C++ to languages nearing the safety of Rust but without it being such a huge shift. Like converting C++ to C#.
I think this is key. RC pointers don’t give you the ability to say: ok, I now know that this subset of the graph is dead because reasons so delete it. In RC, you’d have to walk the graph to break cycles. That’s a rather important difference from how you’d manage a cyclic data structure in C, C++, Java, C#, or any GC’d language. In C/C++, you’d delete what you know to be dead; in Java et al it would be enough to kill the references that point at the outer edges of the dead subgraph. But you wouldn’t have to walk the subgraph to detangle the cycle.
I think it really is worse than that; ie as you say, folks will just do anything but RC in that case. In Rust the safe bet would be to just shove all the nodes into an array and use indices (yuck!!!). But likely a lot of code with use raw pointers instead (also yuck). The whole thing where you reference count cyclic data structures is just too painful for sensible people
For reference: https://news.ycombinator.com/item?id=40172033
Infact Bevy might be a perfect example of my gripe(s) with Rust. Completely throwing a standard object system out the window in-favor of ECS which still hasn't caught on in even the most used game engines like Unity hurts adoption and usability.
Yes, but that doesn't have to do with whether they "like" C++ or not. What they "liked" is a programming model that could possibly be theoretically proven safe by any sort of tractable static analysis, and that inevitably means making decisions contrary to C/C++. Achieving their design goals was more important than adhering to C++'s mistakes for sentimental reasons.
It is the native language of every major operating system.
It is the language most closely tied to mainstream ISA assembly, and—symbiotically—which mainstream archs have tried to optimize for.
It's one of few languages that are completely public, in the sense that it is not de jure or de facto owned by a single market participant.
And it is the only language that both has standardized ABIs (per platform) but API and ABI compatibility implemented in a huge number of other languages.
There is no extern "Rust" {} in C++. There is no with Convention => Swift in Ada.
There is extern "C" and with Convention => C exactly because because C is the de facto standard that everything has to interface with.
C is a fine language, but there are so many glaring and obvious mistakes.
Riiiight. You do realize they made syntax similar to C/C++ on purpose to ease Mozilla's C/C++ programmers into it.
It's not that they didn't like it; it's that C/C++ is about as disinterested in memory/thread safety as you can get. It's been what, ten years since Rust became 1.0? And the safety needle of C++ hasn't budged a femtometer.
> Quite a bit of idiomatic and safe (yes that does exist) C++
Sure, so does legible Brainfuck. However, it's extremely challenging to write it. It usually takes years and years of effort, chasing down obscure bugs.
> Like converting C++ to C#.
If you can take GC pause and not wince, sure, go for it. Not everyone can take that luxury.
Barne has talked about it, but one of the primary reasons he created C++ was to address safety issues in C. And he's talked about this since the early 90s.
Like access modifiers and private by default. Something we take for granted now, but something which is impossible in C.
Or std::vector. Unlike array in C, it won't blow up if you add too much stuff to it. Again, obvious, but at the time, revolutionary.
Or exceptions! We take them for granted to!
No more forgetting to check errno! No, if you don't catch an exception your program terminates, so you have to handle errors.
Or, the biggest one of all: RAII and ownership. Might sound familiar to rust devs!
Point is, C++ is not C. That's why C++ exists. Its not safe, but it's much, much safer.
The issue Mozilla faced wasn't that it wasn't safer than C. It's that it was not safe enough for their needs. A chainsaw is safer than a saw blade; you still don't want to trim your beard with it.
And the C++ working group, to this day, hasn't even moved one inch to accommodate those needs. As another commenter noted, they added a feature for C++26 that Rust abandoned circa 2019.
They couldn't multithread the components like compositor and renderer as much as they would have liked, even with all the caveats.
I would agree with this for most use cases. My main qualm is lumping together C and C++.
It's like lumping together Rust and JS, because they're both memory safe. But Rust is WAY more safe. JS is, overall, an extremely footgunny language.
In my view, the jump from C to C++ is about the same as the jump from Rust to JS, potentially even bigger.
That's not fair. C++ 26 gets from the uninitialized primitives by default being a massive footgun to only slightly worse than using Rust's unsafe core::mem::uninitialized function - which was deprecated in 2019.
Now, sure, in a good language this mistake shouldn't even compile, so C++ moved from "Reprehensibly awful, do not use" to "Very bad". But that's more than a femtometer.
Literally just not being able to easily and efficiently express interior mutability completely changes how you design both code and APIs. Unsurprisingly, since they evolved in parallel, C++ is pretty well-suited for old-school widget toolkits like Qt, but Rust is not. It's not just a matter of having to retool things for composition... The entire view and data model just doesn't work very well. Instead with Rust you wind up seeing the vast majority of toolkits go for immediate mode or functional reactive flow designs that look like React.
I'm not Rust expert but this is basically my opinion on what's really going on. I don't think it's a hatred of C/C++, especially since I think C especially translates to Rust perfectly well ignoring the borrow checker. Rust found one way to do safety and it does reject some valid code and make some patterns awkward or necessarily inefficient... There are others but it is clearly an area of open research.
The issue is that fundamentally interior mutability is hard to reason about. It requires a lot more temporal reasoning to make sense of and ensure the safety of. Leaning into the type system Rust has does make interior mutability harder when you have "temporally based" safety arguments. It's a lot easier to reason about correctness in the model Rust uses.
Have you looked at the godot-rust bindings? They've gone very far to make the Godot object system work well going between C++ Godot code and Rust. I would love to see that model adapted to Gtk.
C# overlaps C++ in all these “performance-sensitive high-level code” domains.
Is C# perfect for every task, no. But it's probably suitable for most of the tasks that DARPA is targeting to support. The reality is that low-level languages were used in the past because generally our computers were less efficient, and the higher-level languages didn't exist. Most things today written in C++ would probably be written in a higher-level language if designed today.
Infact, I know of a specific case where a vendor is currently in hot water because a GUI tool running on a standard windows machine is not memory safe when in this case some agencies think it should be. This is probably similar to the vast majority of C++ code DARPA is concerned with.
What?
> Quite a bit of idiomatic and safe (yes that does exist) C++
Reminds me of the “yes I’m vegan, yes I eat meat, we exist” meme.
How? If you're writing modern safe-ish (still very unsafe though) C++, then you're going to be avoiding shared mutability and using lots of smart pointers which translate straightforwardly to Rust.
I will add a #3 to your list: Make an all-around nice language I think playing up rust as the memory-safe language underplays its value.
or even better: WARPATH: War Advanced Research Projects Agency for Technology and Hardware
Say what you will about this administration, I do favor the more honest name. Defense carried connotations of peace and passivity that did no more than obfuscate the underlying nature of the military industrial complex. Maybe people will be more reluctant to profit from business with the Department of War, and maybe fewer individuals will benefit from spinning "Defense" industry as anything other than trade in arms and armor intended for state sanctioned violence. Something about "Defense Industry" just carried a whole lot of "ick" in modern parlance.
The US should definitely keep doing R&D, the tech that comes out of DARPA has lots of downstream benefits beyond military applications. We should continue producing the best tech in the world, and explore all sorts of skunkworks and moonshots and crazy tinkering. I agree with "peace through strength" - be too dangerous to abuse, and if shit goes down, be the one who decides who wins and loses.
We don't need a corrupt military industrial complex, endless wars, private contractors, NGOs, nepo-grifters, and all the rabble that have abused the lack of accountability to make themselves rich, or inflict unrest on other countries, or manipulate bureaucracy for political gain, and all that jazz. Basic things like "department of war" naming fall in that direction, from my perspective. Simplify, cut, use blunt truthful language, and figure out how to hold them accountable going forward, at the very least, and at best, figure out how to claw back the trillions, or figure out where it went. You don't need to alter the underlying mission at all, really.
See, there's this notion that the US is a bad guy, and they point out all the casualties and conflicts and collateral damage and say "see, we're the baddies!" They never account for the context. Some of it is as simple as pointing out that if we hadn't killed all those german nazis, and sought pacifism and peace at any price, we'd all be speaking German. Some legitimate atrocities have occurred, as recently as Obama's unnecessary drone murders, but ranging from improper harms done to US troops, exposure to toxins, Abu Ghraib abuses of civil liberties, some of what's happened at Gitmo, etc. Each and every time we recognize a harm done, we should at the very least hold ourselves, collectively, responsible, and seek to be better. Accountability is a civic duty, regardless of political affiliation or philosophy. We should also be honest about necessary evils, not allow ourselves to be manipulated by bad faith actors, back up positions and words with actions and force, and hold ourselves to the highest possible standards. If we find ourselves continuously presented with no alternatives except between two evils, we should choose the lesser evil which allows us to preserve ourselves (otherwise, what are we even doing?)
The US body politic has allowed assumptions of good faith by our bureaucrats and military brass and politicians to fester into unimaginable corruption and vice, proving Eisenhower a prophet. We should simply be better - little things, important things, ground up discipline, principles, and a persisted social construct upon which to stably build a nation's strength is 100% necessary.
A lot of what Trump and Hegseth are doing pushes in that direction. Some aspirational, some performative, some well intentioned but wrong, but I think it's mostly in good faith, and I can get behind that.
I wish more on the left would at a bare minimum wish everyone to be responsible and to do well, for everyone to be happy, healthy, prosperous, and free. It has to be permitted to hope that whoever is in power achieves victories and success in those basic things, or we've lost the plot.
What I want folks to get out of the Fil-C thing is that the whole notion that C is a memory unsafe language and Rust (or any other language) being safer is a subtle thought error.
The truth is: C as it is currently implemented is unsafe, and implementing it in a safe way is possible but we choose not because that would make it slower and use more memory.
The argument for using Rust instead of a memory safe implementation of C is all about performance. And that’s not a bad argument! But we should be honest about it.
(It’s also annoying that this DARPA page mentions some kind of consensus. There’s no consensus on Rust being the safe bet. Lots of orgs are going with alternatives, like Swift, Zig, C++-with-changes, or other things.)
Fil-C is so compatible that I have a Linux userland compiled with it https://fil-c.org/pizlix
Think of Fil-C as Java-ifying C an C++
And more comprehensively. There’s no `unsafe` statement in Fil-C. There’s no need for it since dynamic checking is vastly more precise.
Rust uses runtime checking for array access bounds, which are the most common kind of memory safety vulnerability.
This is something recent versions of C++ do really well. It is my main reason for using C++ beyond its unparalleled performance in practice.
Totally not the same thing.
Like, notice how DARPA is in no hurry to have folks rewrite Java or JavaScript in Rust. Why? Because even JavaScript is memory safe. It’s not achieving that with dynamic checking rather than static checking.
Safe rust doesn't have UB, and validating unsafe rust isn't meaningfully different than doing it for C++, except that it's limited to tiny leaf functions with well-defined interfaces where a code reviewer can challenge you.
Fil-C largely gets rid of UB.
There are exceptions left but they’re all fixable.
The only reasons why C has UB are:
- lack of memory safety (Fil-C fixes this)
- policy (Fil-C mostly fixes this but there are still a small number of remaining issues, which I intend to fix).
Fil-C is super comprehensive in how it fixes C. I bet it’s more comprehensive than you’d expect.
The reason not to use Fil-C in safety critical systems is that some operations have varying cost and there’s a GC. The GC is concurrent so you might be able to make it suitable for safety critical hard realtime stuff; it would just be a lot of work and probably not worth it. Rust is better than Fil-C for hard real time stuff for that reason.
Most of annex-J is unrelated to memory safety. No, C has explicit UB because there wasn't a defined behavior that made sense to codify in the standards process. Signed overflow, invalid printf specifiers, and order of evaluation for example. I assume Fil-C doesn't fix things like uninitialized memory or division by zero either.
Wasn't really getting into the GC because that's "just" an engineering issue, rather than a structural issue with the approach.
It'd be great to not only terminate on detecting these issues as Fil-C does, but prevent them from happening entirely.
It’s on my list to solve division. It’s easy to do and also not super important for the security angle that I’m addressing. But with doing precisely to provide clarity to these kinds of discussions.
I’ve mostly tackled signed overflow. I’ve fixed all the cases where signed overflow would let you bypass Fil-C’s own bounds checks. It’s not hard to fix the remaining cases.
In short: any remaining UB in Fil-C is just a bug to be fixed rather than a policy decision.
The reason why C has UB today is policy and memory safety.
Its a goal of Fil-C to address memory safety violations by panicking because:
- That’s the most secure outcome.
- That’s the most frantically compatible with existing C/C++ code, allowing me to do things like Pizlix (memory safety Linux userland)
In a good language this mistake is caught at compile time, like in Rust, the compiler says "Hey, I don't see how this variable is initialized before use" and you slap your forehead and fix it. But zeroing everything is technically safe.
For the Casey "hand made" Muratori type zeroing might even seem like a better idea. It's cheap, it means now your code compiles and executes, who cares about correctness?
I think what you’re doing with Fil-C is cool and interesting. But I think you’re talking past a large part of the “memory safety” audience with this framing: most people don’t want “memory safety” qua uncontrolled program termination, they want memory safety qua language semantics that foreclose on (many, if not all) things that would be memory-unsafe.
Or in other words: it’s great to be able to effectively be able to forklift C onto a managed runtime, but most people really want to be able to write code that doesn’t crash at all because of expressive limits in C’s semantics. “Memory safety” is a convenient term of art for this.
Rust’s most important safety mechanism is panicking on out of bounds access. OOBA’s are the thing that attackers most want to do, and Rust, Fil-C, and almost all of the other memory safe languages solve that with runtime checking.
In short, I’d say what Rust gives you is static checking of a bunch of stuff and also memory safety. Fil-C gives you memory safety (and Fil-C’s memory safety goes further than Rust’s).
On browsers and other high-performance codebases? I would have guessed UAFs and type confusions would be higher on the attacker priority queue for the last 15 years. Rust prevents those statically.
The most important safety mechanism in Rust is the borrow checker. It solves so many real problems that people willingly put up with the steep learning curve because that's easier than debugging data races and use after free.
Bounds checking is nice but it's not interesting or compelling enough to talk about as some ungodly super power of safety and security.
For such projects, a GC runtime goes against the reason why they used C in the first place. Rust can replace C where Fil-C can't.
A technically memory-safe C with overhead is not that groundbreaking. It has already been possible with sandboxing and interpreters/VMs.
We've had the tradeoff between zero-overhead-but-unsafe and safer-but-slower languages forever, even before C existed. Moving C from one category to the other is a feat of engineering, but doesn't remove the trade-off. It's a better ASAN, but not miraculously fixing C.
Most projects that didn't mind having a GC and runtime overhead are already using Java, C#, Go, etc. Many languages are memory-safe while claiming to have almost C-like performance if used right.
The whole point of Rust is getting close to removing the fast-or-safe tradeoff, not merely moving to the other side of it.
These are two great reasons to try Fil-C instead of Rust. It seems that many Rustaceans think in terms of their own small community and don’t really have a feel for how massive the C (or C++) universe is and how many different motivations exist for using the language.
There's a lot of legacy C code that people want to expand on today, but they can't because the existing program is in C and they don't want to write more potentially unsafe C code or add onto an already iffy system.
If we can rewrite in Rust, we can get safety, which is cool but not the main draw. The main draw, I think, is you now have a rust codebase, and you can continue on with that.
The thing that is interesting about Fil-C isn’t that it’s a garbage collected language. It’s that it’s just C and C++ but with all of the safety of any other memory safe language so you can have a memory safe Linux userland.
Also, Fil-C isn’t anything like ASAN. ASAN isn’t memory safe. Fil-C is.
Rust doesn’t rely only on compile-time checks, so I find your claim dubious. Actually, the dynamic checks done by Rust are presented as useful features in themselves.
The memory safety audience and most people seem like arbitrary groups defined to support claims which aren’t really supported by strong evidence.
The biggest improvement in memory safety in the past decades wasn’t thanks to Rust, but languages like Python, Java or C# which rely heavily on dynamic checks. The goal is to catch bugs and avoid security vulnerabilities.
Taking standard C code and achieving the above would be amazing and much more useful than rewriting something in Rust.
The point about expressive semantics is that you can foreclose on vulnerabilities statically, not that everything becomes a static check. That’s why I mentioned UAFs and type confusions in the adjacent response below.
> Taking standard C code and achieving the above would be amazing and much more useful than rewriting something in Rust.
As others have pointed out, you can’t do this without biting one of two bullets: you either change the language semantics to resemble something like Rust, or you add instrumentation that turns C into a managed language. Either of these forks is great, but neither is something you can do transparently: the former means breaking existing C code, and the latter means excluding a large percentage fraction of the world’s C code (where the absence of a managed runtime is a hard requirement).
Fil-C bites the second bullet, under the theory that there’s a lot of userspace code that isn’t extremely performance sensitive. And that’s probably true, but I also think it misses the larger trend: that a lot of userspace code is abandonware, and that there’s sufficiently more interest in rewriting it than maintaining it. For that reason alone, I think we’re going to see more userspaces in safe compiled languages, not unsafe ones that have been instrumented into safety.
Is there sufficiently more interesting in rewriting it, really? I know that there are a handful of userspace utils being rewritten in Rust, doing that is labor-intensive, and causes regressions (in perf and behavior), which then causes more labor (both for folks to deal with the fallout on the receiving end and to fix the regressions). And for every tool that has a rewrite in flight, there are maybe 100 others that don't.
(If it was, we wouldn't have dozens of tools that all NIH the same thing.)
I think any software on the "most people are annoyed" list will get a rewrite. All the tools where people cared specifically about perf anyway are already rewritten or being rewritten because there are so many performance opportunities. The out-of-box grep sucks compared to ripgrep for example.
It will suck to be someone with no programming ability for whom a tool most people aren't annoyed by is too slow with Fil-C for their niche use. But that's not so different from how it sucks when your local government forgets deaf people exist, or that time we made everything use touch screens so if your fingers don't "work" on a touch screen now you're crippled with no warning.
I think it might also be that people mostly consider languages from the perspective of what they'd write a greenfield codebase in. And if I'm gonna pay the GC cost, I'd much rather work with language/library body that doesn't have tons of ownership idioms that are basically irrelevant with a GC. So it's not Fil-C vs Rust directly; it's Fil-C vs Go (Go wins), then Go vs Rust (more interesting decision).
But for existing large C projects that are ancient enough that running on modern hardware far outweighs the new GC cost, and that are mature/minimally maintained so the development costs for a rewrite/translation won't ever pay off in future maintenance, I think Fil-C is an intriguing option.
btw, IMO Rust has more going for it than just the borrow checker.
Like, say you’re writing a port daemon. Then your argument holds! And that’s admittedly a big category since it includes databases, application servers, and a lot of other stuff.
But say you’re writing an app that talks to systemd and your desktop shell and renders things and has a UI. If you do that in Go or Rust, you’re pulling in a ton of unsafe dependencies. But the Fil-C story is that you just compile all of that stuff with Fil-C and so there are no unsafe dependencies.
By the way, that’s not a fantasy but like mostly a reality. I have a Linux distro where all of userland is compiled with Fil-C and it works great!
Now you might say, why not rewrite all the deps in Go or Rust? The funny thing about that is you sort of can’t do that today since neither of those languages has dynamic linking. Fil-C supports dynamic linking just fine.
what do you mean by this?
Compare this situation with Java/JVM or C#/.NET, both of which define their own ABIs albeit not for native machine code, or especially Swift, which defines its own native-code ABI.
I don’t know about Go, but that’s certainly not true for Rust. Dynamic linking is the norm in Rust; you can run `ldd` on any stock-built binary to see that it dynamically links to glibc (or libSystem or similar).
(It’s also common for Rust libraries to be distributed as shared objects with C APIs/ABIs — to my understanding, this is how virtually every incremental adopter of Rust has chosen to adopt it.)
So if you rebuilt userland with Rust and had the same layout of shared libraries then you’d have a massive amount of unsafe code
Sort of, but I think that’s misleading; you’d have a massive amount of safe code, scaffolded with unsafe ABI boundaries. That’s a problem, but it’s not really the same kind of attacker or fault surface as unsafe code in the libraries themselves.
It’s also a wholly solvable problem in the sense that Rust could define a stable non-C ABI. There just hasn’t been an extraordinary need for that yet, since most people who want to build Rust code into shared objects do want a C ABI.
scpptool demonstrates enforcement (in C++) of a subset of Rust's static restrictions required to achieve complete memory and data race safety [1]. Probably most notably, the restriction against the aliasing of mutable references is not imposed "universally" the way it is in (Safe) Rust, but instead is only imposed in cases where such aliasing might endanger memory safety.
This is a surprising small set of cases that essentially consists of accesses to methods that can arbitrarily destroy objects owned by dynamic owning pointers or containers (like vectors) while references to the owned contents exist. Because the set is so small, the restriction does not conflict with the vast majority of (lines of) existing C++ code, making migration to the enforced safe subset much easier.
The scpptool-enforced subset also has better support for cyclic and non-hierarchical pointer/references that (unlike Safe Rust) doesn't impose any requirements on how the referenced objects are allocated. This means that, in contrast to Rust, there is a "reasonable" (if not performance optimal) one-to-one mapping from "reasonable" code in the "unsafe subset" of C++ (i.e. traditional C++ code), to the enforced safe subset.
So, relevant to the subject of the post, this permits the scpptool to have a (not yet complete) feature that automatically converts traditional C/C++ code to the safe subset of C++ [2]. (One that is deterministic and doesn't try to just punt the problem to LLMs.)
The problem isn't dedicating public resources to trying to getting LLMs to convert C to Safe Rust after investments in the more traditional approach failed to deliver. The problem is the lack of simultaneous investment in at least the consideration and evaluation of (under-resourced) alternative approaches that have already demonstrated results that the (comparatively well-funded) translate-to-Rust approach thus far hasn't been able to.
[1] https://github.com/duneroadrunner/scpptool/blob/master/appro...
[2] https://github.com/duneroadrunner/SaferCPlusPlus-AutoTransla...
This is half of it; the other half is that there's more to writing correct code than just memory safety.
Rust was not initially designed as a memory-safe "C alternative" -- it started as a higher level language with green threading and garbage collection. Borrow checking, affine types, and all that were introduced not to "solve" memory safety, but to reduce logic bugs in complex, highly concurrent code by enabling programmers to statically check application invariants using the type system. Once it became apparent that this system was powerful enough to express the semantics of full memory safety without garbage collection, GC was removed from the core of the language, and Rust became what it looks like now.
The point is, I think focusing on "memory safety" seriously undersells Rust. Rust is aimed at giving you tools to statically verify arbitrary correctness properties of your program; and memory safety is just one example of how the standard library uses the available tooling to prove one particularly useful property. But Rust's "safety" protects you from any logic bug that you define to be a safety issue.
Additionally, this means that you're not restricted to one particular runtime or environment's ideas of memory safety -- you can write or bring in unsafe code to define your own requirements. This is very important to me -- I work on low-level driver and RTOS code for microcontrollers, and am commonly doing very unsafe things with task switching, interrupts, DMA, memory layout and pointer casting tricks, inline assembly, hardware MMIO, power management, etc. Rust fits fantastically in this niche, because I can use the type system to write out all the preconditions that external users must uphold when interacting with my driver code.
I think Fil-C is an excellent project, and is far more practical and realistic than TRACTOR for the problem of securing legacy code. But I also see it as largely orthogonal to Rust -- I can't see many situations where someone would choose Fil-C for greenfield code over something like Java or Go. Rust has safety, performance, and interop advantages over GC'd languages; and safety advantages over other C-like languages; so it's a great choice for new projects, but it's not gonna help you with all your old code like Fil-C will.
> It’s also annoying that this DARPA page mentions some kind of consensus. There’s no consensus on Rust being the safe bet.
The "consensus" the article talks about is not Rust, it's that "relying on bug-finding tools is not enough." Swift, C++-with-[the right]-changes, and Fil-C all would fall within that consensus (of needing some sort of guaranteed safety); only Zig is something of an exception in your list.
But what Rust has is the best tooling bar none(cargo, build system, compile time checks, ease of first use). The tooling is actually more important than the borrow checker and memory safety in my opinion.
If I clone a Rust repo, it’s actually easier to compile, test, and run the code than any other language. It avoided the fragmentation of JS/TS (npm, yarn, pnpm, bun, deno) and dep hell of Python (which was a nightmare until uv).
If Rust didn’t have the syntax warts (macros), it would be eating the world.
Here's a struct that maintains an invariant - say, that field a is less than field b. That invariant should be set when it is created.
You find a bug where a is greater than b. Where is the bug? With a struct, it can be anywhere in the code - any line that touches the struct. But with a (well designed) class, a and b are private, and so you only have to look at lines of code within the class. The surface area where the bug can be is much smaller.
The bigger the code base and the more well-used the class is, the more this matters.
Take std::os::fs::OwnedFd the file descriptor. In fact of course this struct is literally just a C-style integer inside, it's the same size in memory, representationally they're identical. But, it's encapsulated, so it gets to enforce the fact that file descriptors are never -1 by definition, and since it is encapsulated it gets to refuse to participate in arithmetic, and to call close when we throw away the file descriptor, and so on. It's a huge improvement.
I beg to differ because Go has a large standard library which means less dependencies than Rust on average.
My experience with random rust projects is that they usually "just build", with limited exceptions like weird embedded stuff.
In Go, it doesn't have any of that so it depends on the end builder of the binary to be aware of all the C dependencies and manually manage integrating the cgo configuration into their build process.
And is actively discouraged by the community.
https://github.com/discord/lilliput/blob/master/cgo.go
far more commonly in corporate Go code than Rust.
The vast majority of Go code, like 99% doesn't have a single cgo dependency.
zig is very comparable, and much faster at doing so. zig also comes with a build system, libc and can compile c programs. its a better c compiler and build system than most, lol.
zig's type system is pretty straightforward, but its comptime is very powerful and, among other things, can enforce arbitrary compile time constraints. It's not the same as rust's types, but I wonder if it isn't better in many ways.
33 more comments available on Hacker News