Skip to content

Language guide

Learn Rust

Systems-level speed with a compiler that refuses whole classes of memory bugs.

Rust on SkillAIVibe

Written guide

SkillAIVibe does not run Rust in the browser yet, so this page is a written guide: what the language is, a complete first program, how to run it on your own computer, and a learning order. Languages that do run here are listed on the Learn to Code hub.

What Rust is

Rust is a compiled systems language that aims for the speed and control of C and C++ without their memory bugs. It does this through ownership: every value has exactly one owner, borrowing is checked when the program is compiled, and the compiler refuses code that could use freed memory or race on shared data. Writing it feels like working with a very careful reviewer — the error messages are unusually detailed and often suggest the fix — and once a program compiles it tends to behave. The price is a steeper learning curve than most languages.

Where Rust is used

Systems software
The Linux kernel and Android both now contain Rust code, and Microsoft has rewritten parts of Windows in it, in each case to remove memory-safety bugs from code that runs with high privileges.
Command-line tools
Fast start-up, a single binary and a strong set of libraries for argument parsing and terminal output make Rust a common choice for developer tools.
Network services
Async Rust with the Tokio runtime is used for web servers, proxies and services where memory use and latency matter.
WebAssembly
Rust compiles cleanly to WebAssembly, so performance-critical parts of a web application — image editing, simulations, games — can be written in Rust and run inside the browser.
Embedded and firmware
Rust runs on microcontrollers without an operating system (no_std), giving the same memory guarantees on hardware where a crash is expensive to track down.

Your first Rust program

Saved as main.rs. Run it with the steps in the next section.

Rust
fn main() {
    let name = "Ravi";
    let year = 2026;

    println!("Hello from Rust.");
    println!("{name} started learning in {year}.");
    println!("Two years on, it will be {}.", year + 2);
}

What it prints

Output
Hello from Rust.
Ravi started learning in 2026.
Two years on, it will be 2028.
  1. Line 1 declares main, the function every Rust program starts in. fn introduces a function and the braces hold its body.
  2. Lines 2 and 3 create two variables with let. Rust infers the types — name is a string slice (&str) and year an integer (i32 by default) — and both are immutable: assigning to year later would be a compile error unless it had been declared let mut year.
  3. Line 5 prints a line. println! ends in an exclamation mark because it is a macro rather than a function, which is what lets it check the format string at compile time.
  4. Line 6 puts variables straight into the text: {name} and {year} are replaced by their values. This inline form works for plain variable names.
  5. Line 7 uses an empty {} placeholder filled by the expression after the comma, because an expression such as year + 2 cannot go inside the braces directly.

Run Rust on your own computer

Rust is installed with rustup, the official toolchain manager, which brings the compiler (rustc), the build tool and package manager (cargo) and the documentation in one step. Nearly all Rust work goes through cargo.

  1. Install rustup

    On macOS and Linux, run the command below in a terminal; it downloads rustup and installs the current stable toolchain. On Windows, download and run rustup-init.exe from rust-lang.org/tools/install; it tells you if it needs the Visual Studio C++ build tools, which the default Windows toolchain links against, and offers to install them.

    Shell
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. Check it works

    Open a new terminal so the PATH change is picked up. rustc --version shows the compiler; cargo is the command you will type most.

    Shell
    cargo --version
  3. Create a project

    This makes a hello folder containing Cargo.toml, which holds the project's metadata and dependencies, and src/main.rs, which already contains a hello-world. Replace the contents of src/main.rs with the program above.

    Shell
    cargo new hello
  4. Run it

    Run this inside the hello folder. cargo compiles the project, prints a few lines about what it is doing, then runs the result. The first build of a project takes longer than later ones. cargo build compiles without running, and cargo build --release turns on optimisations for a program you mean to ship.

    Shell
    cargo run
  5. Keep the toolchain current

    Rust publishes a new stable release every six weeks, and this one command updates everything rustup installed. For an editor, install rust-analyzer, the official language server; it shows the compiler's own error messages inline as you type.

    Shell
    rustup update

A learning order for Rust

Stages, not a timetable. Each one exists because the next would not make sense without it, and how long each takes depends on how much you write.

  1. Stage 1. Cargo, printing and variables

    • cargo new, build and run
    • let and let mut
    • integers, floats, bool and char
    • println! and format strings
    • reading compiler errors and cargo check

    Immutability by default is the first thing that trips people, and the compiler's messages are the main teaching tool, so learning to read them carefully comes first.

  2. Stage 2. Control flow and functions

    • if as an expression
    • loop, while and for over ranges
    • match
    • functions and return values
    • expressions versus statements

    In Rust almost everything is an expression — if and match produce values — which changes how you write even simple code. match is the pattern-matching construct you will use constantly.

  3. Stage 3. Ownership and borrowing

    • moves
    • references: & and &mut
    • the borrowing rules
    • String versus &str
    • lifetimes in outline

    This is the heart of Rust and the reason it is harder than other languages. Expect to spend real time here and to argue with the borrow checker; it is teaching you what memory-safe code looks like.

  4. Stage 4. Structs, enums and collections

    • struct and impl
    • enums that carry data
    • Option and Result
    • Vec, HashMap and String
    • iterators and closures

    Option and Result replace null and exceptions, and are why Rust programs handle missing values and failures explicitly. Iterators are how idiomatic Rust loops, and they compile down to the same code as a hand-written loop.

  5. Stage 5. Errors, traits and generics

    • the ? operator
    • custom error types
    • traits and impl Trait
    • generics and trait bounds
    • Debug, Clone and Display

    Traits are Rust's answer to both interfaces and inheritance, and generics are checked against them at compile time. This is the stage where your code starts to look like the standard library's.

  6. Stage 6. Modules, crates and beyond

    • modules and pub
    • dependencies from crates.io
    • cargo test
    • Box, Rc and RefCell
    • threads, Send and Sync, then async

    Real programs span files and pull in crates. Smart pointers and the threading traits are the advanced corners of ownership, and async is a large enough topic to deserve its own pass once the rest is solid.

