Interactive roadmap
Rust roadmap
Designed for programmers wanting to build fast, reliable software. You will learn to write memory-safe code without needing a garbage collector.
- 1
Getting Started with Cargo
0 of 3 done
Set up your environment and learn how to manage Rust projects.
Take it one step at a time and run your code often to see how the compiler helps you. - 2
Ownership and Borrowing
0 of 3 done
Understand Rusts unique way of managing memory safely at compile time.
Visualise ownership as passing a physical baton in a relay race to understand how data moves. - 3
Structs and Enums
0 of 3 done
Group related data together and model complex application states.
Use enums to model valid states so your code becomes immune to whole classes of bugs. - 4
Traits and Generics
0 of 3 done
Write flexible code that works across many different data types.
Think of traits as contracts that promise certain behaviours, making your code modular and reusable. - 5
Errors and Collections
0 of 3 done
Handle unexpected runtime issues and store collections of items.
Writing tests as you code turns debugging into a quick verification check rather than a mystery hunt.
Learn it all, with a tutor that never sleeps
Every topic links to LevelUp lessons, practice exercises and the 24/7 AI Tutor. Your progress updates as you master lessons.
Every topic explained
Step 1: Getting Started with Cargo
- Install the toolchain using rustup so you have the compiler and package manager ready.Rust Documentation
Read more
Rustup is the official installer that manages your Rust toolchain, compiler, and build tools. It ensures you always have the right version installed for your projects.
Think of it like setting up a workbench with all the correct screwdrivers and spanners before you start fixing a bicycle. You run a simple command in your terminal, and everything downloads securely.
Getting this foundation right matters because it gives you access to the compiler, which acts as your strict but helpful guide throughout this entire learning roadmap.
- Rustup manages your toolchain and updates.
- Includes the compiler and package manager.
- Works smoothly across different operating systems.
- Manage dependencies and build your applications easily with the built-in package manager.
Read more
Cargo is Rust's built-in package manager and build system. It handles downloading libraries, compiling your source code, and packaging your software for release.
Imagine you are building a wooden shelf. Instead of cutting every screw from scratch, Cargo visits a hardware store to fetch pre-made brackets so you can focus on the wood.
This tool matters because it saves you hours of configuration work, letting you share your code and add outside features with a single command.
- Creates new projects using cargo init or new.
- Compiles and runs code with cargo run.
- Downloads external libraries automatically.
- Learn variables, functions, and data types to write your very first programs.
Read more
Basic syntax covers variables, functions, and data types like integers and booleans. It forms the vocabulary you use to write instructions that the computer can execute.
Think of writing code like penning a recipe. You declare your ingredients, define preparation steps, and combine them in a specific order to get a predictable dish.
Mastering these fundamentals matters because every complex program you build later will rely on these exact same building blocks.
- Variables are immutable by default in Rust.
- Functions are defined using the fn keyword.
- Data types must be known at compile time.
Step 2: Ownership and Borrowing
- Every value in Rust has a single owner, preventing memory leaks and double frees.
Read more
Ownership is Rust's core memory management rulebook. Every value has a designated variable called its owner, and when that owner leaves scope, the memory is dropped.
Picture a cinema ticket. Only one person holds the ticket at a time, and when the film ends, that ticket is torn up and thrown away cleanly.
This system matters because it prevents memory leaks and crashes without needing a garbage collector, keeping your software lightning fast.
- Each value has a single owner variable.
- Memory drops automatically when the owner exits scope.
- Assigning data to another variable moves ownership.
- Allow functions to use data without taking full ownership by passing references.
Read more
Borrowing lets functions access data using references without taking full ownership. You can have multiple readers or one writer at any given time.
Imagine lending a book to a friend. They read the story, but you keep ownership of the book and get it back afterwards.
This concept matters because it allows you to share data across your program safely without constantly copying large chunks of memory.
- References are created using the ampersand symbol.
- Borrowed data cannot be modified unless mutable.
- Prevents data races at compile time.
- (optional)
- Reference a contiguous sequence of elements in a collection rather than the whole thing.
Read more
Slices let you reference a contiguous sequence of elements in a collection rather than handling the entire data structure.
Think of it like highlighting a single sentence in a long magazine article instead of reading the whole page.
Slices matter because they give you a safe, efficient way to inspect subsets of arrays and strings without allocating extra memory.
- String slices view a portion of text.
- Array slices let you inspect parts of collections.
- Slices borrow data safely without copying.
Step 3: Structs and Enums
- Create custom data types tailored to represent specific real-world entities.
Read more
Structs allow you to bundle related values together into custom data types that represent real-world concepts.
Imagine filling out a user profile form with fields for a username, age, and email address, grouping them neatly into one entity.
Structs matter because they organise your data logically, making your code easier to read, maintain, and expand as projects grow.
- Defined using the struct keyword.
- Contains named fields and data types.
- Can have associated functions using impl blocks.
- Define types that can be one of several variants and handle them safely.
Read more
Enums let you define a type that can be one of several distinct variants, while pattern matching ensures you handle every single case.
Think of traffic lights displaying red, amber, or green, where drivers must take a specific action for each light colour.
This matters because the compiler forces you to handle all possible variants, preventing unhandled edge cases from causing bugs.
- Enums list multiple possible variant choices.
- Match expressions exhaustively check every variant.
- Variants can hold different data types inside them.
- Use standard enums to handle missing values and potential failures gracefully.
Read more
Option and Result are standard enums used to handle missing values and potential errors explicitly without null pointer crashes.
Picture opening a mailbox. It either contains a letter or is empty, and you must check before assuming you have mail.
These enums matter because they replace vague error codes with robust types that force you to think about failure cases upfront.
- Option represents a value that might be present or absent.
- Result represents success or failure outcomes.
- Encourages safe, explicit error management.
Step 4: Traits and Generics
- Write code templates that accept multiple concrete data types without duplication.
Read more
Generics let you write flexible code templates that accept multiple concrete data types without duplicating your logic.
Think of a cardboard shipping box that can hold shoes, books, or electronics without changing the box design.
Generics matter because they keep your codebase DRY, letting you write algorithms once and reuse them across different data structures.
- Uses angle brackets for type parameters.
- Eliminates duplicate code for different types.
- Zero runtime cost through monomorphisation.
- Define shared behavior across different types similar to interfaces in other languages.
Read more
Traits define shared behaviour across different types, similar to interfaces in other programming languages.
Imagine a speaker trait implemented by both dogs and musical instruments, where both can produce a sound in their own way.
Traits matter because they allow you to write decoupled code that interacts with types based on what they can do rather than what they are.
- Declared using the trait keyword.
- Types implement traits using the for syntax.
- Enables polymorphic function arguments.
- (optional)
- Restrict generic types to only those that implement specific behaviors.
Read more
Trait bounds let you restrict generic types so they only accept inputs that implement specific behaviours.
Picture a shelf in a library that only accepts books equipped with braille markings, filtering out standard print.
This matters because it lets you write generic functions that safely call specific methods on unknown types.
- Restricts generics using colon syntax.
- Ensures required methods exist at compile time.
- Combines multiple bounds with plus signs.
Step 5: Errors and Collections
- Use the try operator and custom error types to manage issues robustly.
Read more
Error handling in Rust relies on the Result type and the question mark operator to propagate issues up the call stack cleanly.
Think of a factory assembly line where a broken part stops the process immediately and alerts the supervisor.
Robust error management matters because it prevents your application from crashing unexpectedly in production when faced with bad inputs.
- The question mark operator propagates errors easily.
- Custom error types provide descriptive feedback.
- Avoids panic crashes in production code.
- Store lists of items and key-value pairs using standard library collections.
Read more
Vectors store lists of items in contiguous memory, while hash maps store key-value pairs for quick lookups.
Picture a shopping list stored on a notepad alongside a telephone directory matching names to phone numbers.
Collections matter because real-world applications constantly need to organise, search, and manage dynamic sets of data efficiently.
- Vectors grow and shrink dynamically.
- Hash maps link keys to unique values.
- Standard library collections are optimized for speed.
- Ensure your code works correctly by writing automated tests alongside your source code.
Read more
Unit tests are automated checks written alongside your source code to verify that individual functions behave correctly.
Imagine a baker tasting a spoonful of batter before baking the cake to ensure the sugar level is right.
Testing matters because it gives you the confidence to refactor your code and add new features without breaking existing functionality.
- Tests are marked with the test attribute.
- Run using the cargo test command.
- Uses assert macros to check expected outcomes.