193 comments

  • Animats 2 days ago ago

    This is C to Rust, not C++ to Rust. That's important.

    DARPA was willing to award multiple contracts, but the only one awarded is to a group from several universities. [1]

    "The team’s approach, Formally-Verified Compositional Lifting of C to Rust (which forms the acronym ForCLift, pronounced “forklift”), uses Verified Lifting, which combines formal methods and program analysis with AI techniques such as Large Language Models, so as to create accurate translations of complex C code into safe, idiomatic Rust. The approach seeks to enable formal verification of the translated code while also preserving performance-critical behavior."

    This involves something called "Verified Lifting."[2] "Metalift uses verified lifting to search for possible candidate programs in the target language that the given input can be translated to." So it's looking for matching idioms in the target language and using proof techniques to check that they are equivalent. Going uphill in abstraction automatically is rare. This will definitely be interesting. It's essential to good translation.

    The old C2Rust is all downhill. What comes out of C2Rust are huge numbers of calls to functions that exactly emulate C semantics, bugs and all. I tried it once, on a buggy JPEG 2000 decoder. The test case which caused a segfault in the C version also caused a segfault in the unsafe Rust version. At least it generates compatible code.

    [1] https://www.cs.wisc.edu/2025/07/15/translating-legacy-code-f...

    [2] https://metalift.pages.dev/

    • juliangmp 2 days ago ago

      > The test case which caused a segfault in the C version also caused a segfault in the unsafe Rust version. At least it generates compatible code.

      I mean... That's what I would expect. It's a translation not a rewrite. The question here is really “what's the end goal?”. Are you gonna refactor parts of the translations output, or is that too much work? Cause a pure translation won't give you anything besides a different compiler and build system. Ah well I guess you can claim you're memory safe and blazingly fast

      • Animats a day ago ago

        The end goal for DARPA's project is safe Rust. Translate unsafe constructs to safe constructs. C arrays of unknown length become Rust arrays or Vec items of known length. Pointer arithmetic becomes slices. (This covers most string manipulation, a high-risk activity in C.) Ownership translation probably will involve too much Rc/RefCell at first.

        The key to this is using an LLM to recognize idioms, then formal methods to verify that the LLM guessed right. Which is what the current project is trying to do.

        For example, consider C code with a function:

            void foo(int* tab, size_t len) { ... }
        
        TRACTOR needs to do something like:

        - Look at foo and its callers. Determine whether "tab" is an array or an indirect pass of a single integer.

        - Look at foo and see if tab is ever modified. That determines whether it is mutable. It may be necessary to go down the call chain. This analysis may not be able to determine if it is mutable, but if determines it is immutable, tab can be passed immutably.

        - Ask the LLM to figure out the size of tab from context in both foo and its callers. Is len the length of tab? That's a common idiom in C an LLM can recognize, but it might be a wrong guess. Is it the length in bytes or in ints? Remember, the programmer had to be able to figure this out, so the LLM has a good chance of doing it.

        - If tab is immutable, hypothesize that the correct translation is

            fn foo(tab: &[int]) { ... }
        
        and within "foo", len comes from tab.len()

        Now attempt to use "lifting" formal analysis, as mentioned in the paper, to see if that changes the semantics of the program. Does "foo" subscript out of range? Can you prove that it doesn't?

        This problem needs both LLMs and formal methods. LLMs to infer intent, and formal methods to check that inference.

      • estebank a day ago ago

        There's one reason I could think of for translating from C to Rust without further changes: simplifying the build. If you can remove the need for a build.rs script running make, that's one headache less. At that point you have exactly the same behaviour as wrapping the original C code in a -sys crate, so all of the usual caveats are warranted.

  • pizlonator 2 days ago ago

    (Sorry for talking about my personal project again y’all.)

    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.)

    • woodruffw 2 days ago ago

      > 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.

      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.

      • pornel 2 days ago ago

        Another aspect is that the majority of projects that keep using C, do it specifically to maximize performance or low-level control (codecs, game engines, drivers, kernels, embedded).

        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.

        • pizlonator 2 days ago ago

          There are so many programs written in C or C++, but not in any of the languages you cite, that run just fine in Fil-C.

          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.

        • pjmlp 2 days ago ago

          Many project do keep using C out of cultural and human reasons as well, they could have long written in a memory safe language, but goes against their world view, even when proven otherwise.

        • blub 2 days ago ago

          Many people know and like C. Many companies have access to plenty of C talent, but no Rust talent.

          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.

          • array_key_first a day ago ago

            I agree, but the converse is also true and is where the value of this DARPA grant lies:

            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.

      • pizlonator 2 days ago ago

        I’m not inventing a definition for memory safety out of thin air, so I think there’s just a tendency to conflate Rust’s static checking with memory safety.

        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).

        • woodruffw 2 days ago ago

          > 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.

          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.

          • pizlonator 2 days ago ago

            My data comes from OSes as a whole not just from browsers or high performance codebases.

        • duped 2 days ago ago

          I would disagree, because people don't really care about memory safety for security reasons as much as I think gets talked about.

          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.

      • blub 2 days ago ago

        “ 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 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.

        • woodruffw 2 days ago ago

          I didn’t say it relies only on compile time checks. Where are you getting that from?

          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.

          • pizlonator a day ago ago

            > 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.

            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.

            • tialaramex a day ago ago

              Fil-C is going to usually be a huge perf regression right? Sometimes I won't care, sometimes I will and this will vary between users with only some commonality.

              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.

            • woodruffw a day ago ago

              I think so: you're 100% right about the labor, but OSS isn't a rational labor market :-). People RIIR not because it's easy, but because they find it more fun than the alternative.

              (If it was, we wouldn't have dozens of tools that all NIH the same thing.)

    • AlotOfReading 2 days ago ago

      There's plenty of reasons to prefer Rust to a memory-safe C. For example, I work on safety-critical code. That means that I have to review and affirm "This code implements my design". Making C memory-safe doesn't make the semantics of all UB defined or appropriate.

      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.

      • pizlonator 2 days ago ago

        > Making C memory-safe doesn't make the semantics of all UB defined or appropriate.

        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.

        • AlotOfReading 2 days ago ago

          It's on my free-time backlog to spend more time with Fil-C, so I'm not disagreeing from lack of interest.

          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.

          • pizlonator 2 days ago ago

            Fil-C absolutely does fix uninitialized memory.

            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)

            • junon 2 days ago ago

              How does Fil-C "fix" uninitialized memory?

              • tialaramex 2 days ago ago

                I assume under the same "memory safety" rationale it just zeroes the RAM. That's "safe" and compatible with C.

                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?

                • junon a day ago ago

                  I guess I don't see how making inherently incorrect C code "safe" by sanitizing something it shouldn't be doing anyway is actually improving the C code.

                  • voidmain a day ago ago

                    The key thing that memory safety provides is local reasoning. You can look at some important piece of code and conclude that it does the right thing, even if there are a million other lines of code somewhere else. UB makes this impossible; no matter how carefully you review dont_launch_missiles() it might launch the missiles due to an integer overflow in totally unrelated code in the same process.

                    • junon 16 hours ago ago

                      I agree with you, but this feels more of "fixing" inherently unsafe code in the same way we "fixed" the elephant's foot in Chernobyl by covering it with a giant roof. It doesn't actually fix the problem, just lessens and prolongs it.

                      • tialaramex 15 hours ago ago

                        Yes the resemblance to the sarcophagus is I suppose warranted. The best of bad options.

                        The assumption in Fil-C is that you can't or won't rewrite. So a modified C compiler which rejects the uninitialized variable (as Rust would) is not acceptable because now what? We were supposed to make the existing C program memory safe, not reject it, anybody could write a "compiler" which rejects the C programs as unsafe.

                        This is the same assumption C++ had. C++ 26 lands "Erroneous Behaviour" for this purpose. Previously if you write `int x; foo(x);` that's Undefined Behaviour in C++ just like C, game over, anything might happen if this executes.

                        In C++ 26 `int x; foo(x);` is Erroneous but not Undefined. It might tell you (perhaps at runtime) that you forgot to initialize x, because doing so is an error - but if it presses on it will behave like `int x = SOMETHING; foo(x)` where SOMETHING was chosen by your compiler and implemented exactly the way you'd expect, by quietly initializing your uninitialized variable.

              • pizlonator a day ago ago

                By initializing it to zero.

    • scottlamb 2 days ago ago

      > 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.

      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.

      • pizlonator 2 days ago ago

        I think what you’re saying is true for the kind of software where it isn’t just greenfield but also doesn’t have to make deep use of preexisting system dependencies.

        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.

        • woodruffw 2 days ago ago

          > 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.

          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.)

          • pizlonator 2 days ago ago

            When you do that, the ABI boundary around your shared library is unsafe.

            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

            • woodruffw 2 days ago ago

              > 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.

        • Splizard 2 days ago ago

          > neither of those languages has dynamic linking

          what do you mean by this?

          • kbolino a day ago ago

            Neither Go nor Rust define an ABI for themselves. They can use dynamically linked C code just fine but cannot link their own language with all (or even a reasonably broad subset) of its own features. This is not as bad in Rust, where you can fall back to the unsafe C ABI while still having safe Rust on either side, whereas Go cannot have two instances of its runtime active in the same process.

            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.

    • adastra22 2 days ago ago

      Does your thing add linear types, borrow checking, and remove implicit conversions from C?

      • pizlonator 2 days ago ago

        Definitely not. Then it wouldn’t be a C implementation.

        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++

        • adastra22 2 days ago ago

          I don’t see the relevance to this discussion then.

          • NobodyNada 2 days ago ago

            The discussion is about a project for securing legacy code by machine-translating it to Rust. Fil-C is an alternative way to secure legacy code using a different C implementation. I think that's highly relevant to the discussion.

            • adastra22 2 days ago ago

              The kind of errors being protected against are totally different though.

              • pizlonator 2 days ago ago

                Fil-C protects against a superset of the errors that Rust protects against. It just does it dynamically.

                And more comprehensively. There’s no `unsafe` statement in Fil-C. There’s no need for it since dynamic checking is vastly more precise.

                • adastra22 2 days ago ago

                  Dynamic/runtime checks (and crashes) are VERY different from compile time checks though. Many applications, and especially those that DARPA are focused on, care about ahead-of-time guarantees that code will work correctly, and runtime panic is actually the worst possible failure mode. Think of flight control software, for example.

                  • pizlonator 2 days ago ago

                    This DARPA doc isn’t about flight software.

                    Rust uses runtime checking for array access bounds, which are the most common kind of memory safety vulnerability.

                • jandrewrogers 2 days ago ago

                  Checking at compile-time is required for some applications and highly desirable regardless.

                  This is something recent versions of C++ do really well. It is my main reason for using C++ beyond its unparalleled performance in practice.

          • pizlonator 2 days ago ago

            You’re confusing memory safety with Rust’s specific flavor of static checking.

            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.

    • NobodyNada 2 days ago ago

      > 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.

      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.

    • safercplusplus 2 days ago ago

      As long as we're plugging our projects, I'll mention the scpptool-enforced memory-safe subset of C++. Fil-C would be generally more practical, more compatible and more expedient, but the scpptool-enforced subset of C++ is more directly comparable to Rust.

      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...

    • iberator 2 days ago ago

      Hey. Thanks for sharing. Never heard about Fil-C before. Looks interesting

    • heavyset_go 2 days ago ago

      I'm genuinely curious where Swift is being used outside of macOS/iOS apps

    • hluska 2 days ago ago

      The article doesn’t say the consensus was reached around Rust. That paragraph was talking about memory safety and so were both paragraphs around it. Rust isn’t even mentioned for two paragraphs after the part that annoyed you so much. But the first four paragraphs were all about memory safety.

  • IceHegel 2 days ago ago

    I don’t think Rust syntax and patterns (no classes) are especially elegant for many tasks. I can’t express the behavior of a system as cleanly in Rust as TypeScript, C#, go or Python. I know that’s not what it was designed for, but a guy can dream.

    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.

    • foota 2 days ago ago

      This is a bizarre take to me, what do you want to do with classes that aren't supported by structs and traits? Imo the usability issues with rust arise from the borrow checker and associated complexity + restrictions on patterns, so I'm surprised that you're citing macros and classes.

      • AnimalMuppet 2 days ago ago

        Access control.

        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.

        • kibwen 2 days ago ago

          Rust has privacy and encapsulation just fine. More than that, Rust's entire safety story is built on these mechanisms; being unable to (safely) access private fields outside of the module in which they were defined is load-bearing when it comes to safely encapsulating unsafe code.

        • joshmarinacci 2 days ago ago

          You can do exactly this in rust using non public fields and accessor methods.

        • tialaramex 2 days ago ago

          I think the large C++ or Java shaped hole in your understanding is simply that you think "class" means encapsulated and "struct" means Plain Old Data and in Rust that's not what it means.

          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.

        • foota 2 days ago ago

          Ah, that makes some sense, although some reading says that struct member visibility is by default the module, which is a file if you don't do anything. If you wanted you could probably just wrap all the structs you want to be protected inside a module per file? It is a bit annoying though. I guess the issue here is that in rust struct fields need to be accessed for trait implementations. It wouldn't be backwards compatible obviously, but I wonder if they could have tightened that so that by default only trait implementations for a struct can access that structs members?

        • 3836293648 2 days ago ago

          Rust has exactly that. The difference is that rust considers the scope of private access te be the entire file it's defined in, not just its methods.

          • kibwen 2 days ago ago

            Just the module the struct is defined in, not the file. Easy mistake to make, given that a file is implicitly its own module, but you can create submodules within a file with the `mod` keyword.

            • 3836293648 a day ago ago

              I thought it crossed into submodules as well, making it the entire file?

        • array_key_first a day ago ago

          Rust has access control, and rust has better mutability and reference control. Many languages like C# and Java let you take references willy nilly and do almost whatever you want.

        • Dr_Emann 2 days ago ago

          Rust has access control. Fields are private by default.

      • the__alchemist 2 days ago ago

        I'm confused too! When I write Python, I do it in a similar style as rust, but knowing the classes and enums are sloppier than rust's; regarding mutation for example.

    • mrheosuper 2 days ago ago

      >dep hell

      As a C programmer, i'm always a little panic how a small Rust Program can pull in that many crates when compiling.

      • james7132 2 days ago ago

        Once you understand that a crate is the translation unit in Rust, it doesn't feel as bad. Most medium to large Rust project's will separate out their code into separate crates for both organization and compile time.

        I've definitely cloned down my fair share of C projects, mashed the make command into my terminal, and watched the gcc/clang logs fly by and never batted an eye beyond checking the sha256sum on any downloaded tarballs.

        There's a valid argument to be made about supply chain attacks, but there does exist tooling to lock that down, and I would argue that any serious software development firm should be auditing every third party dependency they take on.

    • sitzkrieg 2 days ago ago

      > If I clone a Rust repo, it’s actually easier to compile, test, and run the code than any other language

      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.

      • treyd 2 days ago ago

        But Zig doesn't have the very sophisticated type system that Rust has. Nor does it, importantly to DARPA, have the memory safety that Rust does.

        • jmull 2 days ago ago

          A type system in programming languages is a way to express and enforce compile time constraints (conventionally, anyway).

          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.

          • treyd 2 days ago ago

            It's not comparable, comptime is more of an alternative to macros. You can build complex systems with it, but they don't natively give you the algebraic reasoning abilities that the typechecker does, at best you'd have to reimplement it yourself in an ad hoc way. Rust's proc macros are also fully programmable and have comparable expressive power to comptime.

            • Rendello 2 days ago ago

              I used Zig in the past (after my "why don't we just write everything simply in C" phase). I don't think I used comptime too much, but I understood why it would be useful.

              Now I write Rust and absolutely love it, except for the damn macro edge cases, like not being able to use a known-at-compile-time string for format!() unless it's a literal (I even tried to fake it with more macros, no dice). I think Zig's Andrew Kelley mentioned this exact scenario, if I recall correctly.

              It's funny because I do write a lot of code that generates code, but I avoid macros if I can.

        • jandrewrogers 2 days ago ago

          Don’t underestimate Zig’s comptime or modern C++’s constexpr. You can use these to prove things about the program at compile-time far beyond the type system. In recent versions of C++, the scope of code that is compile-time verifiable is quite large, nothing like when it was first introduced 15 years ago.

          This has limited (but not zero) applicability to memory safety but it has a lot of applicability to many other classes of defect against which Rust offers no special protection. Features like this are why modern C++ is still the language of choice for new software in high-assurance environments at DoD when performance matters. (When performance doesn’t matter it seems to be Java and C#.) These systems often have little or no legacy C++ code as a dependency, so that isn’t a factor.

          I have less experience with Zig but this is an area where Rust can’t replicate the safety features of modern C++. With the introduction of compile-time reflection in C++26, this gap will increase. People who aren’t deep in it seriously underestimate what can be verified at compile-time in recent versions of C++ without the use of ugly arcana (which used to be required).

          • tialaramex 2 days ago ago

            C++ constexpr is a nasty trap. Because after all it says right on the tin that we're getting a constant expression right? So it's as powerful as Rust's const right?

            Nope - of course the usual suspects insisted they needed a way to write non-constant expressions and have that somehow "work" anyway. So whereas a const function in Rust genuinely is constant, a constexpr function in C++ might not be, and we only find out whether it was if we force the compiler to do the operation at compile time. If we leave any gap where it can just delay until runtime that's what happens.

            You can literally write a random number generator, label it "constexpr" and a modern C++ compiler goes OK, that's not actually constant, but you didn't technically promise it was constant you just used this useless "constexpr" keyword to gesture performatively at the idea of compile time evaluation without promising anything so we'll only complain if you try to use it in a context where I must know the concrete value at compile time.

            • pjmlp 2 days ago ago

              True, however I would expect that anyone that knows constexpr is also aware of constinit, consteval and static constexpr.

              Does it suck instead of having a single mechanism?

              Yes, but the tools are there to actually enforce it at compile time.

      • heavyset_go 2 days ago ago

        These are honest questions and not rhetorical: how does Zig handle versions with syntax changes or breaking changes?

        Can you mix Zig libraries written X years ago with modern Zig? Will today's code work in 5-10 years if I want to use it in a project then?

        • james7132 2 days ago ago

          Zig has not hit 1.0 yet, and as recently as a few months ago completely reworked how every form of IO is written. AFAIK, this wasn't a syntax change, but it changed the function signature or type definition of every piece of code that reads/writes a file, establishes a connection, etc. At the current time, there is little guarantee that the code you write today will still work in 5-10 years time.

          • heavyset_go a day ago ago

            Thanks for the info, I was hoping there was something like Rust's editions that would allow for mixing libraries with differing language versions that have breaking changes.

    • AbuAssar 2 days ago ago

      > It avoided the fragmentation of JS/TS (npm, yarn, pnpm, bun, deno)

      just use npm, the others are just more options, thersr is no "fragmentation"

    • iberator 2 days ago ago

      Not everyone likes OOP you know? Some people love low abstraction code.

    • hu3 2 days ago ago

      > If I clone a Rust repo, it’s actually easier to compile, test, and run the code than any other language.

      I beg to differ because Go has a large standard library which means less dependencies than Rust on average.

      • AlotOfReading 2 days ago ago

        It's not usually the standard library or dependencies that create the issues I've seen. The teams I work with producing Go tools (across multiple companies) invariably require carefully orchestrated dev environments that are nigh-unreproducible. It's 50/50 on whether I can actually build a random project first try without reading the instructions if CGO is involved, which seems to be all of them.

        My experience with random rust projects is that they usually "just build", with limited exceptions like weird embedded stuff.

        • 0x696C6961 2 days ago ago

          Rust projects which depend on C libs have very similar issues.

          • timschmidt 2 days ago ago

            Well yeah, because C has those issues. People like to clown on the Rewrite It In Rust attitude, but it comes with real benefits.

          • treyd 2 days ago ago

            I haven't experienced this. Rust's build system allows you to automate most of the pain in building/bundling those dependencies, so it's just up to the builder to have the right headers (if they're not bundled). That makes it no worse than meson C/C++ builds.

            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.

            • estebank 2 days ago ago

              Its highly dependent on the kind of project. A few years back libxml and libxmlsec1 were a consistent pain in the neck for me. I don't know about now, I simply moved on from the project that needed me to interact with them.

          • joshmarinacci 2 days ago ago

            I don’t hate the C language. I hate the C compiler (and the rest of the toolchain). Anything that helps me not interact with the C compiler is a huge win.

        • Thaxll 2 days ago ago

          I worked for 10 years with Go and almost never seen a cgo dependcy, it's far more common in Rust, it's not even comparable. Rust replaces tons of c/c++ so it has more ffi.

          The vast majority of Go code, like 99% doesn't have a single cgo dependency.

        • hu3 2 days ago ago

          Again, I disagree. CGO is rarely needed for Go projects.

          And is actively discouraged by the community.

  • brendank310 2 days ago ago

    Past work in the area by the folks at Immunant (https://immunant.com/) that appears to be on-going https://github.com/immunant/c2rust. I think the project was also DARPA funded for a time.

  • bangaladore 2 days ago ago

    One of, in my opinion, the largest problem with Rust is that they sought to solve two problems:

    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#.

    • jchw 2 days ago ago

      To be honest I don't buy it. The biggest problem with translating programs to Rust, IMO anyway, isn't actually dealing with the chasm between mentalities regarding programming language design. I don't disagree that Rust intentionally goes a different way in many regards; obviously it focuses on composition over inheritance, and takes more inspiration from ML. But still, that isn't really the problem. It really does come down to the fact that appeasing the borrow checker is hard. It only accepts valid, well-formed programs according to its rules, but it rejects a ton of completely safe things in the process. It's a tradeoff.

      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.

      • treyd 2 days ago ago

        > Literally just not being able to easily and efficiently express interior mutability completely changes how you design both code and APIs.

        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.

    • the__alchemist 2 days ago ago

      Unfortunately, I don't think that's avoidable. This is equivalent to lamenting not being able to use Haskell-style pure FP, nor object inheritance. There are C++ (and C) design patterns that will just not work in rust, or won't work in an ergonomic way. The solution is to solve the problem in a different way.

      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.

    • convolvatron 2 days ago ago

      I don't think #2 is at all fair. I'm certainly of two minds about Rust and its ergonomics. But #2 seems to assume that C is some kind of default and canonical programming model, and to the extent that I like rust, its because they made different and internally consistent design choices.

      • bangaladore 2 days ago ago

        C/C++ is the "default" language they are/were trying to replace with Rust. So I think it's fair to point out that Rust made design decisions explicitly contrary to design decisions of C/C++ style languages even though Rust is meant to replace it. That's going to (and does cause) problems.

        • kibwen 2 days ago ago

          > design decisions explicitly contrary to design decisions of C/C++ style languages even though Rust is meant to replace it

          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.

          • bangaladore 2 days ago ago

            You are confusing problem 1 (memory / thread safety) with problem 2 (being distinct from C/C++). I'm not here to argue about changes made that are necessary to solve problem 1, but I'm also not here to pretend that all the differences Rust has compared to a C-style language like C/C++/C# is largely due to supporting memory / thread safety.

            • kibwen 2 days ago ago

              You continue vaguely asserting "differences" and then retreating when challenged. So please be specific: what differences?

      • torstenvl 2 days ago ago

        But C is the default and canonical programming model.

        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.

        • array_key_first a day ago ago

          For historical reasons. Which are very good reasons, but IMO we shouldn't just be forced to deal with the first somewhat okay solution we come up with for now until the end of time.

          C is a fine language, but there are so many glaring and obvious mistakes.

      • adastra22 2 days ago ago

        At the time that Rist was created, C/C++ and Java were pretty much the only industry standard languages.

        • kibwen 2 days ago ago

          No, even by 2010, Javascript, PHP, and Python would have all already surpassed C and C++ by number of professional programmers in industry.

          • adastra22 2 days ago ago

            None of those are systems languages.

            • kibwen 2 days ago ago

              The parent's claim wasn't about systems languages.

              • adastra22 a day ago ago

                It was about C/C++ and Rust, both of which are systems languages.

    • Ygg2 2 days ago ago

      > They didn't like C/C++

      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.

      • array_key_first a day ago ago

        C++ is much more safe than C and has numerous safety contracts that are impossible to represent in C. Its always weird when C and C++ are thrown together.

        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.

        • Ygg2 14 hours ago ago

          > C++ is much more safe than C

          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.

          • array_key_first 2 hours ago ago

            > The issue Mozilla faced wasn't that it wasn't safer than C. It's that it was not safe enough for their needs.

            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.

      • tialaramex 2 days ago ago

        > And the safety needle of C++ hasn't budged a femtometer.

        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.

    • waterTanuki 2 days ago ago

      C++ and C# share a letter only. They operate in entirely different domains. You can certainly try to write PLC logic or a an IMU Sensor in C#, but that's probably not going to be a fun task.

      • derefr 2 days ago ago

        C++ is used in many non-low-level domains simply because of performance, due to the many kinds of zero-runtime-overhead abstractions it offers. There are e.g. popular game engines written in C++. LLVM is written in C++. Some DBMSes are written in C++. Etc.

        C# overlaps C++ in all these “performance-sensitive high-level code” domains.

        • waterTanuki 2 days ago ago

          Given the topic of the thread is DARPA it's unlikely they're going to benefit from the type of overlap C++ and C# have in game engines or DBMSes.

      • bangaladore 2 days ago ago

        I'm very familiar with both. My day job in defense is bare metal systems with C & C++ and often integrating them with C#-based test infrastructure.

        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.

    • littlestymaar 2 days ago ago

      > Quite a bit of idiomatic and safe (yes that does exist) C++ doesn't "translate" well to Rust without large amounts of rearchitecting.

      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.

    • adastra22 2 days ago ago

      Examples?

      • bangaladore 2 days ago ago

        My best example of a "real" and not more artificial example (like XYZ data structure) is Game development / game engines & UI.

        For reference: https://news.ycombinator.com/item?id=40172033

        • adastra22 2 days ago ago

          A bit surprised that you didn’t mention Bevy in your post. Have you worked with it?

          • bangaladore 2 days ago ago

            Not my post, but I've heard the same concerns with Bevy as with the others. And the actual blog post linked by that post does mention Bevy many times.

            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.

            • adastra22 2 days ago ago

              I thought Unity and Unreal were transiting to ECS? I was under the impression at least that Bevy was adopting what the industry was moving towards, not exploring virgin territory.

              • bangaladore a day ago ago

                I'd very much consider ECS virgin territory. DOTS (ECS) in Unity has been out for 5+ years with little to no real adoption. I'm unaware of any pretty much any use of ECS in Unreal (I think what exists is mostly focused on internal graphics / animation, not gameplay).

      • pizlonator 2 days ago ago

        Doubly linked lists. Any cyclic data structure.

        • jnwatson 2 days ago ago

          While I think this is Rust's biggest flaw, this doesn't stem from any particular hatred of C/C++. This is related to memory safety, as it is very difficult to reason about memory lifetimes of object graphs with cycles.

        • treyd 2 days ago ago

          There are doubly-linked list libraries in Rust. They are safe and well-designed. It's rare for a project to actually need a doubly-linked list. When you need it, you should use those instead of reimplementing your own.

        • hackyhacky 2 days ago ago

          Both of those are a direct consequence of Rust's memory model, not a result of animus against C++.

        • JoshTriplett 2 days ago ago

          That's not at all a "we don't like C++" problem. That's "the chosen borrow-checking model makes cyclic structures hard, you have to do Rc/Arc and some manual management, or use unsafe and raw pointers". (Frankly, the latter is easier.)

          • pizlonator 2 days ago ago

            Ref counting doesn’t work for cyclic data structures

            • NobodyNada 2 days ago ago

              Sure it does. Make the backreferences weak, or use a library that provides cycle detection (or even full-on tracing GC if you really want).

              • pizlonator 2 days ago ago

                That changes the semantics. It won’t work for a graph for example.

                • NobodyNada 2 days ago ago

                  Right. The comment you replied to said "Rc/Arc and some manual management" -- "some manual management" implying that you need to account for the change to semantics in the manner appropriate for your application.

                  • JoshTriplett 2 days ago ago

                    (Note that I edited my comment for clarity since the original reply. My original comment just said "reference counting".)

                    • pizlonator 2 days ago ago

                      The key part I agree with most in your edited comment is that unsafe raw pointers are the easiest way to deal with cycles.

                      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

                      • adastra22 2 days ago ago

                        > 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.

                        That’s exactly what weak references do.

                      • JoshTriplett a day ago ago

                        For a graph, I agree.

                        For a tree with parent pointers, I'd absolutely use Rc, with Weak for the parent pointers.

            • JoshTriplett 2 days ago ago

              It doesn't fully handle the memory management, but it handles having shared references. You can use weak references or manually break the links when you want to free something. Or you can use unsafe raw pointers, which frankly seem simpler. Either way you're going to wrap it in a data structure that encapsulates all the details.

            • cyberax 2 days ago ago

              It works well. One easy trick is to have one reference count for the whole graph.

            • adastra22 2 days ago ago

              Rc has downgrade and the Weak type explicitly for this purpose.

        • adastra22 2 days ago ago

          The easiest way to implement these is with Weak references in one of the directions. This requires some checking and/or locks, but the fact it is not trivial to do is kinda the point: the integrity of a cyclic data structure depends on managing multiple pointers in multiple structs simultaneously, and with that comes concurrency dragons.

      • actionfromafar 2 days ago ago

        Syntax is different any many places for no apparent reason

    • dymk 2 days ago ago

      > They didn't like C/C++

      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.

      • array_key_first a day ago ago

        C++ is an unsafe language, but there is lots and lots of safe C++ code. Most C++ code is safe, that's why every other line isn't a segfault. Safety, as a whole, is about catching edge cases.

  • joshcsimmons 2 days ago ago

    Rust is the ideal language for defense applications. It's great to see defense buxxx funding this transition.

  • iberator 2 days ago ago

    Silly question:

    Let's say someone designed a C program that leaks memory for example in some unique way.

    Would RUST do the same? Would it happily auto translate erroneous code too?

    • correct_horse 19 hours ago ago

      Safe rust can leak memory, so a better question is "If someone wrote C code that made an invalid read or write, would rust do the same?" I can't answer the question, but ideally if the translated was safe, it would somehow eliminate the bug while keeping the desired behavior. That scenario seems a bit too optimistic though, so probably it'll have an unsafe block that does the invalid read/write and a human can come in and add runtime checks or refactor it further.

  • scj 2 days ago ago

    Is it going to translate C into good Rust code, or just C with a Rust accent? Think transpiled C in Javascript.

    Soon LLMs will be able to write Fortran in any language!

    • tialaramex 2 days ago ago

      There are definitely categories of code where you could realistically expect lift-and-shift from C which you're confident is correct to safe Rust that's maybe not very idiomatic but understandable.

      I believe Microsoft has a tool which did this for some bit twiddling crypto code. They have high confidence their C crypto code is correct, they run a process, they get safe Rust, and so their confidence transfers but now it's safe Rust so it just works in Rust software and you get all their existing confidence.

      But it's never going to be all code, and it might well never be most code.

  • gdiamos 2 days ago ago

    They should make the challenge to translate all of Linux and then maintain it

  • andrewmcwatters 2 days ago ago

    Maybe I just need to spend more time with Rust and deal with it, but I'm sad the industry desires to rally around it. Despite the specific subset of protections it aims to provide, I have always had issues with how ugly the language is.

    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.

    • malwrar 2 days ago ago

      I’d suggest reading their (free, online) book if you haven’t already, that’s what motivated me to actually try using it. It sells its core features pretty well and eased me into it better than just trying to grok the syntax. What kept me using it is how annoyingly frequently my code would _just work_ once I got it compiling, which I could often get to pretty quickly by catching errors early with a linter. I’d highly recommend giving it an honest try, the aesthetics make sense with a minimal amount of experience.

      • andrewmcwatters 2 days ago ago

        I am definitely interested in working with it more. It's obviously a fantastic modern language. It just has warts to me. Ones that make learning it a little off-putting in specific domains.

        I mostly expose myself to it, at the moment, through benchmark work which highlights how competitive of a good language it is.

      • adastra22 2 days ago ago

        As we transition to an era of LLM-generated code, it also means that once the LLM gets it to compile, it likely works.

    • mikepurvis 2 days ago ago

      What are the specific aesthetic complaints here?

      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.

      • mrheosuper 2 days ago ago

        I have no specific compaints, but here one example i saw online, and i'm talking from a C dev perspective.

          let x: Option<Result<Vec<i32>, std::num::ParseIntError>> = Some(Ok(vec![1, 2, 3]));
          let flattened = x
         .map(|r| r.unwrap_or_default())
         .unwrap_or_else(|| Vec::<i32>::new());
        
        I have no idea what the code is doing here, but while reading python or JS code, i can make an educated guess what it's doing.

        I have no experience with Rust so it makes sense i dont understand, but i also have no experience with Python or JS.

        • tialaramex a day ago ago

          It is of course impossible to know the context in which you saw this, but I will say this is a particular idiomatic way to write Rust which won't mesh with your C knowledge.

          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.

              let flattened = vec![1, 2, 3];
          
          Is the same effect, although probably for style you'd write:

              let flattened: Vec<i32> = vec![1, 2, 3];
        • mikepurvis a day ago ago

          It's a bit unusual for a type to be wrapped in both an option and a result, since they have a lot of overlap. They're both union types, but semantically, Result takes the place of throwing an exception (Ok is your return value or here's the error) while Option takes the place of a pointer (Some is an instance of the underlying type, vs None which the null case).

          Normally these union types would be handled with a match, or an if let, eg:

              if let Some(x) = fn_returning_an_option() {
                  do_thing_with_x(x);
              } else {
                  // handle that it was none
              }
          
          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.

      • andrewmcwatters 2 days ago ago

        Some of my complaints are petty, and I think can be dismissed as just personal preference. I don't have a great deal of complaint with languages with different syntax, just ones that are so intentionally cryptic so as to invent needless specific sigils that you need to memorize.

        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.)

        • mynameisash 2 days ago ago

          > just ones that are so intentionally cryptic so as to invent needless specific sigils that you need to memorize.

          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?

          • mikepurvis 2 days ago ago

            As in the prior comment, I'm a relative novice myself and certainly never achieved that moment with Rust where the code kind of melts away and you just see raw intent ("blonde, blunette, redhead"), but I do wonder if languages like Python have set our expectations a bit unrealistically in regards to that. Like instead of prioritizing information density, explicitness, and clarity, we got excited about the quick rush that came with `import antigravity`.

            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++.

    • umanwizard 2 days ago ago

      I see this complaint all the time about Rust, and it always confuses me because it doesn't match my experience at all. Do you have an example of Rust syntax that is more complicated than complicated C++?

    • adastra22 2 days ago ago

      I don’t consider Rust beautiful, but after a decade of working with Rust I am no longer bothered by its aesthetic warts.

    • Ygg2 2 days ago ago

      > My account is throttled by Hacker News moderators.

      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.

    • pizlonator 2 days ago ago

      It’s wild that this is downvoted.

      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).

      • AlotOfReading 2 days ago ago

            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).
        
        The whole problem is that C++ doesn't support them safely either. The committee has no interest in fixing C++, so what's the alternative that doesn't involve a new language? DARPA already considered and rejected things like sandboxed runtimes and rewrites from scratch because they don't fully solve the issues.
      • adastra22 2 days ago ago

        Do you have specific examples? All the areas you list are done in Rust too, where the borrow checker helps make sure they are bug free. Do you have an example of something that just can’t be represented in Rust’s type system?

      • Havoc 2 days ago ago

        This is DARPA we're talking about. They've got a pretty good track record on pulling off stuff people we're convinced can't be done

    • synack 2 days ago ago

      Have you tried Ada?

      • ggm 2 days ago ago

        Wait, wasn't there a DARPA round funding automatic translation of C to Ada once, long ago?

      • andrewmcwatters 2 days ago ago

        No, though I am familiar with its history a bit.

    • scoopdewoop 2 days ago ago

      I once had a boss that used to really hate python. He would roll his eyes whenever it was brought up. He was CTO of the company and he would sneer at it. One day, in a one-to-one meeting, I asked him, "what is so bad about python?"

      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.

      • hn_acc1 2 days ago ago

        I mean, I don't work with python all the time, but at work, it's the #2 language.. And the whitespace stuff is the most annoying part of it by far.

    • geertj 2 days ago ago

      It’s sad you are getting downvoted for simply expressing what seems to be a genuine opinion.

      • andrewmcwatters 2 days ago ago

        I am getting tired of participating in this community for many reasons, but this specific reason is one of the most tiring ones.

        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.

        • adastra22 2 days ago ago

          I didn’t downvote you, but I can see why your original unedited comment was downvoted. It provided no actionable objections, e.g. no examples.

      • Ygg2 2 days ago ago

        Because it's an extremely subjective, extremely superficial statement that does more FUD than it explains.

  • ChrisArchitect 2 days ago ago
  • observationist 2 days ago ago

    Shouldn't they change it to WARPA to reflect the Dept of War name change?

    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.

    • wmgries 2 days ago ago

      It feels more likely they'd shut down DARPA without realizing what it is than try to rename it.

    • hobs 2 days ago ago

      I will say what I will - what a pointless change that will yield nothing, literally virtue signalling. Nobody selling to the DoD is going to "yuck" after the word "war" is now part of the game, we've basically been continuously killing people since WW2.

    • kspacewalk2 2 days ago ago

      What alternative to having a defense/war industry and stockpiling significant amounts of armour and arms intended for state sanctioned violence do you propose? Where do the actions of the current governments of the PRC, Russia and North Korea figure in this proposed setup? What do you think the consequences of the transition phase (not the final result) of your changes will be? Some possible quantifiable measures of the latter include number of additional wars fought, number of additional genocides perpetrated, number of additional millions killed in conflict; but you're free to choose your own.

      • observationist 2 days ago ago

        Oh, no alternative proposed. The US has lost 10+ trillion to what amounts to an unaccountable budgetary black hole, however, and limiting the awful dingleberry NGOs and private contractors and horde of companies and people that exploit the need for miltary R&D is a good thing.

        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.

    • k72siqqu 2 days ago ago

      This is from 2024. Hegseth would want a language with a "warrior ethos", not Rust with its woke developers.

    • cozzyd 2 days ago ago

      Wait until Hegseth learns about the "safety" ethos present in rust and how heavy the binaries can be.

  • pyuser583 2 days ago ago

    I've said it before, but C with proper tooling extremely safe.

    • waterTanuki 2 days ago ago

      Every time this subject comes up there is always a "well MY C code is safe so Rust is a stupid language! You're just using the <language wrong/wrong tools>".

      I find it funny how much folks foam at the mouth about using X or Y wrong in a language that specifically chose to be flexible to fit into any possible combinations of toolsets and now you're telling people they need to use YOUR tools.

      Meanwhile Rust has solved this problem by having 1 compiler, 1 package manager, 1 formatter, 1 way to run tests, etc. etc. C/C++ will never have this because of how fragmented the ecosystem is. That's the price paid over years of committee decisions which prioritized industry customization & backwards compatibility above all else. You cannot have your cake and eat it too.

    • dymk 2 days ago ago

      You can say it as many times as you want, but we know it’s not true.

    • 01HNNWZ0MV43FF 2 days ago ago

      C and C++ yearn for modern tooling equivalent to Cargo and UV

      Noobs need consensus and senior devs need something that works, supports everything, and runs on crap platforms that can't run a Mix dev shell (Windows)

    • nickpsecurity 2 days ago ago

      Could you list the tooling that you use?

  • ironfootnz 2 days ago ago

    I think the only folks can solve this at the guys at autohand.ai They're into something at this level.