Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
The Case for Rust in the base system (freebsd.org)
185 points by pjmlp on Jan 21, 2024 | hide | past | favorite | 145 comments



To strongman the "anti" case: I believe that FreeBSD still nominally supports a number of architectures that have immature or no Rust support, which seems like a major blocker to (at least) rewriting major system components like devd in Rust. And build times are already a problem -- the joke five years ago was that the FreeBSD build was a wart on the side of Clang. Doubling that isn't ideal.

That said, I'm a big Rust believer and think it's the right tool for the job in a lot of situations where the historical answer was C or C++. Maybe it's the right tool for FreeBSD, too.


Yeah, the architecture point comes up in lost of rust in core type discussions, but I think when it comes to the BSD's it's actually a critical argument. I'm not particularly excited by limping along unusual architectures that most of the contributors can't perform reproductions on, but the BSD's are a bastion in this space and something probably has to be. Addressing this issue in both Rust and LLVM would be valuable at large.


Even arm32 and x86 are Tier 2. Not exactly unusual architectures. The only Tier 1 architectures are amd64 and arm64, i.e. only the absolute mainstream. Not exactly a bastion of architecture support.


> Even arm32 and x86 are Tier 2. Not exactly unusual architectures.

There is 32-bit x86 tier 1 targets like i686-unknown-linux-gnu.

> The only Tier 1 architectures are [...] only the absolute mainstream. Not exactly a bastion of architecture support.

Tier 1 means that the target has the full testsuite run against it for each single pull request. Running the CI is computationally extremely complex, and it is hard to provide a reliable and fast CI service for most architectures.


I meant ... the FreeBSD tiers.


It seems actually FreeBSD has dropped a lot of old platforms in recent versions, so this may not be a problem anymore. I imagine it would be with some other BSD's.


This. FreeBSD probably shouldn't be held back by VAX or MC88k support, but I'd be really disappointed if NetBSD for example abandon them.


Honestly, after being in the software industry for a couple of decades and seeing how many times folks attempt to reinvent the wheel (for commercial or other reasons), I am beginning to sigh when I see how many language zealots there are (not you, just in general). The reality is, Rust does not need to replace everything. Nor should it be held on some kind of pedestal.

E.G. Curiosity rover is doing just fine running on millions of lines of C.

https://vdocuments.mx/monitoring-the-execution-of-space-craf...

If it's going to impact OS stability and decrease performance and portability of the humble, dependable, simple C, it doesn't belong in the core. C is better than Rust for OS development.


The Curiosity rover might be doing ok, but the many places that have my social security number are not. I care more about the latter than the former.


Right—and maybe those places ought to install OpenBSD. https://www.openbsd.org/

Rust is not immune to security vulnerabilities. And at the end of the day, social engineering will steal more data than "hacking the mainframe". Why break in when you can just ask to be let in?

OpenBSD has a great security track record because they resist excessive change and prefer simplicity. For those who want to add Rust to the core of FreeBSD my primary question: is it really necessary? Or is it just because a bunch of Rustaceans want to?


Not solving all security issues isn't the same as not solving security issues. I'd rather my financial data be handled by software written in something that solves many whole classes of vulnerabilities than something that solves none of them.


Apart from the fact that it doesn't only solve a lot of security vulnerabilities, but also avoids a lot of bugs, by virtue of having a stricter type system and memory safety.


Remember we are talking about putting it into the core OS and overall what will the impact be on the stability of said OS. What folks here tend to describe is userspace applications which languages like Go/Java/C#/Erlang/Etc... already solve. In fact, most banks probably already use safer languages for the bulk of the workloads and it works just fine.

I want to point out one more thing: Rust is not a simple language by any stretch. It's equal to in complexity to C++ (yet without decades of established "good practices"). It is much preferable to have an easier to understand core and move the complexity outward—for improved stability and robustness. The core OS by nature of what it does needs to access raw resources in an "unsafe" manner. Rust kernel code will be littered with unsafe blocks and unnecessary complexity.


> For those who want to add Rust to the core of FreeBSD my primary question: is it really necessary? Or is it just because a bunch of Rustaceans want to?

Bfha... the link is a thread by the FreeBSD devs. Stop it with this language evangelist strawman.


> Right—and maybe those places ought to install OpenBSD.

Sure.

But running on OpenBSD doesn't solve application level vulnerabilities. And sure - OpenBSD may help limit the ability of an attacker to leverage one vuln into compromising the entire system. But if the original attack was important enough, that's cold comfort.


OpenBSD? So lower scalability, limited hardware support, less features and a culture that screams "screw you" at anyone who doesn't think their world view is the only One True Way. Yeah...that'd be awesome. I mean, I'm as skeptical of Rust as anyone who's been around for more than a decade, but seriously.


It seems like this isn’t actionable for me - I don’t have much sway over people’s choice of install. Given this, I think my best course of action are to push for regulation, or for standards bodies to accelerate the transition to memory safe languages.

I don’t think it was your intention, but what you just said makes me want to applaud more heavy-handed efforts to make the switch away from C/C++.


the many places that have my social security number

So COBOL everywhere it is. Let it be written, let it be done.


Actually it isn't susceptible to C's security flaws, and is a compiled language, with relatively good performance. :)


I doubt many C devs would be doing fine coding under the same level of quality expected by NASA / JPL programming standards and security validation.


How is this relevant to parent comment?


The C code that went into the Curiosity rover was quite expensive.


I assume you are still programming in COBOL?


Just like C, COBOL will always be with us.

> According to research, up to 850 billion lines of COBOL code are currently running in nearly 30,000 organizations, typically in critical production environments. 90 percent of Fortune 500 companies rely on it. Never has there been this much COBOL in circulation and the volume is only likely to increase for the foreseeable future.

https://www.chrly.pt/en/2023/06/14/cobol-the-immortal-langua...


It's not what you program in that matters—it's how you test and ensure quality results.


That's stupid the language you write in has a huge effect on how you test and ensure quality results. They aren't separate things.

