Learn Rust
Theme

Rust for people who already know another language

Learn Rust (even with all your past baggage)

Your code compiles in Go, Java, Python or C++. Rust says no, and it is usually right. Find out what it can see that you can't, and what to write instead.

Every lesson sets a Rust program beside the same program in your language, then ends with a gotcha: code that looks fine, the real compiler error, and the fix.

  • 53 lessons
  • 7 phrasebooks
  • 5 projects
  • 9 checkpoints
  • 8 languages compared

Every program, output and error on this site comes from a real run: rustc 1.99.1, Go 1.27.3, Kotlin 2.4.21, Java 25.0.5, Python 3.13.5, TypeScript 7.0.2 on Node 24.22.1, .NET 10.0.402, GCC 14.2.0.

Where are you coming from?

Pick the language you know best. Every comparison on the site shows it first, and your starting path appears right below. Nothing is sent anywhere: the choice is saved in this browser.

Your path · Go

Rust for Go developers

Starts from what you know (goroutines, nil, if err != nil), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · Kotlin

Rust for Kotlin developers

Starts from what you know (null safety, data classes), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · Python

Rust for Python developers

Starts from what you know (dynamic types, None, exceptions), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · TypeScript

Rust for TypeScript developers

Starts from what you know (undefined, async/await, npm), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · Java

Rust for Java developers

Starts from what you know (classes, null, exceptions), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · C#

Rust for C# developers

Starts from what you know (LINQ, async, nullable refs), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · C

Rust for C and C++ developers

Starts from what you know (malloc, free, raw pointers), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Your path · C++

Rust for C and C++ developers

Starts from what you know (RAII, templates, smart pointers), then shows each habit that meets a compiler error, with the fix.

Saved on this device. Change it any time from the top of a lesson.

Rust is harder. It is still hard to ignore.

Expect a few months before Rust feels normal. These are the reasons teams pay that price. Every figure comes from the source linked beside it, and the full case also lists when to skip Rust.

It rules out a class of bug that keeps hurting C and C++

Microsoft put memory-safety issues at about 70% of the vulnerabilities it assigns a CVE each year (MSRC, 2019), and Chrome at about 70% of its high-severity bugs (Chromium). In safe Rust the compiler rules that class out, with no garbage collector.

It has been tried at scale, in public

Android's memory-safety share of vulnerabilities fell from 76% in 2019 to 24% in 2024, thanks to memory-safe languages in general, Rust among them (Google, 2024). Linux has had Rust support since 6.1, and Cloudflare's Rust proxy uses "about 70% less CPU and 67% less memory" than the system it replaced (Cloudflare, 2022).

You probably already depend on it

uv and Ruff if you write Python. Turbopack, Rolldown, Biome and Deno if you write JavaScript. ripgrep, which has powered search in VS Code since 2017. Tools people wanted much faster were rewritten in Rust while their users kept writing Python or TypeScript.

Governments are asking for plans

In December 2023, CISA, NSA, FBI and their counterparts in Australia, Canada, the UK and New Zealand asked software makers to plan how to get memory-safety bugs out of their products (CISA). It is guidance, not a ban.

And the price, stated plainly

  • In a Google survey, a third of respondents said they were as productive in Rust as in their other languages within two months, and over half within four. The rest took longer.
  • Slow compilation tops the productivity problems in the 2025 State of Rust survey.
  • It is the wrong tool for some jobs: quick scripts, and ports where another language fits the existing code better.

Read the sourced case for and against →

Vibe-coding Rust works, right up until it doesn't

Ask an assistant for Rust, paste the compiler's complaints back, repeat until it builds. That gets a program that compiles. These are the places where it stops being enough, and the hours that fix it are the ones on this site.

The compiler asks questions only you can answer

Rust rejects code whose ownership it can't follow, and the way out depends on what the code is for. The error shown further down offers two fixes: borrow the value, or clone it. Choosing between them takes knowing who should own the data. Reading compiler errors is the place to start.

Compiling is not the same as correct

Safe Rust rules out memory bugs, not wrong logic. In November 2025 a Cloudflare proxy called unwrap() on an error it hadn't handled, panicked, and took much of their network down (Cloudflare). The compiler let it through because it was valid. Rust makes you decide what happens on an error, and only you can make that decision a good one.

Some code the compiler can't vouch for

Inside an unsafe block, the promises move from the compiler to whoever wrote the block. The first security bug in the Linux kernel's Rust code was a data race inside an unsafe block (CVE-2025-68260). If you can't read a // SAFETY: comment and judge it, you can't review it. unsafe, honestly covers how.

The quickest way to silence an error is often the wrong one

.clone() to quiet the borrow checker, unwrap in a library, Rc<RefCell<_>> for everything: all three compile, and the Idioms lesson shows what each costs. Working with the Borrow Checker shows the fixes that change the design instead.

