🦀 Rust Roadmap (на русском)
Полный курс по языку программирования Rust на русском языке: от первой строчки кода до асинхронности, embedded и WebAssembly. Каждый урок состоит из теории, практики и теста с ответами.
📢 t.me/rust_code — основной Telegram-канал с уроками и разбором кода для Rust-разработчиков.
- 25 уроков — от базового синтаксиса до прикладной разработки.
- Каждый урок построен по одной схеме: теория с примерами → практика с задачами → тест → разбор ответов.
- Только Rust 2021 / 2024 — современный идиоматичный код, актуальные крейты экосистемы.
- Без воды — только практически полезный материал.
| № | Урок | Темы |
|---|---|---|
| 1 | Введение в Rust | установка, cargo, hello world, структура проекта |
| 2 | Переменные и типы | let / mut, целые / плавающие, bool, char, кортежи, массивы, преобразования, переполнение |
| 3 | Управление потоком | if / else, loop, while, for, match, let-else, loop labels |
| 4 | Владение (ownership) | move, Copy, Clone, scope, Drop, замыкания и захват |
| 5 | Заимствование и ссылки | &T, &mut T, NLL, reborrow, elision, времена жизни |
| 6 | Slices, String, Vec | срезы, UTF-8, capacity, итерация по строкам |
| 7 | Structs и enums | tuple / unit-структуры, derive, match на enum, niche, builder |
| 8 | Generics и traits | мономорфизация, dyn vs impl, trait bounds, ассоциированные типы, перегрузка операторов |
| № | Урок | Темы |
|---|---|---|
| 9 | Lifetimes | элизия, 'static, HRTB, структуры со ссылками |
| 10 | Обработка ошибок | Result / Option, оператор ?, panic, thiserror, anyhow, FFI |
| 11 | Коллекции и итераторы | HashMap, BTreeMap, VecDeque, BinaryHeap, кастомные итераторы |
| 12 | Умные указатели | Box, Rc, Arc, RefCell, Mutex / RwLock, OnceLock, Cow, Weak |
| 13 | Многопоточность | потоки, Send / Sync, каналы, scoped threads |
| 14 | Async и Tokio | Future, async / await, рантайм tokio, select!, каналы |
| № | Урок | Темы |
|---|---|---|
| 15 | Макросы | macro_rules!, процедурные макросы, derive |
| 16 | Тестирование | unit, integration, doc-tests, property-based |
| 17 | Экосистема Cargo | workspaces, features, profiles, публикация |
| 18 | Unsafe и FFI | unsafe, raw-указатели, extern "C", bindgen |
| 19 | Веб с axum | роутинг, extractors, middleware, JSON, state |
| № | Урок | Темы |
|---|---|---|
| 20 | Базы данных: sqlx и diesel | пулы, миграции, транзакции, repository |
| 21 | gRPC с tonic | protobuf, streaming, interceptors, TLS |
| 22 | Embedded и no_std |
core / alloc, embedded-hal, RTIC, Embassy |
| 23 | WebAssembly | wasm-bindgen, web-sys, Yew / Leptos, WASI |
| 24 | Паттерны проектирования | newtype, builder, typestate, strategy, RAII |
| 25 | CLI-приложения | clap, anyhow, tracing, indicatif, ratatui |
- Установите Rust с rustup.rs и любой редактор с поддержкой
rust-analyzer(VS Code, Helix, Zed, RustRover). - Идите по урокам последовательно: каждый следующий опирается на предыдущий.
- Для каждого урока: прочитайте теорию → разберите код практики → решите задачи самостоятельно → пройдите тест и сверьтесь с ответами.
- Создавайте
cargo newпесочницу под каждый урок и экспериментируйте.
- Rust 1.75+ (
rustup update stable). - cargo — встроенный пакетный менеджер.
- rust-analyzer — LSP для подсветки и автодополнения.
- Терминал, базовое знакомство с Git и любым другим языком (для контекста).
# создать проект
cargo new my_project
cd my_project
# собрать и запустить
cargo run
cargo build --release
# тесты, проверки, форматирование
cargo test
cargo clippy
cargo fmt
# обновить зависимости
cargo update- t.me/rust_code — основной канал по Rust на русском, уроки и разборы кода.
- t.me/books_englishhh — англоязычные книги и материалы по Rust.
- t.me/ai_machinelearning_big_data — AI, ML, Big Data (полезно при работе с
candle,burn,tch-rs). - Папка с обучающими ресурсами — большая подборка каналов для разработчиков.
- Твой код на Rust компилируется, проходит тесты и является UB. Ты просто об этом не знаешь — про скрытые ловушки undefined behavior в безопасном на вид Rust-коде.
- Как Rust обманывает процессор: тайная жизнь niche-оптимизации, drop flags и MIR — внутренности компилятора и неожиданные оптимизации.
- Как Rust обманывает процессор. Часть 2: niche сквозь крейты, dropck, Pin и провенанс указателей — продолжение про Pin, dropck и провенанс.
- The Rust Book — главная книга, начинать отсюда. Русский перевод.
- Rust Book с интерактивными квизами — экспериментальная версия от Brown University.
- Rust by Example — концепции через работающие примеры.
- The Rustonomicon — тёмная сторона:
unsafe, lifetimes, layout. - The Rust Reference — формальная спецификация языка.
- Rust Async Book — асинхронность от создателей языка.
- Rust API Guidelines — как проектировать идиоматичные API.
- std documentation — стандартная библиотека (читать даже без запроса!).
- Rust Atomics and Locks — Mara Bos, бесплатно онлайн. Про многопоточность и memory ordering.
- Comprehensive Rust — курс от Google, 4 дня интенсива.
- 100 Exercises To Learn Rust — Luca Palmieri.
- Easy Rust — простыми словами для начинающих.
- Too Many Linked Lists — учим Rust через реализацию связных списков (классика!).
- Writing an OS in Rust — Philipp Oppermann, минимальная ОС с нуля.
- Crafting Interpreters — пишем интерпретатор (оригинал на Java/C, есть множество Rust-портов).
- Zero To Production In Rust — Luca Palmieri, веб-сервисы (платная, но стоит того).
- Rust продвинутый: лайфтаймы, async, unsafe и производительность — Внутри: async, unsafe, gRPC, lock-free, observability, Kafka, NATS, axum, tower, CI/CD и канареечный деплой. 21 модуль, 84 урока, 400+ проверочных шагов.
- Rust полный курс разработчика! С нуля до профи" — 6 модулей, 50 уроков, 143 теста. Ownership, borrowing, traits, async, Tokio, Axum, макросы, WASM — всё разложено по полочкам и закреплено практикой.
- Rustlings — 90+ интерактивных упражнений, обязательно в начале.
- Exercism Rust Track — задачи с менторскими ревью.
- Rust Quiz — каверзные вопросы по семантике от dtolnay.
- Rust Playground — экспериментировать без
cargo, смотреть MIR / LLVM IR / ASM. - Codewars — алгоритмические ката.
- Advent of Code — ежегодный декабрьский марафон, отлично заходит на Rust.
- CodeCrafters — пиши свой Redis / Git / Docker на Rust.
- This Week in Rust — еженедельный дайджест экосистемы. Подписка обязательна.
- Inside Rust Blog — что происходит внутри команды разработчиков.
- fasterthanli.me — Amos, глубокие технические статьи.
- Without Boats — блог одного из ключевых дизайнеров async Rust.
- Niko Matsakis — сооснователь языка, пишет про типовую систему.
- Manish Goregaokar — глубокие посты про unsafe и FFI.
- Jon Gjengset — многочасовые стримы по внутренностям (Crust of Rust).
- No Boilerplate — короткие мотивирующие видео про Rust.
- Logan Smith — продвинутые темы доступным языком.
- Let's Get Rusty — туториалы для начинающих.
- Code to the Moon — обзоры экосистемы и крейтов.
- chris biscardi — bevy, leptos, фронтенд на Rust.
rust-analyzer— LSP, основа продуктивности.cargo-edit—cargo add/rm/upgrade.cargo-watch— авто-перезапуск при изменениях.cargo-expand— посмотреть, во что разворачиваются макросы.cargo-nextest— быстрый тест-раннер.bacon— фоновый компилятор-watcher.
- @rust_chats — чат русскоязычных Rust-разработчиков (вопросы, помощь, обсуждение).
- Группа ВК «Rust IT» — русскоязычное сообщество ВКонтакте: новости, статьи, вакансии.
- Rust Users Forum — лучшее место для вопросов новичков.
- Rust Internals — обсуждение развития языка.
- r/rust — Reddit-сообщество.
- Rust Discord — официальный Discord.
- Rust Zulip — где сидят разработчики компилятора.
- Are We X Yet? — обзоры зрелости экосистемы (Are We Web Yet?, Are We Game Yet?, Are We Async Yet?).
- awesome-rust — главный список крейтов и проектов.
- Not Yet Awesome Rust — чего пока не хватает в экосистеме (повод законтрибьютить).
- Awesome Embedded Rust — embedded.
- Awesome WebAssembly — WASM.
Этот путь рассчитан примерно на 6–12 месяцев активного обучения. Каждый этап отвечает на три вопроса: что изучать, где изучать и зачем это нужно. Если ты совсем новичок — не перепрыгивай, порядок выбран не случайно.
💡 Общее правило для новичков: прочитай тему в The Rust Book → прочитай её же в Rust by Example → реши соответствующие упражнения в Rustlings. Три угла зрения на одну идею закрепляют её сильно лучше, чем один источник.
Что изучать:
- Установить
rustup— официальный менеджер тулчейнов. Он ставит компилятор (rustc), пакетный менеджер (cargo), форматтер (rustfmt), линтер (clippy) и позволяет переключаться междуstable/beta/nightly(rustup default stable,rustup toolchain install nightly). - Зафиксировать версию для проекта через файл
rust-toolchain.tomlв корне репозитория — чтобы все участники и CI собирали одним и тем же компилятором. - Редактор: VS Code + расширение rust-analyzer — самая дружелюбная связка для новичков. Альтернативы: RustRover (бесплатен для некоммерческого использования), Helix, Zed, Neovim + LSP. Включи в
settings.json"editor.formatOnSave": trueи"rust-analyzer.check.command": "clippy"— будет ловить проблемы прямо в редакторе. - Ежедневные команды cargo:
cargo new/cargo init— создание проекта;cargo check— быстрая проверка типов без кодогенерации (используй пока пишешь, в 5–10 раз быстрееbuild);cargo build(debug) /cargo build --release(с оптимизациями, разница в скорости часто 10–100×);cargo run/cargo run --release -- arg1 arg2(всё после--уходит в твою программу);cargo test/cargo test -- --nocapture(показывать вывод даже у прошедших тестов);cargo doc --open— генерирует и открывает документацию проекта со всеми зависимостями (включая stdlib);cargo add serde --features derive— добавить зависимость без ручной правкиCargo.toml;cargo clippy -- -D warnings— линтер; флаг превращает все варнинги в ошибки (полезно в CI).
Cargo.tomlминимум, который надо понимать:[dependencies],[dev-dependencies],[build-dependencies], секции[profile.dev]/[profile.release], фичи (features = ["derive", "json"]).- Полезные cargo-расширения сразу:
cargo install cargo-watch cargo-edit cargo-expand.cargo watch -x check -x test— пересборка/тесты на сохранение файла, экономит часы.
Где изучать:
- rustup.rs — установка одной командой.
- The Rust Book, гл. 1.
- The Cargo Book — особенно главы «Specifying Dependencies», «Cargo.toml format», «Profiles».
- Шпаргалка по cargo-командам: cheats.rs/#cargo.
Зачем это нужно: без рабочего окружения и правильных рефлексов (cargo check пока пишешь, cargo doc --open чтобы читать доки оффлайн, cargo clippy перед коммитом) Rust кажется сильно сложнее, чем есть. Один час, потраченный сейчас на настройку, экономит десятки часов на следующих этапах.
Мини-проект: Hello, world!, который читает имя из std::env::args, валидирует, что аргумент задан (если нет — выводит usage и завершает с кодом 1), и здоровается. Бонус: добавь зависимость anyhow через cargo add и используй anyhow::Result как тип возврата main.
Что изучать:
- Переменные:
let(по умолчанию неизменяемые),mut, константы (const NAME: T = ...— всегда с типом, должны быть compile-time),static(живёт всю программу). Shadowing — повторное связывание имени черезlet— идиома, а не баг: позволяет менять тип (let x = "5"; let x: u32 = x.parse()?;). - Целые типы:
i8/i16/i32/i64/i128/isizeиu8/u16/u32/u64/u128/usize.usize/isizeзависят от платформы (32 или 64 бит) и используются для индексации. Переполнение: в debug-сборке —panic, в release — wrap (тихая обёртка). Для явного поведения —checked_add,saturating_add,wrapping_add,overflowing_add. - Числовые литералы:
1_000_000(подчёркивания для читаемости),0xff,0b1010,0o755, суффиксы100u32,1.5f64. bool,char(4-байтный Unicode scalar value, не байт!), кортежи(i32, &str), массивы[T; N](размер в типе), срезы&[T]/&str(динамический размер, fat pointer).- Преобразования:
as— низкоуровневый каст (может молча терять биты);From/Into— безопасное расширение (u32 → u64);TryFrom/TryInto— может не получиться (i64 → i32). Идиома: предпочитайFrom/TryFromвместоasвезде, кроме horizontalных кастов внутри числовой работы. - Строки:
String(владеющая, на куче, мутабельная) vs&str(срез, обычно ссылка на литерал или частьString). Литералы"..."имеют тип&'static str. Грабли:Stringнельзя индексировать какs[0]— UTF-8 переменной длины; используй.chars(),.bytes(),.char_indices(). - Управляющие конструкции — это выражения, не операторы:
let max = if a > b { a } else { b }; let sum = loop { break 42; };
if,match,loop, блоки{ ... }— все возвращают значение. Точка с запятой превращает выражение в оператор (отбрасывает значение). match— главный инструмент Rust для разбора данных. Должен быть исчерпывающим: компилятор требует покрыть все варианты (или_).- Функции: возврат — последнее выражение без
;, либоreturn. Параметры по значению переносят владение (move), по&T— занимают. - Модули и видимость:
mod,pub,pub(crate),pub(super).use crate::foo::Bar. Файловая раскладка:mod foo;ищетfoo.rsилиfoo/mod.rs(новый стиль —foo.rs+foo/). - Doc-комментарии:
///для элементов,//!для модулей/крейтов.cargo docрендерит в HTML; примеры внутри них автоматически становятся doc-тестами и запускаются наcargo test.
Где изучать:
- The Rust Book, гл. 3–7 — основа основ. Прочитать до конца, не перепрыгивая.
- Rust by Example — параллельно с книгой, как «практический режим».
- Rustlings — упражнения, включая
variables,functions,primitive_types,vecs,move_semantics,structs,enums,strings. Делать все, не пропуская. - cheats.rs — однострочная шпаргалка по всему синтаксису, держать открытой.
Зачем это нужно: на этом этапе закладывается ритм работы с компилятором: пишешь → cargo check → читаешь ошибку → правишь. Все остальные этапы предполагают, что синтаксис у тебя уже не вызывает заминок.
Мини-проекты: калькулятор в CLI с + - * /, конвертер температур °C↔°F с валидацией ввода, FizzBuzz, угадай-число (с std::io для ввода и rand для случайного числа).
Что изучать:
- Модель памяти. Стек (быстрый, фиксированный размер) vs куча (
Box,Vec,String— динамический размер, аллокация дороже). Понимание, что где лежит, объясняет 90% «почему компилятор недоволен». - Ownership — центральная идея языка: у каждого значения ровно один владелец; когда владелец выходит из области видимости, вызывается
Drop, ресурс освобождается. Без GC, без ручногоfree. Это работает для любого ресурса, не только памяти: файловые дескрипторы, сокеты, блокировки — всё освобождается автоматически (RAII). - Move-семантика. Присваивание или передача значения по типу, не реализующему
Copy, переносит владение; использование исходной переменной после move — ошибка компиляции. Так Rust ловит use-after-free и double-free на этапе сборки. CopyvsClone.Copy— побитовое копирование, неявное (i32,bool,char, фиксированные массивы изCopy-типов).Clone— явная, потенциально дорогая копия (.clone(), всегда видно в коде). Тип не может бытьCopy, если содержит ресурс сDrop(например,String).- Заимствование.
&T— общая ссылка (только чтение, можно много);&mut T— эксклюзивная ссылка (один писатель). Borrow checker гарантирует: либо много читателей, либо один писатель. Это устраняет data races на этапе компиляции. - Времена жизни (lifetimes). Каждой ссылке компилятор приписывает «живёт не дольше, чем». В простых функциях лайфтаймы выводятся автоматически (lifetime elision rules — три правила в Rust Reference). Явная аннотация
fn longest<'a>(x: &'a str, y: &'a str) -> &'a strнужна, когда выходная ссылка зависит от нескольких входных. - Особый лайфтайм
'static— живёт всю программу. У строковых литералов тип&'static str. BoundT: 'staticозначает «тип не содержит ссылок с более коротким временем жизни» (это не «тип живёт вечно», частая путаница). - Слайсы.
&[T],&mut [T],&str— нормальная форма передачи коллекций в функции; принимай слайсы вместо&Vec<T>/&String. Это работает и дляVec, и для массивов, и для подсрезов&v[2..5]. - NLL (Non-Lexical Lifetimes). Современный borrow checker отслеживает использование, а не лексические скоупы. Поэтому
let r = &v; println!("{r}"); v.push(1);компилируется (последнее использованиеr— вprintln!). - Что нельзя в safe Rust из-за ownership: self-referential structs (структура со ссылкой на собственное поле — нужны
Pinи продвинутые паттерны), произвольные графы со взаимными ссылками безRc/Weak, мутабельные глобалы безMutex/OnceLock. Это не баги, а сознательные ограничения.
Где изучать:
- The Rust Book, гл. 4 (Понимание владения) и гл. 10 §3 (Lifetimes) — каноническое объяснение. Прочитать дважды, с интервалом в неделю.
- Rust by Example: Scoping rules, Borrowing, Lifetimes.
- Rustlings:
move_semantics,lifetimes,strings. - Rust Book с интерактивными квизами от Brown University — те же главы плюс квизы, ловящие типичные заблуждения именно про ownership. Сильно рекомендую.
- Crust of Rust: «Lifetime Annotations» (Jon Gjengset) — когда почувствуешь готовность к более глубокому разбору.
- The Rust Reference: Lifetime elision — формальные правила.
Зачем это нужно: именно ownership и lifetimes делают Rust Rust. Почти все «почему мой код не компилируется?!» сводятся к ним. Когда щёлкнет (обычно к 3-й неделе ежедневной практики), остальной язык становится лёгким.
Типичные грабли на этом этапе:
- «Я просто скопирую через
.clone()». Работает, но это анти-паттерн в горячем коде. Сначала попытайся передать ссылку. - «Не могу мутировать
Vec, пока итерирую». Правильно: либо собрать индексы и потом изменить, либо использоватьVec::retain/drain_filter. return &local_var— возврат ссылки на локальную переменную. Не компилируется, и слава богу.
Мини-проекты: функция longest(&str, &str) -> &str (из книги, но дописать варианты с разными лайфтаймами), парсер CSV (передача слайсов между функциями без копирования), стековый калькулятор на Vec<f64> с обработкой ошибок.
Что изучать:
struct: с именованными полями, tuple-структуры (struct Point(f64, f64)), unit-структуры (для маркеров и реализации трейтов). Деструктуризация:let Point { x, y } = p;.enum— это sum types, а не «нумерация констант». Каждый вариант может нести данные разного типа:enum Event { Click { x: i32, y: i32 }, Scroll(f32), Resize }. Так моделируются «значение — одно из этих вариантов» — основной инструмент для конечных автоматов и доменных моделей.Option<T>иResult<T, E>— ответ Rust наnullи исключения. Оба — обычные enum'ы из stdlib, никакой магии.Option::Noneвместоnull,Result::Errвместоthrow.- Pattern matching:
match,if let,while let,let-else(Rust 1.65+:let Some(x) = opt else { return; };). Так разбирают enum'ы и делают невалидные состояния непредставимыми. - Exhaustive matching и
#[non_exhaustive].matchпоenumобязан покрыть все варианты. Атрибут#[non_exhaustive]на публичном enum заставляет потребителей всегда писать_ => ...— позволяет добавлять варианты без breaking-изменений. impl-блоки: методы (&self,&mut self,self— последний потребляет значение), ассоциированные функции (безself, напримерString::new(),Vec::with_capacity(10)).- Трейты — интерфейсы Rust. Дефолтные реализации методов; авто-вывод стандартных через
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]. Важные стандартные:Debug/Display,PartialEq/Eq,PartialOrd/Ord,Hash,Default,Iterator,From/Into. From/Into/TryFrom/TryInto. РеализуйFrom—Intoпоявится автоматически. Идиома: всегдаimpl From<X> for Y, никогдаimpl Into(orphan rule + удобство для пользователей).- Дженерики:
fn largest<T: Ord>(items: &[T]) -> &T. Trait bounds (T: Ord),where-клаузы для читаемости при многих ограничениях,impl Traitв позиции аргумента/возврата (для краткости). - Trait objects:
dyn Trait,Box<dyn Trait>,&dyn Trait— runtime-полиморфизм. Статический диспатч (дженерики,impl Trait) — компилятор делает копии под каждый тип, нет накладных расходов; динамический (dyn Trait) — vtable + указатель, удобно для гетерогенных коллекцийVec<Box<dyn Trait>>. - Object safety. Не каждый трейт можно превратить в
dyn Trait: запрещены generic-методы,Selfв позиции возврата, ассоциированные константы. Еслиdyn Traitне компилируется — почти всегда нарушено object safety. - Orphan rule и blanket impls. Чтобы реализовать
Trait for Type, либо trait, либо type должны быть из твоего крейта. Blanket impl:impl<T: Display> ToString for T— реализация для всех подходящих типов сразу. - Итераторы и замыкания.
Iterator— самый используемый трейт. Цепочки.iter().filter().map().collect()— идиоматичный Rust. Замыкания:Fn(читает захваты),FnMut(мутирует),FnOnce(потребляет — например,move-замыкание со строкой). - Коллекции stdlib:
Vec<T>(динамический массив),HashMap<K, V>(хеш-таблица),HashSet<T>,BTreeMap/BTreeSet(упорядоченные),VecDeque(двухсторонняя очередь). Знай асимптотику основных операций.
Где изучать:
- The Rust Book, гл. 5–10, 13 — структуры, enum'ы, generics, trait'ы, lifetimes (повторно), итераторы и замыкания.
- Rust by Example: Custom Types, Conversion, Generics, Traits, Closures, Iterators.
- Rustlings:
structs,enums,options,error_handling,generics,traits,lifetimes,iterators. - Rust API Guidelines — чтобы сразу делать идиоматичные публичные типы.
- «Effective Rust» — главы 1–8 идеально ложатся именно на этот этап.
Зачем это нужно: struct + enum + traits + iterators — это то, как ты моделируешь предметную область в Rust. Когда начнёшь использовать enum для состояний и Option вместо null, целые классы багов исчезают на уровне типов.
Мини-проекты: телефонная книга в CLI (потом — сохранение/загрузка в JSON через serde), CLI todo-list, простой граф (HashMap<NodeId, Vec<NodeId>>) с поиском в ширину/глубину, парсер арифметических выражений через enum Expr { Num(f64), Add(Box<Expr>, Box<Expr>), ... } с интерпретатором.
Что изучать:
panic!,unwrap,expect— быстрый и грязный способ: программа падает при ошибке. Норм для прототипов, примеров из Rust Book, инвариантов «здесь по построению точноSome». Не норм для production-логики и публичных API библиотек.- Идиоматичная обработка:
Result<T, E>везде, оператор?для проброса ошибки одним символом.?автоматически вызываетFrom, конвертируя один тип ошибки в другой. - Свои типы ошибок через
thiserror— для библиотек, где потребителям нужно матчить конкретные варианты:#[derive(thiserror::Error, Debug)] pub enum MyError { #[error("io: {0}")] Io(#[from] std::io::Error), #[error("parse: bad value at line {line}")] Parse { line: usize }, }
anyhow— для приложений:anyhow::Result<T>,anyhow!для создания ошибки из строки,.context("loading config")для добавления контекста. Конкурент:color-eyre— то же самое, но с красивым выводом и поддержкой кастомных хендлеров.- Правило большого пальца: библиотеки →
thiserror(точные enum-ошибки); бинари / приложения →anyhow/eyre(контекст + цепочка причин). Не смешивай в одном крейте. - Конверсии
From/Into— как?автоматически превращаетio::ErrorвMyError.#[from]вthiserrorгенерируетimpl Fromза тебя. Result::map_err,.context(),.with_context(|| ...)— добавление контекста к ошибке без потери исходной причины (sourcechain).- Panic vs Result — когда что: Panic — невосстановимая ошибка (битый инвариант, баг). Result — ожидаемая (файла нет, parse failed).
unwrap()в production допустим только там, где доказать, что значение есть, проще, чем переписать код. - Тестирование:
- Юнит-тесты в
mod tests { #[test] fn name() { ... } }рядом с кодом. - Интеграционные — в
tests/(отдельные крейты, видят только публичный API). - Doc-тесты — примеры в
///-комментариях запускаются как тесты наcargo test. Сразу и документация, и проверка. #[should_panic(expected = "...")],#[ignore](для долгих, запуск черезcargo test -- --ignored).
- Юнит-тесты в
- Property-based тестирование:
proptestилиquickcheck. Вместо «проверить пару примеров» — задаёшь свойство и крейт генерирует сотни случайных входов, ищет минимальный контрпример. - Snapshot-тесты:
insta— особенно удобно для сложного вывода (JSON, HTML, дерева AST). Запустил, проверил глазами, утвердил — дальше тест ловит регрессии. - Бенчмарки:
criterion— статистически грамотные бенчи (встроенный#[bench]доступен только на nightly и проигрываетcriterionпо выводу и шуму).
Где изучать:
- The Rust Book, гл. 9 (ошибки), 11 (тесты), 14 §3 (doc-тесты).
- README
thiserrorи READMEanyhow— короткие, прочитать оба. - Статья: «Error Handling In Rust — A Deep Dive» (Luca Palmieri) — лучший разбор за один заход.
- «Beginner's guide to property-based testing in Rust».
Зачем это нужно: ошибки — это половина боевого кода. Result + ? делает их обработку приятной и явной — ты буквально не можешь молча проигнорировать ошибку. Тесты дают уверенность для рефакторинга; без них любое нетривиальное изменение страшно.
Мини-проект: CLI-утилита для валидации конфигов (JSON/TOML) — читает, парсит, возвращает список ошибок с номерами строк. Свой тип ошибки через thiserror, интеграционный тест на tests/, doc-тесты на публичные функции, proptest на парсер.
Что изучать:
Box<T>— аллокация на куче. Нужен, когда тип имеет известный размер на компиляции, но ты хочешь его на куче. Классика — рекурсивные типы:Безenum List { Cons(i32, Box<List>), Nil }
Boxрекурсивный enum имел бы бесконечный размер. Также используется дляBox<dyn Trait>и для возврата больших значений без копирования стека.Rc<T>— Reference Counted, разделяемое владение в одном потоке. Несколько владельцев, освобождается, когда последний уходит.Rc::clone(&rc)— дешёвая операция (инкремент счётчика), не глубокое копирование.Arc<T>— Atomic Reference Counted, потокобезопасная версияRc. Чуть медленнее из-за атомарных операций. Используй ровно тогда, когда данные пересекают границу потоков.- Циклические ссылки и
Weak<T>.Rc/Arcне освобождает циклы — это утечка памяти (не UB, но плохо). Для деревьев с обратными ссылками (parent ← child) используйWeakдля одного направления;Weak::upgrade()возвращаетOption<Rc<T>>. - Интериор-мутабельность. Как менять данные через
&T(общую ссылку). Обычное правило Rust говорит «нельзя» — эти типы являются спасательными люками с runtime-проверкой:Cell<T>— дляCopy-типов,get/setпо значению, без borrow. Очень дёшево, но только дляCopy.RefCell<T>— runtime-проверка borrow (borrow()/borrow_mut()); один поток. Грабли:borrow_mutpanics, если уже есть активный borrow — это runtime-аналог borrow checker'а.Mutex<T>— потокобезопасный, блокирует.mutex.lock().unwrap()—unwrapпотому что lock возвращаетResult(poisoning при панике в другом потоке).RwLock<T>— много читателей или один писатель, потокобезопасно. На сильной contention может страдать от writer starvation — для горячих структур иногда лучшеparking_lot::RwLockилиMutex.OnceLock<T>(stable с 1.70) /OnceCell<T>(одно-поточная) — записать один раз, читать многократно. Идеальная заменаlazy_static!для глобалов.LazyLock<T>(stable с 1.80) /LazyCell<T>— ленивая инициализация при первом доступе. Современная заменаonce_cell::Lazy.
Cow<'_, T>(Clone-On-Write) —Cow::Borrowed(&str)илиCow::Owned(String). Полезно для функций, которые обычно не модифицируют вход, но иногда должны (например, нормализация строк).Pin<T>— гарантия, что значение не сдвинется в памяти. Нужен для self-referential типов (typically — для async-future). На этом этапе достаточно знать, что он существует и зачем; глубокое погружение — на этапе 13.- Drop, RAII, drop order. Поля структуры дропаются в порядке объявления.
std::mem::drop(x)— явный ранний дроп. Не реализуйDropради привычки — большинству типов он не нужен. - Когда что выбирать (шпаргалка):
- один владелец на стеке → обычное значение;
- один владелец на куче →
Box<T>; - несколько владельцев в потоке →
Rc<T>; - несколько владельцев между потоками →
Arc<T>; - мутация через общую ссылку, один поток →
RefCell(илиCellдляCopy); - мутация между потоками →
Mutex/RwLock/ атомики.
Где изучать:
- The Rust Book, гл. 15 (умные указатели), гл. 16 (overlap с многопоточностью).
- Rust by Example: Box, Rc, Cell/RefCell.
- Классика: «Learn Rust With Entirely Too Many Linked Lists» — реализуем 6 связных списков, каждый учит свой умный указатель. Тот самый туториал на этот этап, обязательно.
- docs.rs/once_cell — переходное чтение перед
OnceLock/LazyLockиз stdlib.
Зачем это нужно: без умных указателей Rust ощущается зажатым («как мне это пошарить?!»). С ними понимаешь, почему обычные правила Rust такие строгие — они дают статические гарантии, а эти типы — аккуратно подписанные исключения с явной runtime-стоимостью.
Мини-проект: двусвязный список (Rc + RefCell + Weak) или дерево, где дети знают родителя; кэш с OnceLock для ленивого вычисления тяжёлых констант.
Что изучать:
std::thread::spawn— создаёт OS-поток. Замыкание захватывает данные; безmoveRust не даст захватить переменные с лайфтаймом (нет гарантий, что они переживут поток).std::thread::scope(stable с 1.63) — scoped threads. Позволяет потокам безопасно заимствовать данные из родителя; scope ждёт завершения всех порождённых потоков. Современный дефолт для параллельной обработки локальных данных.SendиSync— два маркерных трейта, на которых строится thread safety:T: Send— значение можно передать в другой поток.T: Sync— на значение можно сослаться из другого потока (&T: Send).Rc— неSend(счётчик не атомарный);Arc—Send. Компилятор не даст пошаритьRcмежду потоками — гарантия, не предупреждение.
- Разделяемое состояние:
Arc<Mutex<T>>,Arc<RwLock<T>>— каноническая обёртка для shared mutable state. СтандартныеMutex/RwLockна Linux реализованы через futex и разумно быстры; для интенсивно конкурируемых случаев —parking_lot(короче, быстрее, без poisoning). - Каналы (message passing). Идиома Rust: «не шарьте память, передавайте сообщения».
std::sync::mpsc— multi-producer single-consumer, в stdlib.crossbeam-channel— быстрее, поддерживаетselect, bounded/unbounded.flume— современная альтернативаmpscс async-API.
- Атомики:
AtomicUsize,AtomicBool,AtomicPtr— целочисленные операции без блокировок. Memory ordering (Relaxed,Acquire,Release,AcqRel,SeqCst) — глубокая тема; новичкам хватит правила «если не уверен —SeqCst, не теряя в корректности; оптимизировать упорядочения — после освоения этапов 13–14». - Параллельные итераторы —
rayon.v.par_iter().map(...).sum()— прозрачное распараллеливание data-parallel вычислений на work-stealing thread pool. Чаще всего этого достаточно: не надо вручную поднимать потоки. - Условные переменные и барьеры:
Condvar,Barrier— низкоуровневая синхронизация. На практике редки; обычно лучше канал. - Деадлоки. Rust не защищает от deadlocks (защищает только от data races). Правило: всегда захватывай мьютексы в одном порядке; не вызывай чужой код, держа lock; используй
tokio::sync::Mutexилиparking_lot::Mutexбез poisoning, если poisoning не нужен. thread_local!— данные, локальные для потока. Полезно для thread-local буферов и счётчиков.
Где изучать:
- The Rust Book, гл. 16 (Бесстрашная многопоточность).
- Rust Atomics and Locks (Mara Bos) — бесплатно онлайн, та самая книга по теме. Читать после главы Rust Book — в этой книге плотный практический разбор атомиков с нуля и реализация
Mutexсвоими руками. - README
rayonи его docs — короткие, сразу полезные. - «Crust of Rust: Atomics and Memory Ordering» (Jon Gjengset).
Зачем это нужно: многопоточность — место, где большинство языков пропускают баги (data races, dangling references). Rust ловит data races на компиляции через Send/Sync — это настоящая суперсила, ради которой многие выбирают язык.
Мини-проект: параллельный word-counter (rayon::par_iter + объединение через fold/reduce); thread-pool с очередью задач через crossbeam-channel; параллельный обработчик изображений (поток-производитель читает с диска, пул-потребителей применяет фильтр).
Что изучать:
- Трейт
Future— async-кирпичик Rust. Future — это стейт-машина, которую рантайм опрашивает (poll) до готовности. Ключевое: future ничего не делает, пока ты не сделаешь.awaitили не отдашь его рантайму (tokio::spawn). Это отличается от JS-промисов, которые исполняются eager. - Синтаксис
async fnи.await.async fn foo() -> T— этоfn foo() -> impl Future<Output = T>..awaitприостанавливает выполнение, возвращая контроль рантайму, до готовности future. - Рантаймы. В 95% случаев —
tokio(де-факто стандарт; многопоточный планировщик, богатая экосистема). Альтернативы:async-std(API ближе к stdlib, развитие замедлилось),smol(минималистичный). Не смешивай рантаймы в одном бинаре. tokio::main:Под капотом —#[tokio::main] async fn main() -> anyhow::Result<()> { ... }
Builderдля рантайма; для production-сервисов часто пишут конфигурацию рантайма вручную.tokio::spawnvstokio::task::spawn_blocking.spawn— для async-задач (требуетSend + 'staticот future).spawn_blocking— переносит синхронную работу в отдельный thread pool, чтобы не заморозить async-планировщик. Любая блокирующая операция (std::fs, тяжёлый CPU-кранч, синхронный SDK) обязана идти черезspawn_blocking.- Стримы (
futures::Stream,tokio_stream) — асинхронные итераторы.while let Some(x) = stream.next().await { ... }. Backpressure обрабатывается естественно через.await. tokio::select!— гонка нескольких future; первый завершившийся выигрывает, остальные отменяются. Это источник тонких багов «cancellation safety»: если внутри ветки была накопленная работа без.await-точек до commit'а — она теряется. Читай документациюselect!целиком, не по диагонали.JoinSet(tokio::task::JoinSet) — динамический набор задач, можноspawnновые в процессе иjoin_next().awaitдля забора результатов. Современный способ организовать «обработать N запросов параллельно с лимитом».Send + 'staticловушки. Future, передаваемая вspawn, должна бытьSend + 'static. Если внутри держитсяRcили non-Send-тип через.await— компилятор объяснит, но сообщение бывает длинное. Обычное лекарство: заменитьRcнаArc, либо вытащить non-Sendза пределы.await.- Async-сеть и HTTP: TCP/UDP через
tokio::net; HTTP-клиентreqwest; сервер —axum(наtokio+tower) илиactix-web. - Каналы для async:
tokio::sync::mpsc/oneshot/broadcast/watch— каждая со своим назначением.oneshot— для «отправить один ответ»;watch— для «последнее значение видно всем». - Async-Mutex.
tokio::sync::Mutexнужен только если lock держится через.await. В остальных случаях —std::sync::Mutexилиparking_lot::Mutexбыстрее (нет async-overhead). - Логирование и диагностика:
tracing+tracing-subscriber— стандарт для async; spans корректно прослеживаются через task'и.tokio-console— интерактивный отладчик задач (вид процессов вtop, но для tokio).
Где изучать:
- The Rust Book, гл. 17 (Async и await — в новых редакциях) — вводное.
- Asynchronous Programming in Rust — официальная книга по async.
- Tokio Tutorial — пошаговое создание Mini-Redis.
- Видео: «The What and How of Futures and async/await in Rust» (Jon Gjengset).
- Alice Ryhl — «Actors with Tokio» и «Shared mutable state in Rust» — короткие практические заметки от core-разработчика
tokio.
Зачем это нужно: большинство production-Rust сервисов — async (web-бэкенды, прокси, сетевые тулзы, БД-клиенты). Поверхностного знания tokio мало: cancellation safety, Send-ловушки и spawn_blocking регулярно ломают код тех, кто ими не озаботился.
Мини-проекты: многопоточный TCP-эхо-сервер (tokio::net::TcpListener); HTTP-агрегатор, который параллельно опрашивает 10 API через reqwest + JoinSet и собирает ответы; mini-Redis (TCP + RESP-протокол + HashMap под Mutex).
Что изучать:
- Декларативные макросы —
macro_rules!. Pattern-match по токенам, разворачиваются в код. Ты уже пользуешься:println!,vec!,assert_eq!,format!— это они.- Фрагменты:
expr,ident,ty,pat,block,stmt,path,tt(token tree),item. Не путай — каждый позволяет ровно своё. - Повторители:
$( ... ),*— ноль или больше через запятую;$( ... )+— один или больше. - Гигиена.
macro_rules!гигиеничен по умолчанию: имена, объявленные внутри макроса, не пересекаются с внешними. Это не#defineиз C.
- Фрагменты:
- Процедурные макросы — три вида:
- derive (
#[derive(MyTrait)]) — добавляет реализацию трейта; - атрибутные (
#[my_attribute] fn ...) — преобразуют элемент целиком (используется в#[tokio::main],#[tracing::instrument]); - функциональные (
my_macro!(...)) — выглядят как обычные макросы, но работают с любыми токенами. Живут в отдельном крейте сproc-macro = trueвCargo.toml.
- derive (
- Тройка для проц-макросов:
syn— парсит входящие токены в AST Rust;quote— генерирует Rust по шаблону (quote! { fn #name() {} });proc-macro2— стабильная обёртка над нестабильнымproc_macroAPI; нужна, чтобы код проц-макроса можно было юнит-тестировать безrustc.
darling— высокоуровневая обёртка надsynдля парсинга атрибутов#[my_macro(field = "value", flag)]. Сильно сокращает derive-макрос.trybuild— тестирование, что неправильное использование макроса даёт ожидаемое сообщение об ошибке. Стандарт для проверки UI proc-макросов.cargo expand(изcargo install cargo-expand) — посмотреть, во что разворачивается макрос. Незаменимо при отладке. Работает и дляmacro_rules!, и дляderive.- Когда стоит писать макрос: когда устранение бойлерплейта реально окупает усложнение чтения. Часто лучше функция или дженерик, а не макрос.
Где изучать:
- The Rust Book, гл. 19 §6 (Макросы) — мягкое введение.
- The Little Book of Rust Macros — исчерпывающий справочник по
macro_rules!, читать целиком. proc-macro-workshopот David Tolnay — упражнения, через которые проходят все, кто всерьёз пишет проц-макросы. Материал на 1–2 выходных.- Документация
synиquoteс примерами.
Зачем это нужно: даже если своих макросов писать не будешь, чтение чужих и понимание, что генерируется при #[derive(Serialize, Deserialize)] или #[tokio::main], делает экосистему прозрачной. И сокращает «магия Rust» до «это вот такой код, я могу его прочитать через cargo expand».
Мини-проект: свой derive(Builder) — для struct User { name: String, age: u32 } сгенерировать UserBuilder с цепочечными сеттерами и методом build() -> Result<User, _>. Это упражнение #2 из proc-macro-workshop.
Что изучать:
- Что реально открывает
unsafe(всего пять «суперсил»): разыменование сырых указателей; вызовunsafe-функций; доступ/изменение мутабельныхstatic; реализацияunsafe-трейтов; доступ к полямunion. Всё.unsafeне отключает borrow checker и не делает Rust C-подобным — он просто говорит «здесь я беру на себя инварианты, которые компилятор не может проверить». - Контракт безопасности. Каждая
unsafe fnобязана иметь блок/// # Safetyв doc-комментарии, перечисляющий инварианты вызывающего. Это часть API, а не пожелание. - Сырые указатели:
*const T,*mut T. Не имеют гарантий лайфтайма, могут быть null, могут указывать на освобождённую память. Создание сырого указателя — safe; разыменование — unsafe. MaybeUninit<T>— корректный способ работать с неинициализированной памятью.mem::uninitialized()deprecated и UB. Паттерн:let mut x = MaybeUninit::<T>::uninit(); ptr::write(x.as_mut_ptr(), value); let x = unsafe { x.assume_init() };.mem::transmute— почти всегда не то, что нужно. Крайний случай. Сначала смотриas,From/Into,bytemuck/zerocopy.- Strict Provenance API (стабилизируется):
ptr.addr(),ptr::with_addr,expose_addr. Аккуратная работа с указателями как с числами; устраняет класс UB при оптимизациях. - FFI с C:
- Атрибуты layout:
#[repr(C)](как в C),#[repr(transparent)](как у внутреннего поля — для newtype-обёрток без overhead),#[repr(packed)](без выравнивания — осторожно: ссылки на packed-поля недопустимы),#[repr(u8)]для enum-discriminant. - Panic через границу FFI — UB. Оборачивай экспортируемые функции в
std::panic::catch_unwind, превращая панику в код ошибки. - Miri — интерпретатор Rust, который ловит UB в твоём
unsafe-коде (use-after-free, неинициализированные чтения, выход за границу, нарушение алиасинга). Прогоняй критичные тесты черезcargo +nightly miri test. Это самый дешёвый способ найти ошибкуunsafe. - AddressSanitizer / ThreadSanitizer / MemorySanitizer / LeakSanitizer через nightly:
RUSTFLAGS="-Z sanitizer=address" cargo +nightly test. Дополняет Miri (ловит то, что Miri не моделирует, например, реальные heap corruption).
Где изучать:
- The Rustonomicon — главная книга про unsafe. Читать после уверенного safe Rust. Особое внимание главам про aliasing, variance, drop check.
- The Rust Reference: Unsafety — формальный справочник.
- «Learn Rust the Dangerous Way» — пошаговый перенос C-программы в
unsafeRust, потом — итеративная замена на safe. - Документация
bindgenиcxx. - Miri README.
Зачем это нужно: unsafe нужен на стыке с C-библиотеками, для нестандартных структур данных (свои аллокаторы, lock-free очереди), для перформанс-критичного кода (zero-copy парсеры, FFI без копирования). 99% Rust-кода — safe; unsafe — это инструмент, к которому подходят с осторожностью и доказательством корректности.
Мини-проект: написать safe-обёртку над небольшой C-библиотекой (например, libsodium или zlib) через bindgen, валидируя инварианты на границе и закрывая unsafe блоком #![deny(unsafe_op_in_unsafe_fn)]. Прогон тестов под Miri.
Что изучать — по доменам:
- Веб-бэкенды.
axum— рекомендую как дефолт (tokio+tower, отличная типизация, активная разработка);actix-web(зрелый, очень быстрый);rocket(приятный декларативный API);poem. HTTP-крейты под капотом:hyper,tower(composable middleware: rate-limiting, retry, timeout, load shedding),tower-http(CORS, compression, tracing, auth). - Базы данных.
sqlx— async, проверка SQL на компиляции (макросquery!ходит в живую БД во время сборки), современный дефолт;diesel(sync ORM с сильной типизацией и миграциями);sea-orm(async ORM, ближе к ActiveRecord);redis;mongodb. Миграции —sqlx-cli,diesel migration,refinery. - Сериализация.
serde— тот самый фреймворк, де-факто стандарт. Поддерживает JSON (serde_json), YAML (serde_yaml), TOML (toml), MessagePack,bincode,postcard(для embedded),prostиprotobuf(Protocol Buffers). - CLI.
clap(парсинг аргументов, derive-API, генерация completions для bash/zsh/fish),structopt(исторический предокclapderive — теперь не нужен, всё вclap v4),dialoguer(интерактивные промпты),indicatif(прогресс-бары),console(цвета, стили в терминале). - Логирование и трассировка.
tracing+tracing-subscriber— современный дефолт (структурированные логи, spans, OpenTelemetry-интеграция). Старыйlogещё жив и хорош для библиотек (нейтральный фасад). Не путай:tracingдля приложений,logдля библиотек, которые не хотят форсить выбор системы логирования. - Конфигурация:
config(слои: файл + env + override),figment(от автора Rocket, гибче). Загрузка.env—dotenvy(форкdotenv, который не поддерживается). - HTTP-клиент.
reqwest— дефолт (async, JSON, мультипарт, прокси). Альтернативы:ureq(sync, минимум зависимостей),hyper(низкий уровень, под нестандартные задачи). - WebSockets:
tokio-tungstenite, сервер наaxumчерезaxum::extract::WebSocketUpgrade. - gRPC:
tonic— async-gRPC наtokio+prost. - CLI-утилиты для разработчиков:
cargo-edit,cargo-watch,cargo-expand,cargo-outdated,cargo-audit(CVE),cargo-deny(банлисты лицензий и крейтов),cargo-nextest(быстрый тест-раннер, в 2–3 раза быстрееcargo testна больших проектах),cargo-llvm-cov(покрытие кода). - Дата/время:
chrono(классика, много API),time(современнее, сno_std),jiff(новый, с правильной работой с таймзонами от автораripgrep). - Регулярки и парсинг:
regex,nom(комбинаторный парсер),winnow(наследникnomv8 с переписанным API),pest(PEG, грамматика отдельным файлом). - Шаблонизаторы:
askama(compile-time, типобезопасен),tera(runtime, как Jinja2),maud(HTML как макрос Rust).
Где изучать:
- Awesome Rust — каталог крейтов и проектов.
- lib.rs — альтернатива crates.io с более удобной навигацией и категоризацией.
- «Zero To Production In Rust» (Luca Palmieri) — лучшая книга по практическому веб-бэкенду на Rust (
actix-web+sqlx+tracing+ Docker). Если делаешь web — must-read. - «Rust for Rustaceans» (Jon Gjengset) — для перехода с уверенного среднего на продвинутый.
- Официальная документация каждого крейта на docs.rs.
Зачем это нужно: одно дело — знать язык, другое — собрать рабочий сервис. Этот этап превращает «я могу написать функцию» в «я могу выкатить REST-API в Docker с миграциями БД, логами в JSON и метриками в Prometheus».
Мини-проект: REST-API на axum + sqlx + Postgres с миграциями, аутентификацией (JWT через jsonwebtoken), tracing для логов, tower-http для CORS/compression, тестами в tests/ и Dockerfile на multi-stage. Это — шипуемый проект уровня джуна-мидла.
Что изучать:
- Профилирование на уровне CPU и памяти. Снятие flamegraph'ов, поиск горячих точек, анализ кеш-промахов и аллокаций. Инструменты:
perf+ cargo-flamegraph (Linux), Instruments (macOS),samply(кросс-платформенно),heaptrack,dhat. - Микрооптимизации и low-level perf. SIMD через
std::simd(nightly) илиstd::arch(stable), хинты#[inline]/#[cold], struct-of-arrays vs array-of-structs, cache-friendly layout, выравнивание (#[repr(C, align(64))]). - Fuzz-тестирование и property-based.
cargo-fuzz(libFuzzer),afl.rs; property-based —proptest,quickcheck, снапшот-тесты —insta. - Чтение исходников зрелых крейтов по нарастающей сложности:
itertools→serde→tokio→hyper→rustc. Это самый быстрый путь от среднего уровня к продвинутому. - Open-source-вклад. Бери
E-easy/good-first-issueв любом популярном крейте. Ревью от мейнтейнеров — лучший ускоритель роста. - Публикация своего крейта на crates.io: хорошие доки, CI на GitHub Actions, семвер,
cargo-semver-checksперед каждым релизом. - Nightly-фичи и RFC-процесс. Читай Inside Rust Blog,
rust-lang/rfcs, подпишись на This Week in Rust.
Где изучать:
- The Rust Performance Book — https://nnethercote.github.io/perf-book/
- «Writing High-Performance Rust» (видеосерия Logan Smith и fasterthanli.me).
- Зеркала лекций по
rustcот разработчиков компилятора на YouTube. - Канал @rust_code — разборы кода и идиом, по которым удобно сверяться.
Зачем это нужно: на этом уровне ты перестаёшь учить Rust и начинаешь думать на Rust. Лучшие инженеры публикуют библиотеки, которыми пользуются другие, шлют фиксы апстрим и понимают компромиссы дизайнеров языка.
Мини-проект:
- Возьми любой свой крейт уровня этапа 10, прогоняй его через
cargo-fuzz,proptest,criterion— найди и почини хотя бы одну реальную проблему. - Сделай PR в популярный крейт (например,
tokio,serde,clap,reqwest) — пусть даже небольшой фикс доки или теста.
Этапы ниже не обязательно идти строго по порядку — выбирай ту ветку, которая ближе к твоей предметной области (web, embedded, ML, gamedev, distributed systems). Но все они опираются на уверенное прохождение этапов 1–11.
Что изучать:
- HRTB (Higher-Ranked Trait Bounds,
for<'a>) и GAT (Generic Associated Types) — позволяют выражать «лайфтайм-семейства» и абстракции, которые на обычных дженериках просто не записываются (например, лениво возвращающиеся итераторы со ссылками на собственные данные). - Associated types vs дженерики. Когда выбирать
type Item;(одна реализация на тип), а когда<T>(много реализаций для одного типа). Рассмотри это на примерахIteratorиAdd<T>. PhantomData, zero-sized types, type-level состояния. Кодируй состояния протокола в типах (Builder<Unbuilt>→Builder<Built>), чтобы неправильное использование становилось ошибкой компиляции. Это паттерн typestate.- Sealed traits — закрытые расширяемые API: только модуль-владелец может реализовать трейт у новых типов, потребители — нет.
- Newtype-паттерн (
struct UserId(u64);) — разные типы для разных смыслов без рантайм-стоимости. Защищает от смешиванияUserIdиOrderId. - Variance: covariance, contravariance, invariance. Почему
&mut Tинвариантен, а&Tковариантен. - Auto-traits, negative impls (
!Send,!Sync),?Sized, DST (dynamically sized types).
Где изучать:
- The Rustonomicon — https://doc.rust-lang.org/nomicon/ (главы про variance и DST).
- The Rust Reference — https://doc.rust-lang.org/reference/ (раздел про trait bounds).
- Серия «Pretty State Machine Patterns in Rust» — про typestate.
- Jon Gjengset, плейлист «Crust of Rust» на YouTube — лучший разбор GAT, HRTB и subtyping на практике.
Зачем это нужно: даёт инструменты для «компилятор-как-теорема» подхода: API становятся такими, что неправильное использование в принципе невозможно. Это отличает middle от senior'а в Rust.
Мини-проект:
- Спроектируй type-state API для конечного автомата (HTTP-парсер, протокол хендшейка) — пусть некорректные переходы становятся ошибкой компиляции.
- Реализуй sealed trait для расширяемого API.
Что изучать:
- Внутренности
Future:Poll::Ready/Poll::Pending,Pin,Unpin, self-referential типы и почему они вообще нужны. - Устройство async-рантайма: reactor (epoll/kqueue/io_uring), executor, waker, task scheduling. Прочитай минимальный executor (например,
futures::executor) от и до. - Cooperative scheduling и проблема блокирующих вызовов в async. Когда нужен
tokio::task::spawn_blocking,LocalSet,JoinSet. - Cancellation safety и почему
tokio::select!опасен, если не понимать его. Что значит «фьючи могут быть брошены в любой await-точке». - Структурированная конкурентность.
tokio-util,async-scoped,JoinSet. Идея: ни одна задача не переживает свой scope. - Backpressure в стримах (
futures::Stream,tokio_stream). Как не перегрузить медленного потребителя. async fnв трейтах (стабильны с 1.75) и#[async_trait]— когда нужен какой.- Отладка async:
tokio-console,tracingspans,tokio::time::pause()для детерминированных тестов.
Где изучать:
- «Asynchronous Programming in Rust» — https://rust-lang.github.io/async-book/
- Tokio Tutorial — https://tokio.rs/tokio/tutorial
- Серия Alice Ryhl «Actors with Tokio» и «Shared mutable state in Rust».
- Without.Boats — блог одного из дизайнеров async/await.
Зачем это нужно: большинство production-Rust проектов — async (web, сеть, БД). Поверхностного знания tokio мало: cancellation safety и Pin регулярно ломают код тех, кто их не понял.
Мини-проект:
- Напиши свой простейший async-executor на базе
futures::task::Waker— поймёшь, как всё устроено внутри. - Реализуй mini-Redis (TCP-сервер с pub/sub) на чистом
tokio, добавьtracingиtokio-console.
Что изучать:
- Cache-friendly структуры, false sharing, padding. Почему
Vec<Struct>часто медленнее, чем struct-of-arrays. - SoA vs AoS (struct of arrays) — выбор раскладки, который часто доминирует в перформансе горячих циклов.
- Branch prediction, хинты
std::hint::likely/unlikely,black_boxдля бенчмарков. - SIMD:
std::simd(nightly, переносимый),std::arch(stable, платформенные интринсики), крейтwideиpulp. - Allocator API, кастомные аллокаторы:
bumpalo,mimalloc,jemallocator. - Arena-аллокация:
typed-arena,bumpalo— критично для парсеров и компиляторов. - Zero-copy парсинг:
nom,winnow,zerocopy,rkyv. - Профилирование и анализ:
perf,cargo-flamegraph,samply,hyperfine,cargo-bloat,cargo-show-asm. - Benchmark-driven development через
criterionиiai.
Где изучать:
- The Rust Performance Book — https://nnethercote.github.io/perf-book/.
- «Algorithmica» (Sergey Slotin) — https://en.algorithmica.org/hpc/ — общие принципы HPC, применимы к Rust.
- Видео Logan Smith и Amos (fasterthanli.me) на YouTube.
Зачем это нужно: Rust выбирают там, где важна производительность (БД, бэкенды, парсеры, игровые движки, embedded). Без этого этапа Rust используется как «более безопасный Go», а не как замена C++.
Мини-проект:
- Возьми один из своих крейтов, замерь baseline через
criterion, попробуй ускорить в 2–10× через SIMD, arena-аллокацию или zero-copy парсинг. - Реализуй простой ray-tracer или JSON-парсер и оптимизируй до уровня serde_json/sonic-rs.
Что изучать:
- Формальная верификация: Kani (model checker от AWS), Prusti (на основе Viper), Creusot.
- Model checking конкурентности:
loom— перебор всех возможных переплетений потоков;shuttle— randomized concurrency testing. - Sanitizers через nightly:
-Z sanitizer=address|thread|memory|leak. Помогают найти UB вunsafeкоде. - Mutation testing:
cargo-mutants— оценивает, насколько твои тесты реально проверяют логику. - Аудит зависимостей:
cargo-audit(CVE),cargo-deny(лицензии + банлисты),cargo-vet,cargo-geiger(поискunsafe). - Supply-chain security: reproducible builds, SBOM, проверки на typo-squatting.
- Безопасный FFI: ABI-стабильность,
#[repr(C)], корректное распространение panic'ов через границу языка,catch_unwind.
Где изучать:
- The Rustonomicon — https://doc.rust-lang.org/nomicon/ (про UB и sound
unsafe). - RustSec Advisory DB — https://rustsec.org/.
- Туториалы Kani и Loom в их репозиториях.
- «Learn Rust the Dangerous Way» — пошаговое освоение
unsafe.
Зачем это нужно: в инфраструктурных и крипто-крейтах ошибки означают потерю денег и данных. Эти инструменты — стандарт в крупных Rust-кодовых базах (AWS, Google, Mozilla, Cloudflare).
Мини-проект:
- Возьми любой свой
unsafe-блок и докажи его корректность через Kani или хотя бы прогон под Miri и AddressSanitizer. - Настрой CI с
cargo-audit,cargo-deny,cargo-mutantsдля одного из своих крейтов.
Что изучать:
- Идиоматичный Rust: builder, typestate, RAII-guards (
MutexGuard,Drop), newtype. - Hexagonal / Clean architecture без DI-фреймворков. В Rust DI делается через дженерики и трейты, а не через рантайм-контейнеры. Изучи, как структурировать большой сервис без Spring-подобных фреймворков.
- Error handling: библиотека vs приложение. В библиотеках —
thiserror+ конкретные enum-ошибки; в приложениях —anyhow/eyre/color-eyre+ контекст. Эти две стратегии нельзя смешивать. - Антипаттерны:
- борьба с borrow checker через
.clone()везде («clone-driven development»); - избыточное
Arc<Mutex<_>>там, где хватило бы канала или&mut; unwrap()в production-коде;- god-структуры с десятками полей и lifetimes.
- борьба с borrow checker через
- Композиция вместо наследования. Enum-полиморфизм vs trait objects (
dyn Trait) — когда что выбирать. - Workspace-структура: разделение
-core,-cli,-server,-macrosкрейтов; чёткие границы абстракций.
Где изучать:
- Rust Design Patterns — каноническое собрание идиом.
- «Rust API Guidelines» — как делать публичные API.
- «Effective Rust» Дэвида Дрисдейла — must-read после первого реального проекта.
- Доклады с RustConf и EuroRust на YouTube.
Зачем это нужно: код, который компилируется и проходит тесты, ещё не идиоматичен. Хорошая архитектура делает Rust-проект приятным в поддержке через год. Без этого ты пишешь «Rust как Go» или «Rust как C++» и теряешь половину преимуществ.
Мини-проект:
- Перепиши один из своих крейтов в hexagonal-стиле: ядро без I/O + адаптеры (БД, HTTP, CLI) как отдельные модули.
- Сделай аудит чужого open-source-крейта с точки зрения API guidelines.
Что изучать:
- Прямая работа с syscalls:
mio,epoll/kqueue/io_uringнапрямую через крейтыio-uring,rio. - Async-рантаймы для I/O:
tokio-uring,glommio(thread-per-core, полезен для БД и сетевых сервисов с предсказуемой латентностью),monoio. - Shared memory,
mmap:memmap2для memory-mapped файлов; работа с большими данными без копирования. - Сигналы Unix:
signal-hook,nixкрейт для POSIX API; процессы, pipes, fork/exec. - Свой аллокатор и свой
Future-executor с нуля. Лучший способ понять, как работает Rust-рантайм. - Kernel-разработка: Rust в Linux kernel (Rust for Linux), Redox OS, Theseus.
- Bare-metal:
#![no_std],corevsallocvsstd, panic-handler, custom target. Bootloader и минимальная ОС — Philipp Oppermann «Writing an OS in Rust».
Где изучать:
- «The Linux Programming Interface» (Michael Kerrisk) — фундамент по UNIX API, переносится на Rust один в один.
- «Writing an OS in Rust» — https://os.phil-opp.com/ (одна из лучших обучающих серий вообще).
- Документация Rust for Linux — https://rust-for-linux.com/.
Зачем это нужно: Rust изначально создавался для системного программирования. Эта ветка ведёт к работе над ядрами, гипервизорами, БД, рантаймами и низкоуровневой инфраструктурой — нишам, где Rust сейчас вытесняет C/C++.
Мини-проект:
- Напиши свой простейший event loop поверх
io_uringилиepoll. - Сделай минимальный
#![no_std]бинарь под QEMU, который выводит «hello» в VGA-буфер.
Что изучать:
- Реализация сетевых протоколов с нуля: Redis-протокол (RESP), HTTP/1.1 — отличные учебные задачи.
- Алгоритмы консенсуса: Raft через
openraft, gossip-протоколы (например, SWIM). - QUIC и HTTP/3:
quinn; HTTP/2 streaming, HPACK. - gRPC: streaming, interceptors, middleware в
tonic. - Observability в распределёнке: OpenTelemetry,
tracing-opentelemetry, метрики черезmetricsилиprometheus. - Надёжность: идемпотентность, retry с jitter, circuit breaker, rate limiting через
towerиtower-http. - Архитектурные паттерны: event sourcing и CQRS, saga, outbox pattern.
Где изучать:
- «Designing Data-Intensive Applications» (Martin Kleppmann) — теория, применимая к любому языку.
- Официальный Tokio Tutorial раздел про Mini-Redis.
- Доклады с RustConf про
towerиtonic. - Реальные кодовые базы:
tikv,materialize,databend,risingwave— это лучшие учебники по распределённому Rust.
Зачем это нужно: Rust популярен в инфраструктурных стартапах (TiKV, Materialize, Databend, Linkerd, Vector, Tremor). Это самая «денежная» ниша Rust в индустрии.
Мини-проект:
- Реализуй mini-Redis с поддержкой репликации (одна нода-лидер, несколько read-replica).
- Подними gRPC-сервис на
tonicс трассировкой черезtracing+ Jaeger/Tempo.
Что изучать:
- Глубже
sqlx: compile-time проверка запросов черезquery!/query_as!, миграции черезsqlx-cliилиrefinery. - ORM vs query-builder:
diesel(классический type-safe ORM),sea-orm,sea-query(query builder без ORM-магии). - Connection pooling:
deadpool,bb8, встроенный пул вsqlx. - Embedded базы данных:
sled(LSM),redb(B-Tree, ACID),rocksdb,fjall. - Свой storage engine: B-Tree, LSM, WAL, MVCC. Полезный учебный путь — реализовать упрощённый Bitcask или LSM-engine.
- Векторные БД и поиск:
qdrant(vector DB, целиком на Rust),tantivy(полнотекстовый поиск, аналог Lucene).
Где изучать:
- Курс CMU 15-445 «Database Systems» — https://15445.courses.cs.cmu.edu/ (необязательно делать на C++, можно на Rust).
- «Database Internals» (Alex Petrov).
- Доки и блог Materialize и TiKV.
- Туториал «Build your own Redis» / «Build your own SQLite» на сайте codecrafters.io.
Зачем это нужно: Rust очень силён в storage-движках и БД (RocksDB-клиенты, TiKV, Materialize, Databend, Quickwit, Qdrant). Понимание устройства БД — топовый навык для любого backend-инженера.
Мини-проект:
- Напиши свой key-value движок с WAL, простейшим LSM или B-Tree, поддержкой транзакций.
- Сделай мини-аналог Elasticsearch на
tantivyс REST-API наaxum.
Что изучать:
- Цели компиляции:
wasm32-unknown-unknown(браузер/embedder без stdlib),wasm32-wasi/wasm32-wasip2(с системным API). - Component Model и WIT-интерфейсы — будущее композируемых WASM-модулей.
- WASM embedder'ы:
wasmtime,wasmer— как встраивать WASM-движок в свой Rust-сервис. - Plugin-системы на WASM:
extism— упрощённый фреймворк для расширений. - Frontend на Rust: сравнение
leptos,dioxus,yew,sycamore— signals vs vdom. - SSR, hydration, isomorphic functions — Leptos и Dioxus поддерживают это нативно.
- Edge-runtime: Cloudflare Workers (
workerкрейт), Fastly Compute, Vercel Edge.
Где изучать:
- «The
wasm-bindgenGuide» — https://rustwasm.github.io/wasm-bindgen/. - «Rust and WebAssembly» — https://rustwasm.github.io/docs/book/.
- Документация Leptos и Dioxus.
- Bytecode Alliance — https://bytecodealliance.org/ (WASI и Component Model).
Зачем это нужно: WASM — главная тема последних нескольких лет в Rust-экосистеме. Edge-вычисления, плагины, фронтенд, sandboxing — везде Rust + WASM становится дефолтным выбором.
Мини-проект:
- Сделай SPA на Leptos / Dioxus с SSR + hydration; задеплой на Cloudflare Workers или Fly.io.
- Встрой WASM-плагины в свой Rust-сервис через
wasmtime(например, пользовательские фильтры/трансформации).
Что изучать:
- Hardware Abstraction Layer:
embedded-hal1.0 как общий интерфейс; HAL-крейты для конкретных МК (stm32-hal,esp-hal,rp2040-hal,nrf-hal). - RTOS и async-фреймворки на embedded: Embassy (async-first, очень удобный) — де-факто стандарт для нового кода; RTIC (priority-based, без аллокатора).
- DMA, прерывания, критические секции через крейт
critical-section. - Эффективное логирование на МК:
defmt— компактный бинарный формат логов с decoding на хосте. - Отладка и прошивка:
probe-rs— единый инструмент для GDB/RTT/flashing/SWO. - Безопасность памяти на
no_std:heapless(Vec,String, очереди фиксированного размера), статическое выделение, отсутствие аллокатора.
Где изучать:
- The Embedded Rust Book — https://docs.rust-embedded.org/book/.
- Discovery Book (на STM32F3 Discovery) — https://docs.rust-embedded.org/discovery/.
- Документация Embassy — https://embassy.dev/book/.
- Канал Knurling-rs с туториалами по
defmt/probe-rs.
Зачем это нужно: Rust в embedded — одна из самых быстрорастущих ниш. Производители (Espressif, Nordic, ST) официально поддерживают Rust. Async на МК через Embassy реально удобен и отличается от классического C-подхода.
Мини-проект:
- Возьми ESP32 / RP2040 / STM32, напиши на Embassy прошивку, которая по Wi-Fi/BLE отдаёт данные с датчика.
- Реализуй простой PID-регулятор и управление шаговым мотором / сервоприводом через PWM + DMA.
Что изучать:
- ECS-движок Bevy: компоненты, системы, ресурсы, schedules, plugins. Идиоматический ECS на Rust.
- Шейдеры и графика: WGSL,
wgpuнапрямую (cross-API: Vulkan/Metal/DX12/WebGPU),nagaдля трансляции шейдеров. - Физика:
rapier(2D/3D физика),avian(нативная для Bevy). - Сетевой код для игр:
lightyear,bevy_replicon, client-side prediction, server reconciliation. - Альтернативные движки:
fyrox(бывший rg3d, классический сцен-граф),macroquad(быстрый старт для 2D),ggez. - Низкоуровневая графика:
vulkano,ash(raw Vulkan bindings).
Где изучать:
- The Bevy Book — https://bevyengine.org/learn/book/.
- The wgpu tutorial — https://sotrh.github.io/learn-wgpu/.
- «Learn OpenGL» (Joey de Vries) — переносится на wgpu один в один.
- YouTube-канал Logic Projects, разборы Bevy от Chris Biscardi.
Зачем это нужно: геймдев на Rust ещё не доминирует индустрию, но Bevy быстро становится зрелым. Это интересная ветка для тех, кто любит игры и графику, и при этом отличный стресс-тест продвинутой типовой системы и перформанса.
Мини-проект:
- Сделай 2D-платформер или top-down-шутер на Bevy с физикой через
avian. - Реализуй простой ray-tracer на
wgpucompute-шейдерах.
Что изучать:
- Tensor-фреймворки:
candle(HuggingFace, минималистичный, для inference),burn(гибкий, разные бэкенды: CPU / wgpu / CUDA / Metal). - Биндинги к C++ ML-стекам:
tch-rs— биндинги к LibTorch;ort— ONNX Runtime для inference. - Линейная алгебра и научка:
nalgebra(геометрия, графика),ndarray(numpy-подобный),faer(быстрый dense linalg). - Распараллеливание:
rayon(data parallelism), GPU черезcust(CUDA bindings) иcubecl(универсальный GPU compute). - LLM и inference:
mistral.rs,llama.cpp-биндинги, запуск open-weight моделей на Rust-стеке. - Эмбеддинги и vector search: связка
candle/ort+qdrant/tantivy.
Где изучать:
- Документация
candleиburn(с примерами). - Курс fast.ai (Python), но реализуй упражнения на Rust +
burn. - «Deep Learning» (Goodfellow et al.) — теоретический фундамент.
- Блог HuggingFace о
candle.
Зачем это нужно: Rust используется как infra-слой для ML-сервисов: токенизация, inference, vector search, серверы для моделей. Скорость и предсказуемая память делают его идеальным для production-ML, где Python-стек слишком тяжёл.
Мини-проект:
- Сделай локальный LLM-чат с inference на
candleилиmistral.rsи REST-API наaxum. - Реализуй semantic search: эмбеддинги через
candle+ индекс черезqdrantилиtantivy.
Что изучать:
- Workspaces, feature flags, conditional compilation. Как разбивать большой проект на крейты, не плодя дубликаты, и контролировать набор фич.
- Build scripts (
build.rs). Кодогенерация, биндинги черезbindgen/cxx, линковка с C/C++. - Полезные cargo-расширения:
cargo-make,cargo-nextest(быстрый параллельный тест-раннер),cargo-watch,cargo-expand(раскрытие макросов),cargo-udeps,cargo-machete(поиск неиспользуемых зависимостей),cargo-outdated. - Кросс-компиляция:
cross,cargo-zigbuild(черезzigкак линкер — отличный UX). - Минимизация бинарника: LTO (
lto = "fat"),panic = "abort",strip = true,opt-level = "z",codegen-units = 1. - Контейнеризация: distroless и scratch-образы, multi-stage builds, статически линкованные бинари (
x86_64-unknown-linux-musl). - CI/CD: GitHub Actions с
Swatinem/rust-cache, matrix-сборки, артефакты, релизы. - Релизы:
cargo-release,cargo-dist,release-plz(auto-PR с changelog). - Семвер и совместимость:
cargo-semver-checks.
Где изучать:
- The Cargo Book — https://doc.rust-lang.org/cargo/.
- «Zero To Production In Rust» (Luca Palmieri) — лучшая книга по практическому продакшну на Rust.
- Документация и README цитированных выше cargo-расширений.
- Блог
fasterthanli.me— про реальный продакшн на Rust.
Зачем это нужно: «работает на моей машине» в Rust — это ещё полпути до продакшна. Хороший DevEx (тесты, кросс-сборка, бинарники, релизы) экономит десятки часов и делает крейт привлекательным для контрибьюторов.
Мини-проект:
- Настрой полный CI для одного из своих крейтов: тесты на Linux/macOS/Windows,
cargo-deny,cargo-semver-checks, релизы черезcargo-dist. - Сделай Docker-образ <10 MB на musl + scratch.
Что изучать:
- RFC-процесс. Как предлагается изменение языка/стандартной библиотеки: https://github.com/rust-lang/rfcs. Прочитай несколько принятых и отклонённых RFC, чтобы понять стиль аргументации.
- Структура
rust-lang/rust: компилятор (rustc), стандартная библиотека (core/alloc/std),cargo,rustdoc,miri,clippy,rustfmt. - Внутренние представления компилятора: AST → HIR → THIR → MIR → LLVM IR. Каждый уровень решает свою задачу: парсинг, проверка типов, borrow checking, оптимизации.
- Borrow checker: старая версия (lexical lifetimes) → NLL (Non-Lexical Lifetimes) → Polonius — будущий движок на Datalog.
- Edition-механизм (2015 → 2018 → 2021 → 2024). Как Rust развивается без поломки совместимости.
- Информационные источники для core-разработки: «This Week in Rust», Inside Rust Blog, Rust Internals, Zulip-чаты команд (
compiler,lang,libs). - Менторство:
rustc-dev-guide— официальное руководство по разработке самого компилятора. ЛейблE-mentorв issue-трекереrust-lang/rust.
Где изучать:
- The
rustcDev Guide — https://rustc-dev-guide.rust-lang.org/. - The Rust Reference — https://doc.rust-lang.org/reference/.
- Доклады RustConf «What's new in rustc» и «Inside Polonius».
- Книги: «Rustc Codegen Cranelift», блог-посты Niko Matsakis.
Зачем это нужно: это вершина пути. Понимание устройства компилятора и языкового процесса делает тебя «Rust-инженером с большой буквы», даёт долгосрочное влияние на экосистему и открывает доступ к самым сложным и интересным задачам.
Мини-проект:
- Найди
E-mentorилиE-easyissue вrust-lang/rustилиrust-lang/cargo, сделай PR. - Напиши свой clippy-lint или мини-инструмент анализа на базе
rustc_driver/rustc_lint.
- Метакогнитивные навыки. Умение читать сообщения компилятора как документацию — половина продуктивности в Rust.
cargo expand,cargo asm, Rust Playground с просмотром MIR / LLVM IR — must-have для понимания, что реально происходит. - Чтение исходников в порядке возрастания сложности:
itertools→serde→tokio→hyper→rustc. Это даёт больше, чем десяток книг. - Сообщество. Rust Users Forum (users.rust-lang.org), Rust Internals, Discord/Zulip Rust, русскоязычный чат @rust_chats и группа ВК Rust IT. Ревью своего кода у опытных растовиков ускоряет рост на месяцы.
- Книги продвинутого уровня:
- Rust for Rustaceans — Jon Gjengset.
- Programming Rust — Blandy / Orendorff / Tindall (O'Reilly).
- Rust Atomics and Locks — Mara Bos (обязательна перед серьёзной многопоточкой).
- Zero To Production In Rust — Luca Palmieri (практика веб-сервисов).
- The Rustonomicon — для unsafe.
- YouTube: Jon Gjengset (стримы по внутренностям), fasterthanli.me (Amos), Logan Smith, No Boilerplate.
- Не пытайся выучить всё сразу. Rust большой: ownership, lifetimes, async, макросы, unsafe, типовая система. Если штурмовать всё параллельно — выгоришь. Двигайся по roadmap последовательно: каждый этап опирается на предыдущий.
- Пиши код каждый день, хотя бы 30 минут. Чтение книг и просмотр видео даёт иллюзию понимания. Реальное знание приходит только через борьбу с компилятором. Маленькие ежедневные коммиты сильнее редких марафонов.
- Доверяй компилятору. Сообщения об ошибках в Rust — это не препятствие, а самый честный учитель. Читай их полностью, переходи по ссылкам
--explain E0382, не игнорируй warnings от clippy. - Не борись с borrow checker — слушай его. Если код не компилируется, чаще всего проблема в архитектуре, а не в правилах языка. Перепиши структуру данных, разорви циклические зависимости, подумай о владении заранее.
- Решай задачи на Rustlings в самом начале — это 90+ маленьких упражнений, закрывающих базовый синтаксис. После них пройди Exercism Rust track с менторскими ревью.
- Читай официальную «The Rust Book» (rust-book.cs.brown.edu — версия с интерактивными квизами). Затем «Rust by Example» для практических паттернов.
- Используй
cargo clippyиcargo fmtс первого дня. Clippy подсказывает идиоматичные конструкции — это ускоряет переход от «пишу как на C++/Python» к «пишу как растовик». - Не клонируй ради тишины компилятора. Если возникает желание поставить
.clone()илиArc<Mutex<_>>— остановись. Чаще всего нужно поменять сигнатуру (&strвместоString, итератор вместоVec) или переосмыслить владение. - Объясняй код вслух (rubber duck debugging). Проговаривание «здесь у меня владелец, здесь заёмщик, время жизни
'aсвязано с...» закрепляет ментальную модель быстрее, чем чтение.
- Делай pet-проекты, а не туториалы. Туториалы дают ложное чувство прогресса. Возьми идею, которую тебе реально хочется реализовать — CLI-утилиту, бота, парсер логов — и пиши её с нуля.
- Переписывай на Rust то, что уже знаешь. Если у тебя есть скрипт на Python или сервис на Go — перепиши его. Сравнение даст глубокое понимание различий в моделях памяти и абстракциях.
- Читай чужой код. Открывай исходники крейтов, которые используешь (
serde,tokio,clap) — даже без полного понимания. Постепенно паттерны станут узнаваемы. - Контрибьють в open-source раньше, чем кажется готовым. Найди issue с лейблом
good-first-issueилиE-easyв любом популярном крейте. Ревью от мейнтейнеров — лучший ускоритель роста.
- Принимай, что первые 1–3 месяца будут болезненными. Кривая обучения у Rust крутая в начале и пологая дальше. Это нормально. Все растовики проходили через стадию «ничего не компилируется».
- Учись думать в терминах типов, а не в терминах действий. Rust поощряет «сделай невалидное состояние непредставимым»: используй enum для состояний, newtype для разных единиц измерения, type-state для гарантий компиляции.
- Не путай «сложно» и «непривычно». Lifetimes выглядят страшно, но они описывают то, что в C++ существует неявно — просто Rust заставляет это записать. Через пару месяцев они станут естественной частью мышления.
- Сравнивай Rust осознанно. «В Go проще» или «в Haskell мощнее» — обе мысли верны и обе бесполезны. Rust выбирает компромисс между производительностью, безопасностью и эргономикой. Понимание этого компромисса важнее, чем выбор «лучшего языка».
- Не лезь в
unsafeи FFI слишком рано. Это мощные, но опасные инструменты. Освой safe Rust до автоматизма прежде, чем брать ответственность за инварианты, которые компилятор больше не проверяет. - Не начинай с async. Многие пытаются стартовать с
tokioи веб-серверов. Async добавляет ещё один слой сложности (Pin,Future, runtime) поверх и без того нетривиальной модели владения. Сначала — синхронный код, потоки, каналы. Async — после уверенного владения этапами 1–6. - Не увлекайся продвинутыми трейтами без необходимости. GAT, HRTB, type-state — мощные инструменты, но в 95% production-кода их не нужно. Сначала научись писать обычный идиоматичный Rust.
- Rustlings — упражнения по синтаксису.
- Exercism — задачи с ментор-ревью.
- Rust by Example — паттерны через примеры.
- Rust Playground — экспериментировать без
cargo new. - Advent of Code на Rust — отличная сезонная практика.
- Codewars и LeetCode на Rust — алгоритмические задачи.
- Rust Quiz — каверзные вопросы по семантике.
Нашли опечатку, неточность или хотите добавить пример? Открывайте issue или присылайте pull request.
Материалы курса распространяются под лицензией MIT. Используйте, копируйте, модифицируйте и распространяйте свободно.