E.g. at one end of the spectrum you have Python where you have to write explicit tests for typos and type errors.

At the other end of the spectrum you have formal verification languages like Dafny that may not require any tests to be written.

Rust is somewhere in-between. It has a very strong type system and lots of features that make memory errors and business errors less likely than in most other languages. You still need some tests, but not as many as with C/C++, Python, JavaScript, etc.


I like that Rust tests my code as I write it.


Looks for lollipop...


The amount of budget and time you have for the all project is finished, and in practice it's much easier for management to skip testing and QA than to reduce the scope of the project / the amount of features.hence the terrible quality that's plaguing this entire industry.


It's really hard to test for security.

It's much more feasibly to be secure by construction.


Besides LLVM, there's been progress for a GCC backend, and in google summer of code, a suggested project is a c backend, so that all c compilers may be leveraged.


If these architectures can't muster enough manpower to keep up with modern toolchains then they are living on borrowed time. Maintainers of active, modern development projects have a limited tolerance for anachronism before they say "get a modern toolchain up and running or get left behind, we're sick and tired of C89".


I feel like that might leave embedded devices without an upgrade path, and those are the devices that needs to longest "warning". So yes, borrowed time, but that might be a decade.

That no to say that Rust shouldn't be considered, but maybe initially for new development or selective rewrites. Some of the mentioned, like nscd or devd in particular, shouldn't be that high on the list. The ZFSd should be fairly safe, as that's mainly needed on the larger platforms.


If those devices really need updates then the vendor can fork BSD and do the updates they need. It's not like the existing code will stop working on them.

This is also why we LTS versions.


I feel like those are the kinds of devices that never get manufacturer updates anyway. And even if they did, the manufacturer likely is no longer supporting them.

Sure, it's nice to be able to tinker and hack to see if you can upgrade them yourselves, but is it worth maintaining architecture support for that kind of use case? Not asserting that is definitely not, but I think it's worth considering.


If by "modern" you mean "LLVM" then I'm sure the chip vendors will get right on it when they have a GCC backend that works and all of their customers use it.


There is a Rust front-end for GCC that is under active development [1]. If the chip vendors are not willing to develop and upstream a LLVM back-end then they can start contributing to it as an alternative.

[1] https://rust-gcc.github.io/


> If the chip vendors are not willing to develop and upstream a LLVM back-end

oh, my sweet summer child...


You've got the prioritization backwards


What if Rust compiled to C? Wouldn’t that be a good way to support long tail platforms with low effort?


Not necessarily. C isn't a great language to target, since it's full of fun undefined behavior quirks that you will trip over if you look at it slightly cross-eyed. And part of the problem with the long tail platforms is that they can have issues that you don't expect (e.g., function pointers and data pointers might have different representation!).

So the main set of platforms you're looking at are ones that are functional enough to have modern, stable C compilers, aren't too quirky that reasonably portable C code would "just" work, and yet ones that you don't already have support for in Rust. Outside of the embedded space, there's like... fewer than 5 architectures left, the most notable of which probably being Alpha.


[flagged]


Please don't do this here, even if another comment is annoying.


You go to parties where people are passionate about 32-bit PowerPC?

... can you invite me? This sounds great.


They might be Amigans which seems like a pretty bad outcome. Look forward to an hour or more of someone who is enthusiastically wrong about a broad range of topics and has been scammed for thousands of dollars without learning a thing from the experience. Oh the new one is faster and cheaper, but you had to get in early to lock in the price? And the delays have really only been a couple of years? Right, yes...


Ha what a bunch of idiots (he says, typing this on his 40% ortholinear mechanical keyboard with two stage spring switches and POM blank keycaps).


There's always the mrustc[1] compiler that compiles Rust to C source files. So any platform that can compile C, can also compile Rust (with caveats of course).

Of course, this only means we could, it doesn't necessarily mean we should.

[1]: https://github.com/thepowersgang/mrustc


My first thought was that rust doesn't target as many platforms as FreeBSD (at least not well), but looking at https://www.freebsd.org/platforms/ apparently the answer is that FreeBSD doesn't support many platforms anymore so I guess that's no longer a problem.


Yeah, but Rust tier 1 is only x86, x86_64, and arm64. And only Linux. That excludes MIPS, PPC, and arm32, all of which FreeBSD continues to support to varying degrees. x86_64-FreeBSD is a Rust tier 2 "it might work" target, as are arm6/7 and PPC. MIPS is Rust tier 3 "we don't build for it or test on it."


My understanding of the tiers of support is based on the level of commitment from the community. That is, if the FreeBSD folks wanted to make it a Tier 1 target, they can, “If running the testsuite requires additional infrastructure (such as physical systems running the target), the target maintainers must arrange to provide such resources to the Rust project, to the satisfaction and approval of the Rust infrastructure team.” — https://doc.rust-lang.org/nightly/rustc/target-tier-policy.h...

This seems very much within the realm of the FreeBSD’s capabilities.


I don't think FreeBSD has the resources (money/hardware/volunteer hours) or interest in providing that level of support.


Surely that's not set in stone right? Like FreeBSD could contribute money & resources to hook up CI machines to make it a tier 1 target?


I don't believe FreeBSD has the money, resources, or (sufficient) interest as a project to do so for the foreseeable future.


From that link, it looks like FreeBSD is beginning to phase out MIPS and PPC entirely, and 32-bit ARM is nearing phase-out. It seems entirely reasonable that over the next few years it takes to integrate a Rust core that the "blessed" architectures of both projects will be aligned


FreeBSD can't really be said to support native-hardware PPC. Also don't forget riscv. Which it also doesn't really support in native hardware.


You may have been thinking of NetBSD. NetBSD prides itself on a very broad platform support.


Maybe in the 1990s. Now, try getting it running even on a network edge platform like those from Netgate. NetBSD's hardware support is singularly unstable and unusable.

Most new platforms port to Linux, commit drivers to the Linux kernel, and ignore the other platforms. The other platforms don't really seem to bother anymore, unfortunately. Things have bit-rotted to such an extent that FS will destroy large amounts of data and.. nobody seems to notice. Kernel panic reports are ignored. Debuggers fail to set functional breakpoints on native hardware. CPU quirks that need workaround to prevent panics are never committed.

Meanwhile, developing this kind of expertise is about as far from the minds of younger experimenters and hackers now as baking cakes and permaculture gardening were from the 00s hardware hackers decades ago. Not only is it far from the minds of younger experimenters, but even attempting to develop it hits a hard wall of hardcore, draconian behavioural purists, secops fashionistas who deride essentially any burgeoning attempts at writing drivers, and language revolutionaries who rage extensively at people for writing any new code in any language but their own favourite.

The situation is pretty harsh and it's likely not going to get any better anytime soon.


No, I meant FreeBSD, though NetBSD is (much) further on the same spectrum. If I read that Darwin or NT were looking at using Rust, I'd figure that was easy enough; they more or less only target x86 and ARM, which are mostly well-covered by Rust. If NetBSD said they were moving to Rust... I dunno, I'd assume that either Rust had really changed their approach to platform support, or that NetBSD as I knew it had ceased to exist. OpenBSD is actually also on that far end of the spectrum, because they care even more about self-hosting, which means that the inability of rustc to actually run (or at least self-host) on 32-bit x86 is a hard blocker. FreeBSD is in the middle; I knew they don't intend to hit as many hardware platforms as their siblings, but I still thought they had broader coverage than rustc. And (per the page I linked) they used to, but as of the latest releases they've been really cutting down their targets. Which... I dunno, it's practical, but still sad. I guess there's at least still OpenBSD and NetBSD to cover portability.


Darwin isn't going to do Rust. Apple's plan is that Swift can be made to do everything necessary for their operating system. Since Apple are bad at doing more than one thing, they've settled on the idea of a single successor language, chosen under advice but by senior management. So, Swift. Unless it proves impossible to use Swift (and I doubt it) that's what they'll do.

For everything above the line, Swift is definitely viable today. Expect shiny new stuff from Apple to be Swift first, or even sometimes Swift only. If you're an Apple First developer, you should learn Swift, or you are going to be relegated to maintaining legacy software in the next maybe 3-5 years.

Microsoft is already solidly on the Rust bandwagon. So yes, Rust for NT is very possible. Unlike Apple though the Microsoft corporation has always been able to do a bunch of things at once, even if it doesn't always do them all well -- it doesn't need a singular focus to achieve success. So don't expect Microsoft to magically pull effort off C++ and .NET to do more Rust.


> Since Apple are bad at doing more than one thing, they've settled on the idea of a single successor language, chosen under advice but by senior management. So, Swift.

Apple has been using Rust for years, and I'm not aware of any decisions to move away from that, though given how secretive they are, I guess that could be a possibility.

> So yes, Rust for NT is very possible.

Rust is already being shipped (in preview) in Windows' kernel.


Apple's John McCall makes a picture of where they are going with Swift in

"Introducing a Memory-Safe Successor Language in Large C++ Code Bases"

https://www.youtube.com/watch?v=lgivCGdmFrw


Of course Apple continues to invest into Swift, making it better and writing more code in it. There's no doubt about that.

This is an hour long talk. I don't see anything in the slides that indicates that Apple management has decreed that Swift is the sole successor language to C++, forsaking all others, and winding down their Rust codebases. Could you help me find out where that is in this talk?


There are zero references to Rust on that talk.

It is all about C, C++, Objective-C and how Apple is replacing them with Swift.

Rust isn't even shown on languages in use at Apple, https://youtu.be/lgivCGdmFrw?t=284

As for tracking down the exact minutes of each Swift reference, maybe I will try to find some time on my side to prove me right on the Internet.


What I am saying is that you aren't wrong, just that it comes across as a bit of a non-sequitur. The comment I was replying to says that Swift is the only language for the future. I am pushing back about that and that only. Of course they're not abandoning Swift. Of course they're moving away (in many cases) from C and C++. That doesn't imply that Swift is the only tool they will use, or that they're reversing course from the codebases they've already ported to Rust.


So I got some time to go through the video,

- Overview of C, C++, Objective-C and Objective-C++ history on Apple platforms

From https://youtu.be/lgivCGdmFrw?t=169 to https://youtu.be/lgivCGdmFrw?t=306

- How Swift fits into the picture

https://youtu.be/lgivCGdmFrw?t=317

Key statements.

"Apple is very serious making Swift viable anywhere on this chart..."

Meaning a chart showing "UI Apps, Portable utililities, Platform libraries, Portable libraries, Kernel and below."

"...that is because we feel we need a successor language anywhere on this chart, so we are putting Swift at the kernel and below, as well as, platform libraries, and not just UI application, and we think it is a very important future for the language, we are very commited to it"

Up to https://youtu.be/lgivCGdmFrw?t=352

- Basic Expectations

"We need to focus on adding one sucessor language"

"Every language we add comes with extra complexity, in terms of tooling, XCode support, build system support and so on, as well as, language problems making them interoperate"

"We have four precessor languages, we don't want four sucessor languages"

"Should be accessible as first language, for people coming into our platform"

From https://youtu.be/lgivCGdmFrw?t=360 to https://youtu.be/lgivCGdmFrw?t=411

"At the same time, if we want to make it usable in kernel, we need to provide enough control to make it usable in such environments"

"In particular that means being able to scale down to a minimal runtime"

From https://youtu.be/lgivCGdmFrw?t=420 to https://youtu.be/lgivCGdmFrw?t=493

- Problems with C

https://youtu.be/lgivCGdmFrw?t=493

- Overview of Swift

"So we feel pretty strongly, obviously at Apple our sucessor language is Swift and I am here to talk about features of Swift, both to try to sell you on to it, but also to talk about the things we think are pretty necessary and the ways in which a programming language can support, you know, clear code, safer and more correct code."

