Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> This matches the expectations published in our blog post 2 years ago about the age of memory safety vulnerabilities and why our focus should be on new code, not rewriting existing components.

and

> As we noted in the original announcement, our goal is not to convert existing C/C++ to Rust, but rather to shift development of new code to memory safe languages over time.

For those working on C/C++ code bases, how does the incremental addition of Rust work in practice? What strategies and tools come in handy? Also, what are some good case studies where Rust was introduced to add new features, but still needed to work within a system mainly composed of C/C++? I've seen some of the first steps with Linux, but I'm thinking of a project where more substantial additions have been made.




Wrapping of C libraries in a Rust interface works quite well, and makes them safer. For stable battle-tested libraries I think it's even preferable to rewrites.

Many informal rules of C libraries like: "don't call read() after close()", "pointer must never be null", or "keep this data alive for as long as the handle is in use" in Rust can be expressed using the type system, and enforced at compile time. Cleanup can be automated. This catches bugs in user code and shields the library form misuse.


Nit: these are not informal rules, they’re clear UBs, they’re “just” not checked.

An informal rule would be “don’t use gets” before it was deprecated, or “don’t use the str* functions”, or “don’t pass a user-provided format to printf”.


> but I'm thinking of a project where more substantial additions have been made.

The most famous example of that is AFAIK Firefox. There's a (perhaps outdated) list at https://wiki.mozilla.org/Oxidation#Rust_Components of places where Rust was used to replace some component in Firefox; the most famous of these are probably the CSS style calculation which came from the Servo project (https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-en...), and a renderer also from the Servo project (https://hacks.mozilla.org/2017/10/the-whole-web-at-maximum-f...).


Brave Browser has some Rust components too (e.g. the adblocking engine). Rust in C++ works very well for components with a small, well-defined API surface that involve a lot of logic. You only need to build a small FFI layer for the direct interfaces between the two languages. CXX [1] makes this even easier, too.

Brave is definitely not aiming to convert the entire browser to Rust, but it's increasingly chosen for new development.

[1] https://cxx.rs/


I've only started scratching the surface, but that rust really wants you to use Cargo, while we have our own homegrown package manager, and cmake creates a lot of friction.

I can tell you that bad programmers can write bad code in Rust.


> I can tell you that bad programmers can write bad code in Rust.

Of course. The question rust users seem to put forth is that bad programmers write _better_ (not good) rust code than C code.

That bad programmers write bad code is to expected. That is, after all, a likely explanation for why they're bad.


I would argue that the type system does make it somewhat more difficult for bad programmers to do egregiously bad things in the language. A carefully written library can be quite difficult to misuse (at least, without panics or using unsafe code in the user code, both of which are easy to catch in code review).

Rust has no null/nil pointers. Instead, it has nullable types (Option<T>), which are harder to misuse. If you want to "dereference" a Option, you either use unwrap() (which panics) or you handle the None case properly. While `.unwrap().foo()` is still just as crashy as an unguarded `x->foo()` in other languages, a code review can catch misuse of .unwrap() much more readily than a missing null/nil check.

As another example, the Send/Sync traits provide strong guarantees about thread safety; using these traits properly lets you make data structures that cannot be misused in a multithreaded program. Although deadlock is still possible (hello, halting problem), many types of data races are simply eliminated.


> While `.unwrap().foo()` is still just as crashy as an unguarded `x->foo()` in other languages

I think it is also worth noting that unwrap itself is much safer than an unguarded `x->foo()`, since it doesn't involve undefined behavior. Meanwhile an unguarded `x->foo()` allows compiler to assume that x is never null and consequently do things that the programmer wouldn't expect. The recent post on undefined behavior [1] had a (to me) quite shocking example of that [2]. So while bad Rust programmers misusing unwrap get crashes, they won't get nasal demons.

[1] https://news.ycombinator.com/item?id=33771922

[2] https://kristerw.blogspot.com/2017/09/why-undefined-behavior...


`x->foo()` in C++ often isn't just "crashy", but undefined behavior. See https://en.cppreference.com/w/cpp/utility/optional/operator*

> The behavior is undefined if *this does not contain a value.

I'll take crashes over "probably does the wrong thing" any day.


This was the interesting point for me too; noting that _new_ C/C++ is where most of the bugs are found, and so it's less important to rewrite old code than it is to transition to memory-safe languages for everything new that gets written.

Perhaps this is an obvious point, but I found it interesting .

This probably also applies to the Linux kernal work in Rust too; if only new device drivers get written in Rust and the core remains C, it could still be a major win for kernel security.

> how does the incremental addition of Rust work in practice?

Probably a good starting point: https://firefox-source-docs.mozilla.org/writing-rust-code/cp...


I imagine it works just like FFI works in other languages. Compile a c-archive and link against it.


Pelikan is another example




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: