Skip to content
Rust logo

Rust

First appeared 2010 (1.0 in 2015) · Graydon Hoare

Memory safety without a garbage collector — the compiler proves your code is sound before it runs.

Overview

Rust is a modern, multi-paradigm systems programming language that focuses on three key principles: safety, speed, and concurrency. Developed initially by Mozilla Research and now maintained by the Rust Foundation, Rust represents a revolutionary approach to systems programming by preventing entire categories of common programming errors at compile time through its innovative ownership system, borrowing rules, and lifetime annotations. The language prevents memory safety bugs like null pointer dereferences, dangling pointers, buffer overflows, use-after-free errors, and data races without requiring a garbage collector or runtime overhead, making it suitable for the most performance-critical applications where every microsecond and every byte of memory matters. Rust achieves memory safety through its unique ownership model, where every value has a single owner, ownership can be transferred (moved), and values can be temporarily borrowed with strict compile-time checks ensuring no data races or memory corruption can occur. This compile-time guarantee of memory safety is Rust's most distinctive feature, eliminating the need for manual memory management while avoiding the performance overhead and unpredictable latency of garbage collection. Rust combines low-level control over system resources, memory layout, and performance characteristics with high-level ergonomics, expressive syntax, and powerful abstractions that make it pleasant and productive to use. The language offers zero-cost abstractions, meaning that high-level features compile down to code as efficient as hand-written low-level code, pattern matching for expressive control flow, a sophisticated type system with algebraic data types and traits for polymorphism, powerful macros for metaprogramming, and excellent error handling through the Result and Option types that make error cases explicit and impossible to ignore. Rust's type system is exceptionally powerful, catching many logical errors at compile time and enabling fearless refactoring where the compiler guides you through changes. The language is designed for building reliable and efficient software across a wide range of domains: operating systems, device drivers, embedded systems, web browsers, game engines, blockchain implementations, command-line tools, web servers, databases, and any application where performance, reliability, and resource efficiency are critical. Rust comes with Cargo, an excellent package manager and build tool that handles dependencies, compilation, testing, documentation generation, and publishing packages to crates.io, the Rust package registry. The language has outstanding tooling including rustfmt for automatic code formatting, clippy for linting and best practices, rust-analyzer for IDE integration, and comprehensive error messages that not only identify problems but often suggest fixes. Rust's community is known for being welcoming, inclusive, and helpful, with extensive documentation, learning resources, and a strong emphasis on mentorship and education. The language has been voted the most loved programming language in Stack Overflow's developer survey for multiple consecutive years, reflecting developers' appreciation for its design, safety guarantees, performance, and developer experience.

Key facts

The reference details, without the paragraph.

First appeared
2010 (1.0 in 2015)
Designed by
Graydon Hoare, then developed by Mozilla and now the Rust Foundation
Typing
Static, strong, algebraic, with Hindley-Milner style inference
Execution
Compiled ahead of time to native machine code via LLVM
Memory model
Ownership and borrowing, checked at compile time — no garbage collector, no manual `free`
Package manager
Cargo, backed by crates.io
File extensions
.rs
Release cadence
A stable release every six weeks; editions every few years
Editions
2015, 2018, 2021, 2024 — opt-in, and crates of different editions interoperate
Licence
MIT and Apache 2.0

History

How the language got here — the decisions that still shape how you write it.

