why a memory-safe systems language without a garbage collector
/ Rust -> rust /
Suppose you have learned C and met its sharp edges: a pointer used after the memory was freed, a buffer written one byte too far, two pieces of code both freeing the same block. None of these are exotic — they are everyday mistakes, and in C the compiler waves them through. The usual escape is a language with a garbage collector (like Java, Go, or Python), which manages memory for you so you cannot make those mistakes. But a garbage collector runs while your program runs: it periodically pauses to hunt for unused memory, and it adds a runtime cost you do not control. For an operating system kernel, a game engine, or a device driver, those pauses and that overhead can be unacceptable. So for decades the trade seemed forced: either the manual control and speed of C (and its whole family of memory bugs), or the safety of a garbage-collected language (and its runtime cost). Rust exists to refuse that trade.
Rust is a systems programming language — it compiles to native machine code, talks directly to the hardware, has no required runtime sitting underneath, and gives you the same low-level control C does (you still think about the stack, the heap, and where bytes live). What is new is that Rust makes memory safety a property checked at compile time, before the program ever runs, with no garbage collector. The compiler tracks, as you write code, who owns each piece of memory, who is allowed to read or write it, and exactly when it gets freed. If your code could read freed memory, or write past the end of a buffer, or let two threads race on the same data, the program simply does not compile — you get an error, not a crash three weeks later in production. The cost of all this is paid by the programmer at compile time (learning the rules, satisfying the checker), not by the program at run time.
Be honest about the claim, because the honesty is the whole point. Rust does not make bugs impossible. It prevents a specific, important family of bugs — use-after-free, double-free, dangling pointers, buffer overruns, data races — in code written in its safe subset. It does not stop logic errors, it does not stop you from leaking memory on purpose, it does not stop deadlocks, and the moment you step into an unsafe block (which you sometimes must, to talk to hardware or C) you are back to C-like responsibility. Rust is best understood not as magic but as a language that encodes the ownership discipline good C programmers already keep in their heads, and then forces everyone to follow it. The rest of this field unpacks how it does that.
// C: this compiles and may crash, leak, or corrupt silently. char *p = malloc(8); free(p); puts(p); // use-after-free; C says nothing // Rust: the same mistake does not compile. let p = String::from("hi"); drop(p); // value freed here println!("{p}"); // error[E0382]: borrow of moved value: `p`
Same bug, two languages: C compiles it and hopes; Rust refuses to compile it at all.
Memory-safe without a GC is the headline, but the safety guarantee covers safe Rust only. Inside an unsafe block, or across a foreign-function boundary into C, you can still hit undefined behaviour exactly like in C.