Mistakes beginners make in Rust

Assigning to an immutable variable
let count = 0; followed by count += 1; fails with 'error[E0384]: cannot assign twice to immutable variable `count`'. Variables are immutable unless declared with let mut. The compiler's message includes the fix, and getting used to reading those messages is half the learning curve.
Using a value after it has been moved
let a = String::from("hi"); let b = a; println!("{a}"); gives 'error[E0382]: borrow of moved value: `a`'. A String owns its memory, and assigning it hands ownership to b, so a is no longer valid. Clone it with a.clone() if you really need two copies, or borrow it with &a if you only need to look at it.
Holding a mutable and a shared borrow at the same time
Taking &mut v while an earlier &v is still in use produces 'error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable'. The rule is one mutable borrow or any number of shared borrows, never both at once. The usual fix is to shorten the life of the first borrow, and the error points at the lines involved.
Confusing String and &str
Passing a String where a function wants &str, or the reverse, gives 'error[E0308]: mismatched types' with a note such as 'expected `&str`, found `String`'. A String owns its text and can grow; a &str is a borrowed view of text that lives somewhere else. Functions should usually take &str, and callers pass &my_string.
Calling unwrap and crashing
Calling .unwrap() on an Option or Result panics when the value is None or Err, with 'called `Option::unwrap()` on a `None` value'. That is fine in a quick experiment, but in real code use match, if let or the ? operator to handle the missing case instead of assuming it never happens.

Strengths and trade-offs

Where it is strong

  • Memory safety without a garbage collector: no use-after-free, no data races and no null, all enforced at compile time.
  • Performance in the same class as C and C++, with the same control over memory layout and allocation.
  • Error messages that explain what went wrong and usually propose the fix, plus cargo, which makes building, testing and dependency management one consistent tool.
  • One language from firmware to WebAssembly to web servers, with the same guarantees everywhere.

Where it is not

  • The learning curve is steep. Ownership, borrowing and lifetimes have no direct equivalent in other mainstream languages, and the compiler rejects code that would be accepted in C or Go until you learn to structure it differently.
  • Compile times are long compared with Go or C, and noticeably so on large projects with many dependencies.
  • Slower to write: satisfying the compiler takes longer than in a garbage-collected language, which matters when you are prototyping.
  • Async Rust and some advanced trait patterns are genuinely hard, and the ecosystem for graphical interfaces and games is younger than C#'s or C++'s.

Who Rust is for

Rust is the right next language for programmers who already know one language and want to understand memory and concurrency properly, or who work in systems, embedded, security or performance-sensitive code. It can be a first language for a patient, curious learner who wants the hard things taught explicitly, but most people find the ownership rules easier to appreciate after seeing the bugs they prevent in C or the runtime costs they avoid in a garbage-collected language. If you want to get something working quickly, want to do data work or scripting, or want a web front-end or a mobile app, start with Python, JavaScript or C# and come back later.

Questions about learning Rust

Is Rust a good first language?
It can be, but it is a demanding one. The compiler's error messages are unusually good and the tooling is consistent, which helps a lot. But ownership and borrowing are ideas you cannot skip, and they are easier to appreciate when you have already met the problems they solve. Many people learn Python or Go first and Rust second, and there is nothing wrong with that order. If you do start with Rust, expect slower early progress and read the official book in order.
Do I need to know C or C++ first?
No. Rust does not build on C, and its syntax owes as much to the ML family of languages as to C. What helps is having met pointers, the stack and the heap once, because Rust's rules make more sense when you know what they are protecting you from. If you have never seen those ideas, the ownership chapter of the official book introduces them from scratch.
What is the borrow checker?
The part of the compiler that enforces the ownership rules: every value has one owner, you can hold either one mutable reference or any number of shared references, and a reference can never outlive the value it points to. It runs at compile time, so it costs nothing when the program runs, and it rejects programs that could corrupt memory before they ever start. Fighting it is the normal experience at first; the errors become rarer as your code naturally starts to follow the rules.
Should I use cargo or rustc directly?
cargo, almost always. rustc main.rs works for a single file and is worth seeing once, but cargo handles dependencies, tests, documentation and release builds, and every Rust project and tutorial assumes it. The only reason to reach for rustc on its own is a quick one-off experiment.

The primary source

When this guide and the official documentation disagree, the documentation is right and we would like to hear about it.

Other languages

All languages and paths · Programming glossary · Your progress