Speculative: Rust for base system components

Eric McCorkle eric at metricspace.net
Mon Dec 31 02:18:40 UTC 2018


Before I begin, I want to be clear that everything here is in the realm
of speculative, long-term discussion.  My goal is to start a
conversation, not to propose anything concrete right now.



I've talked at several conferences about the possibility of bringing the
Rust programming language into the base system, with the intent of
making it a viable implementation language for parts of the base system.
 I believe the potential security and stability benefits of doing this
are *substantial*.  This would obviously be a serious undertaking, but I
think the benefits are worth the cost.  For the rest of this mail, I'll
outline my position and present the important facts that support it.

I of course welcome any discussion, criticism, or input.

= Why Rust? =

Rust is a true systems programming language that incorporates results
from programming language research that took place in the late 90's and
2000's, and can be viewed as a culmination of this work.  (Specifically,
it draws on work on region types as well as substructural types, but
that's its own survey article).

This manifests most clearly in Rust's lifetime type system, which is
able to perform quite sophisticated reasoning about memory allocation
and ownership.  Rust programs do not require you to explicitly manage
memory, but neither do they use garbage collection.  Memory management
is automatically tracked by the lifetime types and allocations/frees are
added during compilation.  Moreover, threaded programs are able to use
the same type system features to track ownership.  This effectively
prevents a large class of memory- and concurrency-related errors *at the
type system level*, resulting in dramatically safer programs.  Rust
provides an "unsafe" language facility for accomplishing low-level
tasks, so you're not prevented from getting things done; however, almost
all programs can be implemented without relying on unsafe, and doing so
eliminates what has probably been the two worst classes of bugs in the
history of computing.

Because this is done at the type system level, it has no cost at
runtime.  This theme of "zero-cost abstractions" runs throughout the
language, which makes it suitable as a replacement for C in the long
term.  It also incorporates features befitting a modern programming
language such as parameterized types (aka generics), pattern-matching,
and trait-based polymorphism.  Finally, it can interface with C/C++
binaries and libraries relatively easily, making it a suitable systems
implementation language.

Because of these benefits, several projects (Mozilla and Tor) have begun
to reimplement their systems using Rust.  Additionally, there is a
master's thesis about writing FreeBSD device drivers using Rust out
there somewhere (forgive me for not chasing it down).

A secondary benefit is that Rust's packaging system, cargo, is built
around a more modern concept of modularity.  This is in line with
FreeBSD's goals of modularizing the base system and reducing redundancy.

= Downsides =

There are a couple of downsides, which I'll outline briefly, and provide
some counterargumentation for them.

* It's a big component

Adding the entire Rust platform would add more to the buildworld time,
which is already quite long due to LLVM.  OTOH, LLVM itself is a big
chunk of the rust build time, and we already build that as part of the
base system now.  Moreover, it stands to reason that the compiler would
end up being the majority of an open-source operating system's build
time, with second place being the kernel itself.  Compilers are an
active area of research with no signs of slowing down, and more hardware
platforms means more backends, which means the compiler ends up growing
over time, while most of the rest of the system doesn't.

* The language is still evolving

While this is true, the language has gotten *way* more mature in the
past year and a half, and I think it's ready to hold up major codebases
and production use, or at the very least it will be by the time we'd be
seriously looking at bringing it in.

* Rust binaries are large

This issue can be avoided with the proper use of build flags.  The
default settings use static linking for everything, and bring in the
entire runtime library (which isn't necessary in most cases).  See this
article:
https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html.
 With LTO, the size can be cut down to that of a C++ binary, and with
dynamic linking, the executable size is comparable to a C program.  If
we were seriously using rust, we would probably change the default flags
to use dynamic linking/LTO by default, in fact.


= Alternatives =

There have been several alternatives that come up when I mention this.
I'll discuss the two big ones: go and C++

== C++ ==

C++ is already in the base system, of course.  It could be brought into
the kernel with some effort and restrictions.  The biggest argument for
Rust over C++ in my view is that Rust is a much simpler, cleaner
language.  C++ at this point is bewilderingly complex as a language, and
has so many bells and whistles that it almost requires an effort to
decide which subset of the language will be used.  This also tends to
slow down efforts to expand the language over time.

Rust by comparison is much leaner.  Its lifetime type system can be
intimidating, but the benefits are well worth getting used to it.  To
sum it up, C++ certainly isn't going anywhere, but I think Rust has a
great deal more vitality as a language.

== Go ==

Go is not really a "systems language" in the sense that C or Rust are.
It isn't a replacement for C so much as a replacement for python.

What's more, it is almost universally disliked by people with a
background in programming languages (I am one of those).  There's a
couple of reasons for this.  First, it omits a number of features that
modern languages *really* should include, parameterized types (generics)
being one of the most glaring.  Beyond that, it completely ignores
anything produced by modern PL research (unlike Rust, which benefits
from that work).  Second, one of its main design parameters was "it
should compile fast".  This as a design constraint basically guarantees
that you can't do anything interesting in compilation, which rules out
both advanced type systems as well as serious optimization.

Unlike Rust, which offers substantial security and stability benefits
through its type system, Go would do little more than just change the
syntax of a bunch of code.  Moreover, it's likely that there would be
performance consequences, given the design constraint of fast compilation.

= Summary =

Rust is a modern systems language with substantial benefits, and is
well-poised to become the heir apparent to C as the dominant systems
language going into the future.  For this reason, I think we should
seriously consider it as a language for the base system at some point in
the future, when the time is right and after sufficient exploration and
experimentation.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: OpenPGP digital signature
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20181230/c47ead1f/attachment.sig>


More information about the freebsd-hackers mailing list