Rust was originally conceived and developed by Graydon Hoare as a personal project in 2006, and was later sponsored by Mozilla Research starting in 2009, with the first stable release (version 1.0) arriving on May 15, 2015, after years of intensive development, experimentation, and refinement. The language was created to address fundamental challenges in systems programming, particularly the memory safety issues that have plagued languages like C and C++ for decades and continue to be the source of the majority of security vulnerabilities in software today. Graydon Hoare, a Mozilla employee at the time, was frustrated by the frequency of crashes and security issues caused by memory errors in software, and envisioned a language that could provide the performance and control of C++ while guaranteeing memory safety at compile time. Mozilla became interested in Rust as they were planning to build Servo, an experimental next-generation web browser engine, and needed a language that could provide better safety guarantees than C++ while maintaining comparable performance. The development of Rust was highly experimental in its early years, with the language undergoing significant changes and redesigns as the team explored different approaches to achieving memory safety without garbage collection. The breakthrough came with the development of the ownership and borrowing system, which provides compile-time guarantees about memory safety through static analysis. This system was influenced by research in programming language theory, particularly affine and linear type systems, region-based memory management, and concepts from functional programming languages. Rust's development was also notable for its open, community-driven approach, with design decisions discussed publicly, RFCs (Request for Comments) used for proposing and debating language changes, and extensive community involvement in shaping the language. The path to Rust 1.0 involved removing features that didn't work well, refining the core concepts, stabilizing the standard library, and establishing a strong commitment to backward compatibility. The release of Rust 1.0 marked a turning point, with Mozilla committing to stability and backward compatibility, making it safe for production use. Servo, the browser engine project that motivated Rust's creation, successfully demonstrated that Rust could deliver on its promises, with components of Servo eventually being integrated into Firefox. Rust gained significant traction in the systems programming community, with developers appreciating its ability to catch bugs at compile time that would be runtime errors in other languages. Major technology companies began adopting Rust for critical infrastructure: Dropbox rewrote their file synchronization engine in Rust for better performance and reliability; Discord switched from Go to Rust for their message routing service, achieving significant performance improvements; Cloudflare uses Rust extensively for their edge computing platform; Microsoft has been exploring Rust for Windows components and has stated that Rust is the best choice for new systems programming projects; Amazon Web Services uses Rust for performance-critical services including parts of Lambda and EC2; and Google is integrating Rust into Android and Chrome OS. The Linux kernel, after 30 years of being exclusively C, began accepting Rust code in 2022, marking a historic shift in systems programming. In 2021, Mozilla transferred stewardship of Rust to the newly formed Rust Foundation, an independent non-profit organization backed by major technology companies including AWS, Google, Microsoft, Mozilla, and Huawei, ensuring the language's long-term sustainability and independence. Rust's ecosystem has grown tremendously, with crates.io hosting hundreds of thousands of packages covering everything from web frameworks and async runtimes to game engines and machine learning libraries. The language has expanded beyond its original systems programming niche into web development (with frameworks like Actix and Rocket), WebAssembly (where Rust is a first-class citizen), embedded systems, blockchain and cryptocurrency implementations, and even game development. Rust's influence extends beyond its direct usage; it has sparked important conversations about memory safety in the programming language community and influenced the design of other languages. The language continues to evolve with regular six-week release cycles, adding new features, improving compiler performance and error messages, and expanding its capabilities while maintaining its core commitment to safety, speed, and concurrency. Rust represents a fundamental rethinking of systems programming, proving that it's possible to have both safety and performance, and its growing adoption suggests it may play a crucial role in building more secure and reliable software infrastructure for the future.

  1. 2006

    A personal project

    Graydon Hoare starts Rust as a side project, motivated by the memory-safety bugs behind a large share of browser security vulnerabilities.

  2. 2009

    Mozilla sponsors it

    Mozilla adopts the project, aiming at a language safe enough to write a browser engine in without the crash and exploit history of C++.

  3. 2015

    Rust 1.0 and the stability promise

    The ownership model, traits and pattern matching stabilise. From this point, code that compiles is intended to keep compiling.

  4. 2018

    The 2018 edition

    A revised module system, `impl Trait`, and non-lexical lifetimes — which alone removed a large share of borrow-checker frustration.

  5. 2019

    async/await stabilises

    Zero-cost asynchronous programming lands, and Tokio becomes the foundation for a generation of high-performance network services.

  6. 2021

    The Rust Foundation

    Stewardship moves from Mozilla to an independent foundation backed by AWS, Google, Microsoft, Huawei and Mozilla.

  7. 2022–2023

    Into the Linux kernel

    Rust is accepted as a second language for Linux kernel development — a strong signal from the most conservative systems community there is.

  8. 2024

    The 2024 edition

    Refinements to async, lifetime capture rules and `unsafe` handling, alongside continuing adoption in Windows, Android and cloud infrastructure.

What it is good at

The reasons teams pick it, stated concretely.

  • Memory safety proven at compile time

    No null dereferences, no use-after-free, no data races in safe Rust — and no garbage collector to pay for it. The class of bug behind most critical security vulnerabilities is simply unreachable.

  • Fearless concurrency

    The same ownership rules that prevent memory bugs prevent data races. If it compiles, two threads are not mutating the same data unsynchronised. This turns concurrency from a source of dread into an ordinary engineering task.

  • Cargo is the best package manager in any systems language

    Build, test, benchmark, document, publish and manage dependencies with one tool and no configuration ceremony. Coming from C++ build systems, this alone is persuasive.

  • Expressive types that eliminate whole bug classes

    `Option<T>` makes absence explicit, `Result<T, E>` makes failure explicit, and exhaustive `match` means adding a variant produces compile errors everywhere it must be handled.

  • Genuinely helpful compiler errors

    Rust's diagnostics explain what went wrong, point at the relevant spans, and frequently suggest the exact fix. It set a standard other language toolchains have been chasing ever since.

Trade-offs