"Like I said before, Apple has always intended for Swift to be a sucessor language for all of our predecessors, from the top to the bottom of our stack, accessible to novices, powerful enough for experts, it is real a tall order.

From https://youtu.be/lgivCGdmFrw?t=1996 to https://youtu.be/lgivCGdmFrw?t=2042

Quite clear that Swift is the future and zero mentions of Rust.


On what concerns XBox there is little Rust love on Microsoft's side they are all about C++ and COM, and even on Windows, there are only some little experiements ongoing like the GDI regions rewrite that in now on Windows 11.

It remains to be seen if Rust/WinRT will ever take off, given the mess that the same team has done with C++/WinRT, now in maintenance.

.NET based GUI frameworks seem to have won to that front, no wonder given how bad the C++/WinRT experience end up being, and Rust/WinRT is years away to achieve parity with C++/WinRT, let alone what .NET GUI frameworks can offer today in ecosystem, and GUI components.

Where Microsoft is going big on Rust, is Azure, where Rust is now the official systems language for new development on use cases where managed compiled languages aren't a fit.

This was announced at Prossimo's conference in memory safety systems, by David Weston, the vice president of OS security at Microsoft.

https://twitter.com/dwizzzleMSFT/status/1720134540822520268?...


Apple is juggling Swift and bounds-checked C together just fine last I checked.


Apple's John McCall makes a picture of where they are going with Swift in

"Introducing a Memory-Safe Successor Language in Large C++ Code Bases"

https://www.youtube.com/watch?v=lgivCGdmFrw


> fusefs tests. Absolutely impossible to do in C. I considered Rust, but went with C++ so they could live in base. They are too closely coupled to fusefs(5) to live out-of-tree.

Can anyone comment on why this is impossible in C?


"Impossible" is mild hyperbole. Googletest makes it relatively easy to structure complicated mocked tests in a way that is verbose but not impossible in C.


Not impossible, but a big pain. vtables can be done by hand, but C++ does that for you. I don't know rust or the problem they are talking about, but I believe something like that.


The OP has since elaborated:

> I don't think anybody has claimed this yet. But I _have_ made a similar claim, that some things can't be written in C. I'll elaborate on the project that started this thread: the fusefs test suite. When I designed the fusefs test suite, I based it around the priniciple of Mocking. Each test case has a client thread that does normal file system access, and a server thread that implements a fuse file server. But it isn't a full implementation of a fuse file server; it's just a shim around a mock object. For each test case, the file server's behavior is programmed with expectations. The mocking technique is so limited and awkward to use in C that almost nobody bothers. Just compare the documentation for CMockery (C) with Mockall (Rust). C++'s Googlemock is somewhere in between.

https://lists.freebsd.org/archives/freebsd-hackers/2024-Janu...


Mocking is a horrible principle. It is probably the worst of the various types of test doubles, in terms of the kind of test design they imply. Software engineering would be significantly better off, IMO, if mocking were so awkward that no one bothers to do it, ever, in any language.


I don't fully agree but what I will say is that I perceive mocking to be not that easy or good in Rust, so it is surprising to me to see it cited positively.


Am I the only one just seeing a blank page? Proxying via archive.is did not help.

Edit: after some googling I found https://lists.freebsd.org/archives/freebsd-hackers/2024-Janu... but I couldn't read the whole thread at once


It would be a huge mistake for FreeBSD to adopt Rust in base at this stage, and would likely fracture whatever cohesion exists amongst the current team; it would be "emacs vs. vi" all over again, except worse; it would be that those using emacs wouldn't be able to easily read vi-created documents, and vice versa...

That the very first thing to do is have to fix the compiler and build environment, and only then start to actually use it, is an additional complication.


Perhaps that will bring FreeBSD from Tier 2 to Tier 1 of Rust support, if they cooperate with the upstream?

https://doc.rust-lang.org/nightly/rustc/platform-support.htm...


I'm all for replacing C++ with Rust in the base system. Next step would be to move OpenSSL to ports, [with alternative libreSSL based ports tree available] and use rustls for fetch and friends.


Archive Link: http://web.archive.org/web/20240121220432/https://mail-archi...

Just in case anybody else can not see the post. I have no idea if the post is hidden, deleted, or if the server is overloaded.


FreeBSD bug 276716 – mail-archive.freebsd.org permalink failures

<https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=276716>


Reading through the list it looks like it’s not the kernel that’s being discussed, and this comment implies to me that it’s after much of the C system is built, “ imp suggested adding an additional step after buildworld for stuff that requires an external toolchain”. It’s been a while since I’ve worked with FreeBSD, but I think buildworld includes linking, which would imply to me that you couldn’t link Rust into portions of the system in that stage?


I think the idea is you would just move anything depending on Rust to the later stage.


Pity the heading/topic is not like that:

- The Case for Rust in the FreeBSD Base System

Most Linux folks are not aware of what 'base system' means - and that its related to FreeBSD.

About the Rust inclusion - I would include it - and would add these targets:

    # make buildworld (without Rust)
    # make rust (like Rush without 'buildworld')
    # make buildworldrust ('buildworld' + Rust)
Regards.


That would be amazing :D

I run FreeBSD on my servers and use scripts to manage jails and send and receive ZFS snapshots between hosts.

I've been wanting to write some more robust tools of my own for those things, than the scripts I have now, and my favourite programming language is Rust!


Can't you do that now? The article lists ports tools doing those things already


Sure I can but Rust in the base system would provide:

- A stable target, and

- Lots of FreeBSD specific Rust code to read from expert FreeBSD programmers, as guidance

- Probably better ability to build ISOs of my own that include the base system and my jail and ZFS management Rust programs, so that I can install servers from that ready-made ISO and have less post-install work to do


In terms of server install ISOs, I can highly recommend mfsBSD, and also cloud-init to trigger post-install setup


I thought the plan was to separate the toolchain from world. Building LLVM twice will suck.


I am not familiar with FreeBSD's development model. What constitutes the "base system"?


