thunk / Rust for the Metal / Why Rust, Down Here

Why Rust, Down Here

M1 ended at the bottom of the software stack: drivers, kernel code, bytes moving over an SPI wire toward a display. Before you can read the code that lives down there, you need the language it is written in. In this course that language is Rust. This module teaches just enough of it to read the low-level code coming in the next three modules.

Start with why the language matters at all. Low-level code manages memory by hand. It asks for bytes, uses them, and gives them back. Three mistakes show up over and over in that kind of code:

In older systems languages, nothing stops you from writing any of these. The program compiles cleanly, ships, and runs. The mistake surfaces later, at runtime, as a crash or as quietly corrupted data. Sometimes it surfaces years later, on a machine you will never see, in a way you cannot reproduce. Whole careers have been spent chasing bugs of exactly this shape.

Rust's bet

Rust makes a different bet: none of these mistakes gets to corrupt a running program. The first and third die at compile time, before the program even exists. The compiler is given enough information about who owns each piece of memory and who is allowed to touch it that it can prove memory is never used after it is given back, and that two threads never write the same bytes at once, or it refuses to build the program. Those bugs never get the chance to run.

The buffer mistake is handled differently, because which position a program reads can depend on input no compiler will ever see. So Rust checks every buffer access as it happens, at runtime, and if the position is past the end it stops the program cold rather than let it read bytes it does not own. A stopped program is loud and easy to find. Quietly corrupted data still cannot ship.

The next two lessons cover the two ideas that make the compile-time proof possible: ownership and borrowing. They are rules you write your code within, and the compiler holds you to them.

No garbage collector

Many languages avoid manual memory mistakes a different way: a garbage collector, a runtime helper that watches memory while the program runs and reclaims pieces once nothing uses them anymore. It works, but it costs. The collector needs processor time, and it pauses the program at moments of its own choosing to do its sweep.

Rust has no garbage collector. Because the compiler already proved who owns what, memory comes back the instant its owner is done with it. Not eventually, not when a collector gets around to it. The same instant, every run, predictably.

Why it fits down here

That predictability is why Rust fits kernels and small machines. A kernel cannot stop for a garbage collection pause while an interrupt is waiting. A small machine driving a display may not have the memory or the processor time a collector demands. Rust gives the control of the old systems languages, with the three classic mistakes moved from runtime to compile time.

This is not a fringe position. The Linux kernel, the same kernel M1 was about, now accepts driver code written in Rust alongside its C.

Key terms

Checks

Answer these to prove the lesson landed. Graded right here; nothing is sent anywhere.

When does Rust catch the mistake of using memory after giving it back?

Rust has no garbage collector. So when does a value's memory come back?

Why does Rust fit kernels and small machines?