Every language costs you something. Knowing what, before you commit, is the whole point.

  • The learning curve is real

    Ownership, borrowing and lifetimes are a genuinely new model, not syntax to memorise. Expect several weeks of fighting the borrow checker before it starts feeling like help rather than obstruction.

  • Slow compilation

    Monomorphised generics, LLVM optimisation and heavy macro use add up. Large projects take minutes; incremental builds and `cargo check` help, but this is a daily cost.

  • Async Rust is a second learning curve

    `Pin`, `Send` bounds across await points, executor choice and the lack of async traits until recently make asynchronous Rust noticeably harder than synchronous Rust.

  • Some data structures fight the model

    Doubly linked lists, graphs and back-references are awkward because the ownership model assumes a tree. The answers exist — `Rc<RefCell<T>>`, arenas, index-based graphs — but they are extra concepts to learn.

  • A younger ecosystem in places

    Web services, CLI tools and systems programming are well covered. GUI, game engines, scientific computing and enterprise integration are thinner than in older ecosystems.

Code examples

Not syntax tours — the idioms that make code read like the language rather than a translation of another one.

Ownership and borrowing, in miniature
fn main() {
    let mut inventory = vec![String::from("hammer"), String::from("saw")];

    // Borrow immutably — many readers are allowed at once.
    let first = &inventory[0];
    println!("first item: {first}");

    // Borrow mutably — exclusive, and only after the read borrow ends.
    inventory.push(String::from("chisel"));

    // Moving transfers ownership; `inventory` is unusable afterwards.
    let owned = inventory;
    println!("{} items", owned.len());
    // println!("{:?}", inventory);  // compile error: value moved
}
One mutable borrow or any number of immutable borrows, never both at once. That single rule is what makes data races impossible in safe Rust — and it is checked entirely at compile time, so it costs nothing at runtime.
Errors as values, with `?` for propagation
use std::fs;
use thiserror::Error;

#[derive(Debug, Error)]
enum ConfigError {
    #[error("could not read {path}")]
    Io { path: String, #[source] source: std::io::Error },
    #[error("invalid TOML")]
    Parse(#[from] toml::de::Error),
}

fn load(path: &str) -> Result<Config, ConfigError> {
    let text = fs::read_to_string(path)
        .map_err(|source| ConfigError::Io { path: path.into(), source })?;
    let config: Config = toml::from_str(&text)?;   // `?` converts via #[from]
    Ok(config)
}
`?` returns early on failure and converts the error type automatically, so the happy path stays readable. There are no exceptions in Rust — every function that can fail says so in its return type, and the compiler will not let you ignore it.
Pattern matching over an enum
enum Command {
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
    Quit,
}

fn execute(command: Command) -> String {
    match command {
        Command::Move { x, y } if x == y => format!("diagonal to {x}"),
        Command::Move { x, y }           => format!("move to {x},{y}"),
        Command::Write(text)             => format!("write '{text}'"),
        Command::ChangeColor(r, g, b)    => format!("colour #{r:02x}{g:02x}{b:02x}"),
        Command::Quit                    => "quit".to_string(),
    }
}
`match` must be exhaustive: add a fifth variant and this stops compiling until you handle it. Combined with `Option` and `Result`, that is how Rust removes the 'forgot to handle a case' bug at the language level.
Concurrency the compiler has checked
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = Vec::new();

    for _ in 0..8 {
        let counter = Arc::clone(&counter);   // shared ownership, refcounted
        handles.push(thread::spawn(move || {
            let mut value = counter.lock().unwrap();
            *value += 1;                      // lock released at end of scope
        }));
    }

    for handle in handles { handle.join().unwrap(); }
    println!("{}", *counter.lock().unwrap());   // always 8
}
Try to share the `Mutex` without `Arc`, or mutate the value without locking, and the program does not compile. The `Send` and `Sync` traits encode thread-safety in the type system, so the class of race condition that plagues C++ and Java is caught before you run anything.

Common pitfalls

The mistakes that cost everyone an afternoon at least once.

  • Cloning to silence the borrow checker

    `.clone()` compiles and hides the design question. Sometimes it is genuinely the right answer; often the fix is to restructure so the borrow is shorter or the data has one clear owner.

  • Reaching for `Rc<RefCell<T>>` too early

    It moves borrow checking to runtime, where violations panic instead of failing to compile. Use it when shared mutable ownership is genuinely required, not to escape a lifetime error.

  • `unwrap()` in production code

    Fine in tests and prototypes; a panic waiting to happen in a service. Use `?`, `expect` with a message that explains the invariant, or handle the case.

  • Fighting `String` versus `&str`

    `String` owns, `&str` borrows. Take `&str` in function parameters so callers can pass either, and return `String` when you produce new data.

  • Blocking inside an async task

    A synchronous file read or a `std::thread::sleep` inside an async function stalls the whole executor thread. Use `tokio::task::spawn_blocking` for CPU-bound or blocking work.

  • Over-abstracting with generics and traits

    Rust makes elaborate abstraction possible, and the compile times and error messages both suffer. Write the concrete version first and generalise when a second use case actually appears.

In production

Where it is running at scale, and what it is doing there.

  • Mozilla

    Firefox browser engine (Servo) and various system components.

  • Dropbox

    File storage engine and performance-critical backend services.

  • Discord

    Backend services for handling millions of concurrent users.

  • Cloudflare

    Edge computing and network infrastructure.

Learning path

A realistic order to learn things in, with something to build at each step.

  1. 1

    Weeks 1–2

    Syntax and ownership

    Work through the official Book. Variables, functions, structs, enums, `match`, and then ownership, borrowing and slices. Do not rush ownership — everything after it depends on it.

    Build this: Write a CLI word counter. When the borrow checker objects, work out what it is protecting you from rather than cloning to make it quiet.

  2. 2

    Weeks 3–4

    Traits, generics and errors

    Traits and trait bounds, generics, `Option` and `Result`, the `?` operator, iterators and closures. Iterators are where Rust starts to feel expressive rather than restrictive.

    Build this: Build a small library crate with proper error types, published documentation comments and unit tests.

  3. 3

    Weeks 5–8

    Lifetimes and smart pointers

    Explicit lifetime annotations, `Box`, `Rc`, `RefCell`, and interior mutability. Learn when each is the right tool — reaching for `Rc<RefCell<T>>` too early is a common beginner detour.

    Build this: Implement a data structure with shared ownership, such as an observer registry or a small graph.

  4. 4

    Months 3–4

    Async and real projects

    Tokio, `async`/`await`, `Stream`s, and one application domain — Axum for web services, Clap for CLI tools, or embedded via `embassy`.

    Build this: Build an async web API with a database and tests, and deploy it.

  5. 5

    Ongoing

    The advanced edges

    `unsafe` and when it is justified, FFI to C, macros (declarative and procedural), `no_std`, and performance work with `cargo flamegraph` and Criterion.

    Build this: Write a safe wrapper around a C library and document exactly why each `unsafe` block is sound.

Ecosystem and tooling

The tools you will end up installing whichever project you join.

ToolWhat it does
CargoBuild, test, bench, document, publish and resolve dependencies — one tool, no configuration
rustupToolchain installer and version manager, including cross-compilation targets
ClippyA linter with hundreds of lints that teach idiomatic Rust as you go
rust-analyzerThe language server behind Rust's editor experience — completion, inlay hints, refactoring
TokioThe dominant async runtime: scheduler, timers, networking and synchronisation
SerdeSerialisation and deserialisation via derive macros; effectively the ecosystem standard
Axum / Actix WebThe leading web frameworks, both built on Tokio and Hyper
CriterionStatistically rigorous benchmarking with regression detection

Rust libraries

28 catalogued, each with installation, worked examples and best practices.

Frequently asked

Is Rust hard to learn?

Harder than Go or Python, yes — but the difficulty is concentrated and front-loaded. Ownership and lifetimes take a few weeks to internalise, after which the compiler stops feeling adversarial and starts catching mistakes you would otherwise have shipped. Most people who push through say the payoff arrives around week four.

What does the borrow checker actually do?

It enforces two rules: a value has exactly one owner, and at any moment you may have either one mutable reference or any number of immutable references, never both. That prevents use-after-free, double-free, iterator invalidation and data races — all at compile time, with no runtime cost.

Rust or Go for a back-end service?

Go if development speed, straightforward concurrency and quick onboarding matter most — which is a very common set of priorities. Rust when you need the last measure of performance, predictable latency with no garbage-collection pauses, or the stronger compile-time guarantees. Rust services typically use less memory and are slower to write.

Is `unsafe` a loophole that defeats the point?

No. `unsafe` does not disable the borrow checker; it permits five specific operations, such as dereferencing a raw pointer or calling a foreign function. The convention is to keep those blocks tiny, wrap them in a safe API, and document the invariants that make them sound. Most application code contains none at all.

Can I use Rust for web development?

For back ends, yes — Axum and Actix Web are mature and very fast. For front ends, Rust compiles to WebAssembly and frameworks like Leptos and Yew exist, but this is a niche choice compared with TypeScript. The most common real-world use is compiling a performance-critical module to WASM and calling it from JavaScript.

Why are compile times so slow?

Generics are monomorphised — a separate copy is generated per concrete type — and LLVM optimisation is thorough. Use `cargo check` while iterating, enable incremental compilation, split large crates into smaller ones, and be selective about heavy proc-macro dependencies.