The stuff that’s included in the system after a standard install, before you install any additional stuff. It’s all in one repository and it’s maintained by the FreeBSD project. Stuff like the kernel, libc, utils, dtrace, compilers needed to build base, ... Basically everything that’s needed for a usable system. It’s updated all together through binary patches, not separately through packages like on Linux. When you want something more, you either compile it from source using Makefiles stored in a repository called “ports” (the Makefiles download the tarballs with source code, verify their checksums, build them etc), or you install pre-built packages using the pkg package manager.

The FreeBSD project tends to like to slim the base system down. E.g. some years ago they removed Perl from the base system. So out-of-the-box the only scripting language that’s available is shell. In contrast, OpenBSD has more stuff in its base system and on the subject of Perl they doubled down on it (their package manager e.g. is written in Perl). It’s also visible, when you download the base system repos for each of them and run tokei to find out the numbers of LOC. (I don’t remember the numbers off the top of my head.) That said, FreeBSD still includes a full LLVM toolchain due to the rule “base builds base”, and LLVM is... a lot. It’s the biggest source of bloat in my jails to be honest. I keep meaning to find out if I can remove it from them.


This is a perfect and concise description.


Not after I added the second paragraph. ;)


Don't forget (f)lua is in base :)


To be fair, for the vast majority of FreeBSD users flua is essentially nonexistent; it was pushed off into /usr/libexec and renamed so that it doesn't get used by consumers of base in such a way that it can't be updated.


The kernel, libc (they tie libc to the kernel unlike Linux), and a standard suite of programs.


Very naive question. What's the main selling point of Rust besides being stably sponsored by Mozilla?


There are two very broad set of features:

1) Memory safety. If you live in the world of kernels and embedded code, your options are mostly C, C++, and (as of just the last few years) Rust. Of those, only Rust reliably prevents memory corruption mistakes like use-after-free.

2) Being a 21st century language. Rust has a lot of features that any new language would be expected to have these days: a unified build system, a library ecosystem that the build sytem knows about, slices over arrays and vectors, UTF-8 strings, convenient ways to de/serialize JSON, something like async/await, etc. This makes it competitive with languages like Java and Python for doing "everyday stuff", where realistically ~no one would use C. The main downside of Rust in a Java/Python sort of context is that the learning curve is a lot steeper.

A couple other notes:

- Some of nice 21st century features (like JSON) go away when you're writing embedded/kernel code, but others still work. Embedded ("no_std") Rust still has enums, error handling, slices, iterators, and sometimes even async/await. Those quality-of-life features are hard to replicate in C, even if you believe your code is 100% bug free :)

- If you know you're going to be writing multithreaded code, Rust's thread safety features are really unmatched. A lot of the same machinery that gets used for memory safety also turns out to be useful for thread safety. Libraries like Rayon make it surprisingly convenient to write multithreaded code, while also catching a huge percentage of mistakes at compile time. (Deadlocks are still possible though.)


> Memory safety

Another very naive question. Are memory safety concerns from a cybersecurity standpoint or from less-dev error standpoint?


Microsoft, Google, and other companies have all determined that about 70% of CVEs are memory-related. Here's the US government's take: https://www.cisa.gov/news-events/news/urgent-need-memory-saf...

These memory-related exploits disappear with Rust aside from in "unsafe" blocks (possibly the worst named keyword in any language... it should have been called "trusted"), and that means you have a smaller and more easily auditable attack surface for these types of memory-related exploits. Some code (e.g., FFI) can't be verified as memory-safe by the Rust compiler at compilation time so "unsafe" is there as an escape hatch. I've written a bunch of Rust since 2014 building things like webservers, realtime futures processing algorithms, MEV bots, etc., and I've only had to use "unsafe" a few times.

I've also worked in security on products at Fortune 100 companies, and C is a constant nightmare for CVEs. I think I have PTSD from having to update libcurl. The more software we have written in memory safe languages, the better off we all are.


Just to avoid any “cyclist rides more aggressively when wearing helmet” type behaviour:

It’s probably worth nothing that that vast majority of, and of large scale attacks, is basic shit that has nothing to do with memory safety.

There’s benefit to memory safety, but just cause you’re wearing a helmet doesn’t mean you’re completely safe.

Additionally, it’s not Google overall, but chromium project that find this, as well as not Microsoft overall, but specifically Windows. These are two projects that will naturally see a much higher rate of memory safety issues.


> not Microsoft overall, but specifically Windows

This isn't the case: https://msrc.microsoft.com/blog/2019/07/a-proactive-approach...

> Since 2004, the Microsoft Security Response Centre (MSRC) has triaged every reported Microsoft security vulnerability.

They've never qualified it as Windows only, to my knowledge.


Both for sure, and which one is a bigger deal depends a lot on context.

Cybersecurity issues make Rust a good choice for writing parsers for example. File format parsers handle scary data from the internet (JPEG, X.509, etc), and those often contain addresses and offsets that turn into raw pointers in the implementation, so they're a common source of security bugs. At the same time, they're usually isolated behind a reasonably tight API, so it can be practical to rewrite them in Rust even when all the calling code is still C or C++ or even Python.

On the other hand, fewer-mistakes-sucking-up-dev-time is an especially big deal in multithreaded code. There was a story from Mozilla about how they'd tried to add threading to part of Firefox (I think it might've been the CSS engine?) and failed multiple times, but then they succeeded in Rust. Threading bugs tend to be painful to reproduce, and Rust's compile-time checks are extremely valuable there.


Both. On the one hand, what Rust essentially forces you to do is just to program according to proper RAII principles that an experienced C++ programmer would already know and should already be using (especially once polonius lands), it's just better at checking failure to do so than any sanitizer or linter could ever be, so it's a way to avoid having to deal with annoying, hard to track down memory bugs. And in fact, the greater confidence static lifetime guarantees give you allows you to do things like using move semantics more where C++ programmers would have to use copies out of defensive programming. That's predominantly why I personally use it, as far as memory safety goes. On the other hand, [around 60-70% of serious security bugs have been proven to be caused by memory safety across many different projects](https://alexgaynor.net/2020/may/27/science-on-memory-unsafet...) so if you do care about security in what you're doing, it's a boon there too.


