Introduction to Rust
TL;DR: Rust is a systems programming language that guarantees memory safety without a garbage collector. In this lesson you'll write your first Rust program, learn why ownership makes Rust different, and meet the abstractions that cost nothing once you compile with optimizations on. Estimated: 15 minutes. → Jump to code examples
Welcome to your first lesson in Rust programming! In this introduction, we'll cover what Rust is, why it's unique, and what makes it an excellent choice for modern software development.
What is Rust?
Rust is a systems programming language that focuses on safety, concurrency, and performance. It began as a Mozilla Research project and is now governed independently by the Rust project and the Rust Foundation. It has topped Stack Overflow's annual developer survey as the most admired language for several years running.
Your First Rust Program
Every programming journey starts with "Hello, World!" — hit Run to see Rust in action:
fn main() {
println!("Hello, World!");
}
That's it! Every Rust program starts with a fn main() function — it's the entry point. The println! macro (the ! means it's a macro, not a regular function) prints text to the screen.
Try it! Change the message inside the quotes and run it again.
Key Features
Memory Safety Without Garbage Collection
fn main() {
// Variables are immutable by default
let name = "Rust";
// Use mut to make a variable mutable
let mut count = 0;
count += 1;
println!("Learning {} - Count: {}", name, count);
}
Try it! Change name to your own name, or increment count a few more times.
Abstractions Designed to Cost Nothing
Rust gives you high-level features that, when you compile with optimizations on, collapse down to the same low-level code you would have written by hand. Worth knowing from day one: the sandbox behind the Run button compiles without optimizations, so what you run here still pays for those abstractions.
fn main() {
// Tuples group different types together
let point = (10, 20);
println!("x = {}, y = {}", point.0, point.1);
// Arrays have a fixed size, known at compile time
let numbers = [1, 2, 3, 4, 5];
println!("First number: {}", numbers[0]);
println!("Array length: {}", numbers.len());
}
Try it! Change the values in the tuple or add more numbers to the array.
Arithmetic on Whole Numbers
Arithmetic looks the same as it does everywhere else, with one difference worth meeting on day one: the type of the values decides which arithmetic runs. When both sides of a / are whole numbers, Rust does whole-number division — it throws away the fraction rather than rounding it. Work out all three printed lines below before you run it.
Predict
Three lengths are added up and then divided by 3. Predict all three printed lines before running.
fn main() {
let lengths = [7, 4, 2];
let mut total = 0;
total += lengths[0];
total += lengths[1];
total += lengths[2];
let average = total / 3;
let remaining = total - average * 3;
println!("total = {}", total);
println!("average = {}", average);
println!("remaining = {}", remaining);
}The answer is total = 13, average = 4, remaining = 1. Adding 7 + 4 + 2 gives 13, and 13 / 3 runs as whole-number division: it truncates to 4 and throws the leftover away entirely — it does not round to 5. remaining recovers that discarded 1 by working backwards. The rule to remember is that the operand types decide which arithmetic runs, so a fraction has to be introduced before the division, never after. The next lesson picks this up in detail when it covers numeric types and conversions.
Why Learn Rust?
- Safety: Rust's ownership system prevents common bugs at compile-time
- Performance: No garbage collector, and abstractions that optimize away in release builds
- Modern Tooling: Excellent package manager (Cargo) and documentation
- Growing Ecosystem: Active community and increasing adoption
Getting Started
To start coding in Rust, you'll need to:
- Install Rust using rustup
- Set up your development environment
- Learn the basic syntax — covered in Variables and Control Flow
- Understand Rust's ownership model
We'll cover each of these topics in detail in the upcoming lessons.
Functions in Rust
Rust lets you define your own functions to organize code. Functions can take parameters and return values:
fn greet(name: &str) -> String {
format!("Hello, {}! Welcome to Rust.", name)
}
fn add(a: i32, b: i32) -> i32 {
a + b // No semicolon = this is the return value
}
fn main() {
let message = greet("learner");
println!("{}", message);
let result = add(5, 7);
println!("5 + 7 = {}", result);
}
Notice that Rust functions return the last expression without needing a return keyword (as long as you leave off the semicolon). We'll cover functions in detail in a later lesson.
Try it! Change the name passed to greet, or write a multiply function that returns a * b.
Interactive Playground
Practice what you've learned! Edit and run the code below to experiment with Rust.
fn main() {
// Try changing these values!
let language = "Rust";
let year = 2024;
// String formatting in Rust
println!("Learning {} in {}!", language, year);
// Basic arithmetic
let a = 10;
let b = 20;
println!("{} + {} = {}", a, b, a + b);
// Arrays
let numbers = [1, 2, 3, 4, 5];
println!("First number: {}", numbers[0]);
println!("Array length: {}", numbers.len());
}
Try these exercises:
- Change the
languagevariable to your favorite programming language - Add more numbers to the
numbersarray - Print
numbers[1]multiplied by 3 - Add a new variable and include it in the first println statement
Pro Tip: The best way to learn Rust is by practicing. Try modifying the code examples above and experiment with them in the Rust Playground.
Check Yourself
Every later lesson ends with a question that reaches back to something you learned earlier. This is the first lesson, so there is nothing behind it yet — this one reaches back into what you have already read on this page. Close the page, or scroll away from the examples, and answer from memory rather than by looking.
Recall
Without scrolling up: the memory-safety example bound a name with a plain let and a counter with let mut, then ran count += 1 on the counter. Later, a function add had the single-line body a + b with no semicolon and no return. Which statement matches what those two examples showed?
Both halves are worth fixing in memory now. Rust variables are immutable by default and mut is how you opt out — so let name = "Rust"; is fixed for good, while let mut count = 0; may be reassigned. And a function's last expression is its return value when you leave the semicolon off, which is why add gives back a + b without ever writing return. Put the semicolon back and the function returns nothing, breaking its -> i32 promise. Everything else in this track builds on those two facts.
Key Takeaways
- Rust is a systems programming language focused on safety, concurrency, and performance
- It guarantees memory safety without a garbage collector through its ownership system
- Variables are immutable by default — you opt into mutability with
mut - Rust catches many common bugs at compile time, before your code ever runs
- The language has excellent tooling: Cargo (package manager), rustfmt (formatter), and clippy (linter)
Next Steps
You've seen what makes Rust different: compile-time safety, immutability by default, and abstractions that optimize away in release builds. But we've only scratched the surface of how Rust thinks about data. In the next lesson, we'll explore variables and data types in depth — how Rust's type system decides what a value is, what numeric, boolean, and character types are available, and how to convert between them safely. Understanding the type system is essential because it's the foundation that makes all of Rust's safety guarantees possible.
Next lesson
Variables and Data Types
Master Rust variables, mutability, and data types including integers, floats, booleans, characters, and type annotations
20 min