An assistant doesn't change who reviews the code

Use one if you like. You still read what comes back, run it, and answer for it. Learning Rust is an investment, and the numbers are public: in a Google survey, a third of respondents were as productive as in their other languages within two months, and over half within four (Google, 2023). The rest took longer.

Start with the syntaxLearn to read the errors

6 pages

Start here

Why Rust is worth it (and what it costs), the mindset, your first project, using libraries, splitting code into files, and running several programs.

6 pages

Standard library

What comes in the box and how to use it: files, collections, text, processes, formatting, and how to read the docs.

11 pages

Build with Rust

The crates everyone uses: JSON, async, HTTP services, gRPC, databases, CLIs, errors, logging, testing and data.

6 pages

Going further

Reading macros, what unsafe is for, idioms and design patterns, project structure, deeper testing, and measuring performance.

4 pages

Use Rust from…

Write the fast or risky part in Rust and call it from Python, Node, C and C++, or WebAssembly.

5 pages

Projects

Complete, tested programs built step by step: a CLI, a library, a web API, a concurrent indexer and a multi-crate workspace.

1 page

Cheat sheets

One printable page of Rust syntax: symbols, the habits that trip people up, and how to read a signature.

9 pages

Checkpoints

Predict the output or the compiler error, then run it. One page per part of the course.

The one idea behind every gotcha

Most languagesIs this code wrong?

If nothing is clearly broken, it compiles. Whatever could go wrong is dealt with while the program runs: by a garbage collector, a null pointer exception, a crash, or a race detector if you remember to use it.

RustCan I prove this can never go wrong?

If it can't prove it, it refuses, even when your program would actually work. There's no garbage collector to clean up afterwards, so it has to be sure before the program runs.

Why harmless-looking code fails

  • The compiler doesn't run your code. It doesn't know what is in your variables, whether a key exists, or which thread finishes first.
  • It only sees the shape of the code: the types, and the order things happen in.
  • So when your code has the same shape as code that would crash, it says no. It isn't saying your code is wrong. It is saying it can't prove your code is right.

Is real-world Rust this hard?

No. The gotchas show the edges on purpose, so you recognise them. Everyday Rust reads a lot like the code you already write.

What you will write most days

  • Structs that own their data: String, Vec, Arc<T>. No lifetimes to write.
  • Functions that borrow to read (&T) and return new values.
  • Changes through &mut self methods like push and insert, about as often as you'd call a method that changes an object anywhere else.
  • Iterator chains for loops, and ? for errors.

What you mostly read, not write

  • Hand-written lifetimes ('a), &&T, &mut &T.
  • They live in parsers, zero-copy decoders, and the insides of libraries like Arrow, Parquet and Tantivy, so that your side stays simple.
  • If your code starts to feel like pointer gymnastics, there is almost always a version that returns a value instead. Write that one.

Four kinds of gotcha

Every gotcha carries one of these labels, so you know whether you are learning a safety rule or just a different habit.

Fine where you come from. Rust can't prove it's safe.

Your version really is fine. But the same shape of code breaks in other situations, and the compiler can't tell your case from those, so it refuses them all.

Broken where you come from. Rust catches it.

Your version runs, but it is actually wrong: a null crash, a silently wrong answer, or a data race. In Rust the same mistake is a compile error.

Just a Rust rule.

Nothing could go wrong here. Rust just has a different rule or default from the language you know. You learn it once and move on.

Compiles in both. Different result.

Both versions compile and run, but they don't do the same thing. Usually the other language quietly picks a default where Rust makes you say what you mean.

How to read a compiler error

Rust's errors look long, but they follow a fixed layout. This is the real error from the gotcha in lesson 26, Vectors and Slices.

$ cargo buildWhat is E0507?
error[E0507]: cannot move out of index of `Vec<String>`
 --> src/main.rs:3:17
  |
3 |     let first = names[0];
  |                 ^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
  |
help: consider borrowing here
  |
3 |     let first = &names[0];
  |                 +
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let first = names[0].clone();
  |                         ++++++++
  1. The error[E0507] line names the rule that was broken. Look up the code with rustc --explain E0507.
  2. --> gives the file, line and column.
  3. The - marks are the other parts of the story: here, where the borrow started and where it is used later.
  4. The ^ marks where the compiler gave up. Read the marked lines in order, top to bottom.
  5. help: is a suggestion. It is often right. When it suggests .clone(), check first, because there is usually a fix that copies nothing.

Every lesson

  1. Read the Rust program, then the same program in your language below it.
  2. At the gotcha, look at the Rust code and guess what's wrong before you read the error.
  3. Copy the fixed version into your editor, then break it again on purpose.

45 lessons, 5 standard library pages and 3 more in Going further.