Mostly from a less-dev error standpoint but I think you gain in cybersecurity as well, as the language won't let you write code that accesses memory in places it's not supposed to.


It's mostly from the cybersecurity standpoint actually, at least for large projects / companies. MS, Chromium, Project Zero, Mozilla, have pretty consistently found that north of 70% of vulnerabilities were rooted in memory safety.

The dev-error is broader language guarantees, which dovetail into memory safety but are useful on their own e.g. data race safety, rich type system, ...


Both, and they're related in the sense that software errors can become exploitable vulnerabilities. This is a handy summary by the NSA: https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI...


Tomato, tomato.


I can't give you just one selling point, because Rust has two main competitive features, and it's hard for me to say which one is enticing FreeBSD more here:

1. Rust has a more modern sense of computer primitives than C does. For example, C has the char-short-int-long-long long set of types which correspond to 8, 16, 32, and 64 bit integers in practice (and yes, 5 types for 4 sizes), whereas Rust has u8/u16/u32/u64. Rust also has a builtin slice type, which is a desperately needed notion of pointer + size of array, and C's lack of such type has proven to be the source of much malware. The standard library is also somewhat richer too, you have better support for things like threads or networking than C/C++ does. But note that Rust is still like C in that it has a very thin runtime layer, and can also go a step further and have "no" standard library at all, which is necessary in several contexts.

2. The borrow checker. Effectively, use-after-free (or any other lifetime issue) vulnerabilities become compiler errors, and even many kinds of data races are also turned into compiler errors. Also it can do things like make iterator invalidation issues a compiler error as well.


In short: the type system is significantly more expressive and encourages domain modeling that tends to lead to fewer errors; "if the compiler says it's OK, it'll be OK" isn't strictly true but it's often pretty close. Rust also offers stronger guarantees around memory safety than C, as well as C++ as commonly practiced. (Which is to say, you can write very memory-safe C++, but you will work at it.)


One of the biggest things about Rust for me is that it's essentially Prometheus, bringing the fire of modern languages and more advances PL theory to systems programming, which imo is sorely needed. We don't need a 10% better C or C++, we need a huge jump for the field. Rust I think does this. They have:

1. A type system that's deeply inspired by OCaml, a language that's designed and used by a lot of programming language research people and is widely praised (just look at how every other language — C#, Java, Kotlin — is suddenly trying to pile half baked imitations of ML features like ADTs and deep pattern matching onto their existing OOP type systems), except they've both imemented the type system correctly and fully, and also filed off all the warts and awkward features, and replaced OCaml's verbose and underpowered first class module system with Haskell style type classes

2. got amazing, highly flexible and generalized iterator and monad support (you can use iterator methods on monads), basically second only to Haskell itself, that compiles down to the equivalent of hand written assembly code loops

3. an error handling system using monads that neatly sidesteps the issues with both traditional C style error handling and exceptions that combines with point two in an exponential curve of awesomeness for error handling

4. hygienic (from Racket) and procedural (eg Common Lisp) macros

5. And finally ofc their statuc memory safety and race condition safety, which is based on linear types ala Idris.

But most importantly, Rust's designers seem to IMO have carefully picked only the advanced programming language features that tend to make your code clearer as well as more correct, and help you model problems at the right level of abstraction to be intuitive, and also only features that can be implemented in a way that is as performant as the equivalent C++ code, roughly speaking at least. They also seem to have been very careful with how they integrate and implement everything in order to uphold those goals.

So you get to have 90% of the power of a language like Haskell, in a language that performs like, and has the low level capabilities of, C++, with the extra benefit of — for instance — less dogmatic puritanism and more deterministic and comprehensible performance and execution properties then Haskell, and less Lovecraftian horror full of surprise gotchas than C++.

It's kind of like the ultimate pragmatic language for someone like me who has gone deep into pure functional languages and other esoteric languages and wants to have as much as of that goodness as is practical.


Errata:

Second only in monad support to Haskell and equivalently powerful languages e.g. OCaml and Scala, but much better than mainstream languages, I should've said.

Also, I should have said that Rust helps with data races not races in general.

Also, I should've said Rust's trait system was more practically powerful / usable that OCaml's first class modules and potentially more powerful overall but not quite there yet.

This is what comes with writing enthusiastically, while suffering from a headache and brain fog. I swear I'm not an idiot and know my pure functional languages!


> OCaml's verbose and underpowered first class module system

It's definitely verbose, but underpowered? Modules are just as powerful as Haskell's typeclasses (and therefore more powerful than Rust's).


It's certainly debatable. This is just my opinion.

In my opinion they are, because any group of types and functions that implements a module signature must be wrapped up into a module that satisfies that signature at the point of use of any value that needs to satisfy that module signature, instead of a type just satisfying the given signature if the correct functions exist to manipulate it, which means in my opinion there's a lot less flexibility and it works more like constructing a new value of a certain type then it does having constrained parametric polymorphism in the way Haskell does. I think this is why although they technically can be used to imitate rust traits or Haskell type classes and allow a function to polymorphically take any type of that satisfies a certain interface, it isn't in practice used like that almost at all, whereas it absolutely is in Rust and Haskell. Witness for instance how both rust and Haskell have a generic type class for iteration that allows you to take anything that is iterable and use the whole module of functions available for iterables on it, so for instance in Rust you can use many of the same methods on a vector and an array and error checking monads, whereas in ocaml, even though something similar is in principle possible, it's almost never done that I've seen, because you have to essentially declare that I type implements a signature and how it does on every point of use where you want to pass a value of that type into a function that requires something with a certain signature. Instead functions are duplicated between modules for different types, like lists and arrays. Maybe that isn't underpowered per se, but it's certainly a practical consideration in the use of first class modules that mitigates a lot of what they are theoretically capable of that seems in my opinion to fall directly out of the conceptual model of using first class modules to do constrained parametric polymorphism, since values then must become modules.

As for the ability to represent the signature of monads — yes both ocaml and Haskell can currently do that while rust cannot, but there is actually currently active work on an RFC that would rectify that. So I suppose overall you might say that rust's type system is currently less powerful then the other two, but I really don't think that will be true over the long run, and it certainly isn't true of necessity, and rust has a type system with a great many benefits in practical power over OCaml's otherwise, in ways I feel impact day to day use more.


>2. got amazing, highly flexible and generalized iterator and monad support (you can use iterator methods on monads), basically second only to Haskell itself, that compiles down to the equivalent of hand written assembly code loops

As I understand it, Rust lacks do-notation and higher-kinded types, making it hard to have true monads in Rust.

Scala would be the language with monad support comparable to Haskell.


My understanding is that Rust lacks the ability to have a generic Monad abstraction like Haskell and Scala, but that it certainly has monads (e.g Option, Result, Vec, etc). And indeed that even languages like JavaScript have lots of monads (e.g. Promise) it's just that these are likewise not abstractable.

I believe that a monad is basically any container that has both a constructor and a flat_map function (and there may be one other requirement that I've forgotten). The special ability that Haskell has is the ability to write code that is generic over any such container.


> (and there may be one other requirement that I've forgotten)

`map: forall a b . (a -> b) => (m a -> m b)` and `pure: forall a . a -> m a`, plus some (mostly very natural) compatibility conditions between the three: `flatMap(pure)` does nothing, `map` takes the identity to the identity, etc.


I actually had this objection in mind when I wrote that, so thank you for giving me the opportunity to expand on what I meant a little bit.

Yes, it is very much true that rust cannot yet represent monads as type classes directly, since it does not have any form of higher kinded types yet — which is the reason why I said second only to Haskell. If it could represent monads directly, than I would have placed it equal to Haskell — as I would have placed scala!

But I do think it is important to highlight that it does have pervasive useful monad use in the language, and an interface that allows you to use a very large common set of powerful transformations on them via the iterator trait, and it uses the monads that exist in the language and the ability to use that trait on any monad a lot to increase the power of the language in a way no other language besides ones with superior monad support does that I know of. So I would argue that while it is still second to Haskell, it is still far above almost any other language not equal to Haskell in this respect. Which is what I meant by saying second only to haskell!

Also, HKTs are something that the rust team seems to be very actively looking to rectify with an in progress implementation currently available in nightly, so that won't be true for very long.


My point here wasn't to say that Rust is as good or powerful as the advanced pure functional languages like Haskell and Ocaml and Idris, but that it's starting the process of properly bringing their power and features to the systems programming world, which I think is what's important.


By the way it's not "race condition" safety. Race conditions are a completely normal part of our world and so Rust can't magically fix race conditions. Bob's going to shred all "10+ year old" paper records "after lunch" and Hannah needs the paper customer list from 2003 for the 2:30pm meeting? Well that's a race, good luck, Rust can't help. However, (safe) Rust can eliminate data races, a very weird special case caused by the difference between how you imagine the computer works and how it actually works.

A data race goes like this: At least two simultaneous execution contexts (maybe threads for example) are looking at the same object X and at least one of them changes it, but there is no particular order of these events agreed between these contexts.

In your head, even with parallel computing everything seems to happen in some sort of global order. A happens before B, or B happens before A. This is called Sequential Consistency, and it's a lie, the machine doesn't actually work like that, but humans can't really understand non-trivial software without this lie, so, all our high level software (and when I say "High level" I mean like the C Programming Language) pretends sequential consistency is always preserved and goes to some lengths to achieve that.

In Rust you can go about your business. (Safe) Rust promises this is true and it'll make damn sure. But in many languages like C or C++, actually you can very easily inadvertently construct a data race, revealing that it was a lie and if you do so all bets are off. Since you probably can't reason about your program's behaviour anyway, they figure "fuck it" and that's Undefined Behaviour.

Bonus round for languages which do better than most: Go says if you race a trivial object like an integer, you lose Sequential Consistency but this isn't automatically UB. Complex races are UB.

Java says races are never UB, but they do lose Sequential Consistency. Your Java Program is now very, very difficult to understand, but it's not nonsense.

OCaml goes furthest, it says your race isn't UB and it offers very tight constraints on what's wrong. OCaml's work on this is relatively new, so it may be a while before we're confident whether this is a manageable situation normal humans (well OCaml programmers) can handle.


> However, (safe) Rust can eliminate data races,

Yes, thank you for pointing that out, ive had a bad headache for most of the day and knew I was saying the wrong term when I wrote it, but couldn't for the life of me remember what the right one was! And yeah I'm pretty familiar with this, although I wasn't aware of OCaml's strides


Rust‘s type system prevents memory safety bugs because it reasons about object lifetimes statically. At the same time rust allows you to write systems code on bare metal.


> it reasons about object lifetimes statically.

How does that differ from RAII?

I think i misunderstand you or lack knowledge, because this sounds exactly like RAII.

I know that rust has major compile time checks, but saying that the difference is that it reason about life time as difference to c++ is misleading. I think the major point of c++ compared to c is that c++ "reason about object lifetime statically" with deconstructors and RAII. And saying that rust do this and implying c++ don't is misleading.


Rust and C++ work very similarly with respect to objects you own. In both languages they get cleaned up by a destructor when they go out of scope. However, Rust also has a lot of language features that deal with objects you borrow, i.e. have a pointer to. In C++ you might make a "use-after-free" mistake and hold a pointer to an object that's already been destructed, which can lead to all sorts of memory corruption. In Rust, the same mistake almost always results in a compile-time error. The part of the compiler that enforces all this is called the "borrow checker", and getting used to the borrow checker's rules is a big part of Rust's learning curve.

One thing C++ programmers might be interested to learn, is that this doesn't only apply to simple variables and references; it also applies to library data structures and their methods. The Rust compiler doesn't really "know" what the .clear() method on a Vec does, but it knows enough to prevent you from calling that method while you're holding references to the Vec's elements.


> getting used to the borrow checker's rules is a big part of Rust's learning curve.

It’s also a big part of C and C++’s learning curves, it’s just that the compiler doesn’t tell you about it; you’re being taught by segfaults and silent memory corruption instead.


Very true. My hot take on this is, if you want to learn C or C++ "properly" (not just well enough to get your homework done, but well enough to write medium-size programs that pass ASan/UBSan/TSan), the fastest way is to learn Rust first. This is emphatically not because Rust is quick to learn, but rather because ownership and borrowing discipline takes years of mentorship to absorb in C and C++, and plenty of career programmers never really get it.


> Rust and C++ work very similarly with respect to objects you own.

There is one major difference. In Rust you can memcpy objects you own to a different base address and they will still work, unless they're pointed at by a Pin<> type (as such, code that requires objects to stay put in memory must take a Pin<> reference. This arrangement may potentially be replaced by a special "?Move" trait in future editions of Rust). C++ pins all objects by default and allows objects to have custom "move" constructors, to sort of enable them to be moved elsewhere.

In C++, objects that get "moved" must leave behind something that can be destructed cleanly; Rust has no such limitation, at least wrt. ordinary moves. Arguably the closest thing it has to a C++ move is the .take() pattern, which leaves a default-constructed object behind. But this is rarely used.

The general tradeoff is that the Rust pattern memcpy's compound objects more often, but has less gratuitous use of the heap and less pointer chasing compared to idiomatic C/C++. This is a valid choice once one has the compiler support that Rust provides.


If anyone's trying to follow along but wondering what the heck we're talking about, I have a video about this :) https://youtu.be/IPmRDS0OSxM?t=3019


> However, Rust also has a lot of language features that deal with objects you borrow

An other major safety difference is that Rust uses destructive moves, once a binding is moved-from it becomes invalid / inaccessible (and it won't be destroyed).

In C++, a moved-from object is in a "valid but unspecified state", so it must be destructible (because destructors always run) but any interaction with the object other than destruction may be UB, and the compiler won't tell you (in the same way it won't tell you about borrowing issues whether it's UAF, invalidation, ...).


Yeah if you never use a pointer/reference/iterator, the guarantees are quite similar. The rust compiler however also checks for use after free and iterator invalidation bugs. In addition it makes it harder to shoot yourself in the foot in concurrent code because you can’t have multiple mutable references to an object.


I don’t think Mozilla has had any major sponsorship role for a few years now?


> https://internals.rust-lang.org/t/mozilla-is-hiring-for-the-...

It seems that some Rust folks are still on Mozilla payroll.


That post is from 2019, the layoffs of the teams were in 2020.

Mozilla is still a member of the foundation, so they do support it in that sense, but they are one of many companies that do so.


The build tools are incredible. That's the main reason many people love Rust. For kernel dev however, the memory safety is a big win.


Statically checked memory management

Advanced typing

Build tools


The language features.


You've got to be trolling


Ironic since I’ve been thinking:

FreeBSD : Go :: Linux : Rust


The Go/Rust rivalry is just a peanut gallery meme. It’s never been a real thing IMO.


Go is what I reach for if my other options might be Java or Python but I don’t want deployment and support to be really stupid and awful.

Rust’s close alternative is C++. Maybe also C? I don’t know if Rust can fill its niche of ultra-portable libraries that are relatively easy to import and use in tons and tons of other languages & systems.


Other than LLVM portability concerns, I think Rust can for sure replace C/C++ libraries (I'm talking DLLs etc).

Sure, there will be a small C ABI shim but the developer experience writing in Rust I think is worth it.

Also, nowadays whenever I want to write a fast Python extension, I don't think twice before using pyo3, super simple to write and build.


Yeah, go competes with Java and Python. Rust is in a different class of tools.


I would narrow it even further: Go competes with Java. Their forte is both programming-in-the-large on the backend.

It's much harder to manage a large codebase/application with Python, but it excels at data science and research programming, which Go and Java do not.

(Obviously, there is overlap between all, and you could do anything in any language.)


Can you explain your comment a little more? I don’t understand the relationship between these that you’re suggesting.


Go and FreeBSD share the similarity of a large base system that’s useful out of the box: in go the runtime and large, useful stdlin, in FreeBSD the base system composed of the kernel and standard programs. Both also encourage a certain cultural aesthetics around that base of accepting and going with the flow of the base’s limitations. For FreeBSD, things like composing posixly-correct sh scripts, BSD Makefile stuff. For Go, boilerplate, if err != nil, for a long time “you don’t need generics”.

In contrast, Linux and Rust are both smaller core systems with more exposed complexity, but also require a large user space to make the core useful. Linux is just a kernel so you gotta bring everything else in the OS. Rust you need libraries for things most other languages (including Go) include, like regex, async, etc. However both Linux and Rust have a culture of adapting the system to work exactly how you like, in Linux again you bring everything you want - want systemd? Cool. Don’t want systemd, that’s cool too. In rust, people go absolutely crazy with macros and abstractions and likely it will still be plenty fast at runtime.


FreeBSD and Go are slow to change, extremely hesitant to introduce API changes, and adhere more towards tradition.

Rust and Linux are changing rapidly and aren’t as worried about completely uprooting entire systems. See for example sys v init vs systemd.

Go didn’t get generics until 1.18 and promises backwards compatibility.

In Rust, the popular command line parser Clap completely changed its API between 3 and 4 such that you’ll need to update your code.

As much as I like predictably and simplicity, I think Rust will largely be more successful similar to Linux winning over FreeBSD.


All mainstream languages treat backwards compatibility as paramount at this point, it's table stakes at this point. Rust is no exception.

I will admit that because the library ecosystem in Rust is younger, you do see things like Clap's breaking changes more often than in other languages.




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: