Introduction to Rust
Get Rust installed, compile your first program, and learn how Cargo organises a project.
What is Rust?
Rust is a systems programming language that compiles to fast native code, prevents segfaults, and guarantees thread safety. Mozilla started it in 2010. It gives you memory safety without a garbage collector.
Key Features
- Memory Safety: No null pointers, no dangling pointers, no data races
- Zero-Cost Abstractions: High-level features with no runtime overhead
- Concurrency: Write concurrent code without data races
- Performance: Comparable to C and C++, 10 to 100 times faster than Python
- Tooling: Cargo (package manager), rustfmt (formatter), clippy (linter)
- Helpful Compiler: Error messages that teach you
Coming from Python?
If you write Python, Rust will feel different but pay off:
- No GIL: True parallelism across CPU cores
- Compiled: Binary deployment, no Python runtime needed
- Static typing: Catch bugs at compile time instead of runtime
- No garbage collector: Deterministic memory management via ownership
- 10 to 100 times faster: Performance comparable to C/C++
For a side-by-side comparison, see Chapter 0: Python to Rust.
Where Rust Shines
| Use Case | Why Rust? |
|---|---|
| CLI Tools | Single binary, fast startup, cross-platform |
| Web Services | High performance, safe concurrency |
| System Programming | OS kernels, drivers, embedded systems |
| WebAssembly | Safe, fast code in the browser |
| Game Development | Performance + safety guarantees |
| Blockchain | Security-critical applications |
Installation
Linux and macOS
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Windows
Download and run rustup-init.exe
Verify Installation
rustc --version
cargo --version
You should see output like:
rustc 1.93.0 (254b59607 2026-01-19)
cargo 1.93.0 (083ac5135 2025-12-15)
Update Rust
rustup update
Your First Rust Program
Using Cargo (Recommended)
# Create a new project
cargo new hello_world
cd hello_world
# Your project structure
# hello_world/
# ├── Cargo.toml (project configuration)
# └── src/
# └── main.rs (your code)
Look at src/main.rs:
fn main() {
println!("Hello, world!");
}
Run it:
cargo run
Output:
Compiling hello_world v0.1.0 (/path/to/hello_world)
Finished dev [unoptimized + debuginfo] target(s) in 0.50s
Running `target/debug/hello_world`
Hello, world!
Manual Compilation (Without Cargo)
# Create a file
echo 'fn main() { println!("Hello!"); }' > hello.rs
# Compile
rustc hello.rs
# Run
./hello
Understanding the Basic Program
fn main() {
println!("Hello, world!");
}
Reading it piece by piece:
| Element | Explanation |
|---|---|
fn | Keyword to define a function |
main | Special function, the entry point of every Rust program |
() | Parameters (none here) |
{} | Function body |
println! | A macro (note the !) that prints to console |
"Hello, world!" | A string literal |
; | Statement terminator |
Macros vs Functions
println!with!is a macro (generates code at compile time)printlnwithout!would be a function (but doesn't exist)
Common macros:
println!(): Print with newlineprint!(): Print without newlineformat!(): Create a Stringvec![]: Create a vectorpanic!(): Terminate program with error
Cargo Basics
Cargo Commands
# Create new project (binary)
cargo new myproject
# Create new library
cargo new --lib mylib
# Build (debug mode)
cargo build
# Build (release mode - optimized)
cargo build --release
# Run the program
cargo run
# Run with arguments
cargo run -- arg1 arg2
# Check code without building (fast)
cargo check
# Run tests
cargo test
# Update dependencies
cargo update
# Format code
cargo fmt
# Lint code
cargo clippy
Project Structure
myproject/
├── Cargo.toml # Project manifest
├── Cargo.lock # Dependency lock file (generated)
├── src/
│ └── main.rs # Entry point
└── target/ # Build artifacts (generated)
└── debug/
└── myproject # Your executable
Cargo.toml
The project configuration file:
[package]
name = "myproject"
version = "0.1.0"
edition = "2024" # Rust 1.85+ supports the 2024 edition
[dependencies]
# Add external crates here
# serde = "1.0"
Note on editions: Rust uses an "edition" system to introduce changes while keeping backward compatibility. The 2024 edition is the latest (stabilised in Rust 1.85). All code in this tutorial works with both 2021 and 2024 editions. If you see edition = "2021" in examples, that's still valid. Use whichever edition you prefer.
Hello World Variations
With Variables
fn main() {
let name = "Rustacean";
println!("Hello, {}!", name);
}
With User Input
use std::io;
fn main() {
println!("What's your name?");
let mut name = String::new();
io::stdin()
.read_line(&mut name)
.expect("Failed to read line");
println!("Hello, {}!", name.trim());
}
Run it:
cargo run
# Enter your name when prompted
With Command Line Arguments
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() > 1 {
println!("Hello, {}!", args[1]);
} else {
println!("Hello, world!");
}
}
Run it:
cargo run -- Alice
# Output: Hello, Alice!
The Rust Compiler as Teacher
The compiler is your friend. Try this:
fn main() {
let x = 5;
x = 6; // Error!
println!("{}", x);
}
The compiler says:
error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:3:5
|
2 | let x = 5;
| -
| |
| first assignment to `x`
| help: consider making this binding mutable: `mut x`
3 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
It points at the bad line, names the rule, and offers a fix: let mut x = 5;. Read these messages. They are the fastest way to learn the language.
Key insight: variables are immutable by default. To rebind, write mut.
Rust's Philosophy
Memory Safety Guarantees
Rust prevents common bugs at compile time:
| Bug Type | How Rust Prevents |
|---|---|
| Null pointer dereference | No null pointers (uses Option<T>) |
| Use after free | Ownership system |
| Double free | Ownership system |
| Buffer overflow | Bounds checking |
| Data races | Ownership + borrowing rules |
The Ownership System
The core idea, expanded in Chapter 3:
- Each value has an owner
- Only one owner at a time
- When the owner goes out of scope, the value is dropped
That gives you memory safety without garbage collection.
Development Workflow
# 1. Create project
cargo new myapp && cd myapp
# 2. Edit code
# (use your favorite editor)
# 3. Quick check (fastest)
cargo check
# 4. Test compile
cargo build
# 5. Run
cargo run
# 6. Add dependencies (edit Cargo.toml)
# [dependencies]
# rand = "0.8"
# 7. Build with new deps
cargo build
# 8. Before commit
cargo fmt
cargo clippy
cargo test
Setting Up Your Editor
VS Code (Recommended)
Install extensions:
- rust-analyzer: Language server (autocomplete, go to definition)
- CodeLLDB: Debugger
- Even Better TOML: For Cargo.toml
Other Editors
- Vim/Neovim: rust-analyzer with coc.nvim or native LSP
- Emacs: rust-mode + lsp-mode
- IntelliJ: Rust plugin
- Sublime Text: Rust Enhanced + LSP
Common First-Day Issues
Issue: "Command not found: cargo"
Solution: Restart your terminal or run:
source $HOME/.cargo/env
Issue: Slow Compilation
Solution:
# Use cargo check for quick feedback
cargo check
# Use --release only when needed
cargo build --release
Issue: Cryptic Error Messages
Solution: Read carefully. Rust errors are detailed. Look for:
- The error code (e.g., E0384)
- The suggestion (usually after "help:")
- The problematic line
Practice Exercises
Exercise 1: Hello Name
Create a program that:
- Asks for your name
- Asks for your age
- Prints "Hello, [name]! You are [age] years old."
Exercise 2: Calculator
Create a program that:
- Takes two numbers as command line arguments
- Prints their sum
Example:
cargo run -- 5 3
# Output: 5 + 3 = 8
Exercise 3: Temperature Converter
Create a program that converts Celsius to Fahrenheit.
Formula: F = C × 9/5 + 32
Key Takeaways
- Rust prioritises safety and performance
- Cargo is your one tool for building Rust projects
- The compiler is your friend. Read error messages carefully
- Variables are immutable by default
- Rust has no garbage collector but still guarantees memory safety
Next Steps
Continue to 02-basics.md to learn Rust's type system, variables, and basic operations.
Quick Reference Card
// Create a project
cargo new myproject
// Run a program
cargo run
// Variables (immutable)
let x = 5;
// Variables (mutable)
let mut y = 10;
y = 20;
// Print to console
println!("Value: {}", x);
// Function definition
fn main() {
// code here
}